2
* Generic Dynamic compiler generator
4
* Copyright (c) 2003 Fabrice Bellard
6
* The COFF object format support was extracted from Kazu's QEMU port
9
* Mach-O Support by Matt Reda and Pierre d'Herbemont
11
* This program is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2 of the License, or
14
* (at your option) any later version.
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33
#include "config-host.h"
35
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
37
#if defined(CONFIG_WIN32)
38
#define CONFIG_FORMAT_COFF
39
#elif defined(CONFIG_DARWIN)
40
#define CONFIG_FORMAT_MACH
41
#elif defined(CONFIG_OS2)
42
#define CONFIG_FORMAT_AOUT
44
#define CONFIG_FORMAT_ELF
47
#ifdef CONFIG_FORMAT_ELF
49
/* elf format definitions. We use these macros to test the CPU to
50
allow cross compilation (this tool must be ran on the build
52
#if defined(HOST_I386)
54
#define ELF_CLASS ELFCLASS32
55
#define ELF_ARCH EM_386
56
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
57
#undef ELF_USES_RELOCA
59
#elif defined(HOST_X86_64)
61
#define ELF_CLASS ELFCLASS64
62
#define ELF_ARCH EM_X86_64
63
#define elf_check_arch(x) ((x) == EM_X86_64)
64
#define ELF_USES_RELOCA
66
#elif defined(HOST_PPC)
68
#define ELF_CLASS ELFCLASS32
69
#define ELF_ARCH EM_PPC
70
#define elf_check_arch(x) ((x) == EM_PPC)
71
#define ELF_USES_RELOCA
73
#elif defined(HOST_S390)
75
#define ELF_CLASS ELFCLASS32
76
#define ELF_ARCH EM_S390
77
#define elf_check_arch(x) ((x) == EM_S390)
78
#define ELF_USES_RELOCA
80
#elif defined(HOST_ALPHA)
82
#define ELF_CLASS ELFCLASS64
83
#define ELF_ARCH EM_ALPHA
84
#define elf_check_arch(x) ((x) == EM_ALPHA)
85
#define ELF_USES_RELOCA
87
#elif defined(HOST_IA64)
89
#define ELF_CLASS ELFCLASS64
90
#define ELF_ARCH EM_IA_64
91
#define elf_check_arch(x) ((x) == EM_IA_64)
92
#define ELF_USES_RELOCA
94
#elif defined(HOST_SPARC)
96
#define ELF_CLASS ELFCLASS32
97
#define ELF_ARCH EM_SPARC
98
#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
99
#define ELF_USES_RELOCA
101
#elif defined(HOST_SPARC64)
103
#define ELF_CLASS ELFCLASS64
104
#define ELF_ARCH EM_SPARCV9
105
#define elf_check_arch(x) ((x) == EM_SPARCV9)
106
#define ELF_USES_RELOCA
108
#elif defined(HOST_ARM)
110
#define ELF_CLASS ELFCLASS32
111
#define ELF_ARCH EM_ARM
112
#define elf_check_arch(x) ((x) == EM_ARM)
113
#define ELF_USES_RELOC
115
#elif defined(HOST_M68K)
117
#define ELF_CLASS ELFCLASS32
118
#define ELF_ARCH EM_68K
119
#define elf_check_arch(x) ((x) == EM_68K)
120
#define ELF_USES_RELOCA
123
#error unsupported CPU - please update the code
128
#if ELF_CLASS == ELFCLASS32
129
typedef int32_t host_long;
130
typedef uint32_t host_ulong;
131
#define swabls(x) swab32s(x)
132
#define swablss(x) swab32ss(x)
134
typedef int64_t host_long;
135
typedef uint64_t host_ulong;
136
#define swabls(x) swab64s(x)
137
#define swablss(x) swab64ss(x)
140
#ifdef ELF_USES_RELOCA
141
#define SHT_RELOC SHT_RELA
143
#define SHT_RELOC SHT_REL
146
#define EXE_RELOC ELF_RELOC
147
#define EXE_SYM ElfW(Sym)
149
#endif /* CONFIG_FORMAT_ELF */
151
#ifdef CONFIG_FORMAT_COFF
155
typedef int32_t host_long;
156
typedef uint32_t host_ulong;
158
#define FILENAMELEN 256
160
typedef struct coff_sym {
161
struct external_syment *st_syment;
162
char st_name[FILENAMELEN];
169
typedef struct coff_rel {
170
struct external_reloc *r_reloc;
175
#define EXE_RELOC struct coff_rel
176
#define EXE_SYM struct coff_sym
178
#endif /* CONFIG_FORMAT_COFF */
180
#ifdef CONFIG_FORMAT_MACH
182
#include <mach-o/loader.h>
183
#include <mach-o/nlist.h>
184
#include <mach-o/reloc.h>
185
#if !defined(HOST_I386)
186
#include <mach-o/ppc/reloc.h>
189
# define check_mach_header(x) (x.magic == MH_MAGIC)
190
typedef int32_t host_long;
191
typedef uint32_t host_ulong;
193
struct nlist_extended
199
unsigned char n_type;
200
unsigned char n_sect;
202
unsigned long st_value;
203
unsigned long st_size;
206
#define EXE_RELOC struct relocation_info
207
#define EXE_SYM struct nlist_extended
208
#if defined(HOST_I386)
209
# define r_offset r_address
212
#endif /* CONFIG_FORMAT_MACH */
214
#ifdef CONFIG_FORMAT_AOUT
218
typedef int32_t host_long;
219
typedef uint32_t host_ulong;
221
struct nlist_extended
225
struct nlist *n_next;
228
unsigned char n_type;
231
unsigned long st_value; /* n_value -> st_value */
232
unsigned long st_size; /* added */
235
#define EXE_RELOC struct relocation_info
236
#define EXE_SYM struct nlist_extended
237
#define r_offset r_address
239
#endif /* CONFIG_FORMAT_AOUT */
249
/* all dynamically generated functions begin with this code */
250
#define OP_PREFIX "op_"
254
void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
258
fprintf(stderr, "dyngen: ");
259
vfprintf(stderr, fmt, ap);
260
fprintf(stderr, "\n");
265
void *load_data(int fd, long offset, unsigned int size)
272
lseek(fd, offset, SEEK_SET);
273
if (read(fd, data, size) != size) {
280
int strstart(const char *str, const char *val, const char **ptr)
296
void pstrcpy(char *buf, int buf_size, const char *str)
306
if (c == 0 || q >= buf + buf_size - 1)
313
void swab16s(uint16_t *p)
318
void swab32s(uint32_t *p)
323
void swab32ss(int32_t *p)
328
void swab64s(uint64_t *p)
333
void swab64ss(int64_t *p)
338
uint16_t get16(uint16_t *p)
347
uint32_t get32(uint32_t *p)
356
void put16(uint16_t *p, uint16_t val)
363
void put32(uint32_t *p, uint32_t val)
370
/* executable information */
378
#ifdef CONFIG_FORMAT_ELF
381
struct elf_shdr *shdr;
386
int elf_must_swap(struct elfhdr *h)
394
return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
395
(swaptest.b[0] == 0);
398
void elf_swap_ehdr(struct elfhdr *h)
400
swab16s(&h->e_type); /* Object file type */
401
swab16s(&h-> e_machine); /* Architecture */
402
swab32s(&h-> e_version); /* Object file version */
403
swabls(&h-> e_entry); /* Entry point virtual address */
404
swabls(&h-> e_phoff); /* Program header table file offset */
405
swabls(&h-> e_shoff); /* Section header table file offset */
406
swab32s(&h-> e_flags); /* Processor-specific flags */
407
swab16s(&h-> e_ehsize); /* ELF header size in bytes */
408
swab16s(&h-> e_phentsize); /* Program header table entry size */
409
swab16s(&h-> e_phnum); /* Program header table entry count */
410
swab16s(&h-> e_shentsize); /* Section header table entry size */
411
swab16s(&h-> e_shnum); /* Section header table entry count */
412
swab16s(&h-> e_shstrndx); /* Section header string table index */
415
void elf_swap_shdr(struct elf_shdr *h)
417
swab32s(&h-> sh_name); /* Section name (string tbl index) */
418
swab32s(&h-> sh_type); /* Section type */
419
swabls(&h-> sh_flags); /* Section flags */
420
swabls(&h-> sh_addr); /* Section virtual addr at execution */
421
swabls(&h-> sh_offset); /* Section file offset */
422
swabls(&h-> sh_size); /* Section size in bytes */
423
swab32s(&h-> sh_link); /* Link to another section */
424
swab32s(&h-> sh_info); /* Additional section information */
425
swabls(&h-> sh_addralign); /* Section alignment */
426
swabls(&h-> sh_entsize); /* Entry size if section holds table */
429
void elf_swap_phdr(struct elf_phdr *h)
431
swab32s(&h->p_type); /* Segment type */
432
swabls(&h->p_offset); /* Segment file offset */
433
swabls(&h->p_vaddr); /* Segment virtual address */
434
swabls(&h->p_paddr); /* Segment physical address */
435
swabls(&h->p_filesz); /* Segment size in file */
436
swabls(&h->p_memsz); /* Segment size in memory */
437
swab32s(&h->p_flags); /* Segment flags */
438
swabls(&h->p_align); /* Segment alignment */
441
void elf_swap_rel(ELF_RELOC *rel)
443
swabls(&rel->r_offset);
444
swabls(&rel->r_info);
445
#ifdef ELF_USES_RELOCA
446
swablss(&rel->r_addend);
450
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
455
struct elf_shdr *sec;
457
for(i = 0; i < shnum; i++) {
461
shname = shstr + sec->sh_name;
462
if (!strcmp(shname, name))
468
int find_reloc(int sh_index)
470
struct elf_shdr *sec;
473
for(i = 0; i < ehdr.e_shnum; i++) {
475
if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
481
static host_ulong get_rel_offset(EXE_RELOC *rel)
483
return rel->r_offset;
486
static char *get_rel_sym_name(EXE_RELOC *rel)
488
return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
491
static char *get_sym_name(EXE_SYM *sym)
493
return strtab + sym->st_name;
496
/* load an elf object file */
497
int load_object(const char *filename)
500
struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
506
fd = open(filename, O_RDONLY
512
error("can't open file '%s'", filename);
514
/* Read ELF header. */
515
if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
516
error("unable to read file header");
518
/* Check ELF identification. */
519
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
520
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
521
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
522
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
523
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
524
error("bad ELF header");
527
do_swap = elf_must_swap(&ehdr);
529
elf_swap_ehdr(&ehdr);
530
if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
531
error("Unsupported ELF class (%#x)", ehdr.e_ident[EI_CLASS]);
532
if (ehdr.e_type != ET_REL)
533
error("ELF object file expected");
534
if (ehdr.e_version != EV_CURRENT)
535
error("Invalid ELF version");
536
if (!elf_check_arch(ehdr.e_machine))
537
error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
539
/* read section headers */
540
shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
542
for(i = 0; i < ehdr.e_shnum; i++) {
543
elf_swap_shdr(&shdr[i]);
547
/* read all section data */
548
sdata = malloc(sizeof(void *) * ehdr.e_shnum);
549
memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
551
for(i = 0;i < ehdr.e_shnum; i++) {
553
if (sec->sh_type != SHT_NOBITS)
554
sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
557
sec = &shdr[ehdr.e_shstrndx];
558
shstr = (char *)sdata[ehdr.e_shstrndx];
560
/* swap relocations */
561
for(i = 0; i < ehdr.e_shnum; i++) {
563
if (sec->sh_type == SHT_RELOC) {
564
nb_relocs = sec->sh_size / sec->sh_entsize;
566
for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
573
text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
575
error("could not find .text section");
576
text_shndx = text_sec - shdr;
577
text = sdata[text_shndx];
579
/* find text relocations, if any */
582
i = find_reloc(text_shndx);
584
relocs = (ELF_RELOC *)sdata[i];
585
nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
588
symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
590
error("could not find .symtab section");
591
strtab_sec = &shdr[symtab_sec->sh_link];
593
symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
594
strtab = (char *)sdata[symtab_sec->sh_link];
596
nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
598
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
599
swab32s(&sym->st_name);
600
swabls(&sym->st_value);
601
swabls(&sym->st_size);
602
swab16s(&sym->st_shndx);
609
#endif /* CONFIG_FORMAT_ELF */
611
#ifdef CONFIG_FORMAT_COFF
614
struct external_scnhdr *shdr;
616
struct external_filehdr fhdr;
617
struct external_syment *coff_symtab;
619
int coff_text_shndx, coff_data_shndx;
623
#define STRTAB_SIZE 4
628
#define T_FUNCTION 0x20
631
void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
636
if (ext_sym->e.e.e_zeroes != 0) {
638
for(i = 0; i < 8; i++) {
639
c = ext_sym->e.e_name[i];
646
pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
649
/* now convert the name to a C name (suppress the leading '_') */
650
if (sym->st_name[0] == '_') {
651
len = strlen(sym->st_name);
652
memmove(sym->st_name, sym->st_name + 1, len - 1);
653
sym->st_name[len - 1] = '\0';
657
char *name_for_dotdata(struct coff_rel *rel)
660
struct coff_sym *sym;
663
text_data = *(uint32_t *)(text + rel->r_offset);
665
for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
666
if (sym->st_syment->e_scnum == data_shndx &&
667
text_data >= sym->st_value &&
668
text_data < sym->st_value + sym->st_size) {
677
static char *get_sym_name(EXE_SYM *sym)
682
static char *get_rel_sym_name(EXE_RELOC *rel)
685
name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
686
if (!strcmp(name, ".data"))
687
name = name_for_dotdata(rel);
693
static host_ulong get_rel_offset(EXE_RELOC *rel)
695
return rel->r_offset;
698
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
702
struct external_scnhdr *sec;
704
for(i = 0; i < shnum; i++) {
708
shname = sec->s_name;
709
if (!strcmp(shname, name))
715
/* load a coff object file */
716
int load_object(const char *filename)
719
struct external_scnhdr *sec, *text_sec, *data_sec;
721
struct external_syment *ext_sym;
722
struct external_reloc *coff_relocs;
723
struct external_reloc *ext_rel;
728
fd = open(filename, O_RDONLY
734
error("can't open file '%s'", filename);
736
/* Read COFF header. */
737
if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
738
error("unable to read file header");
740
/* Check COFF identification. */
741
if (fhdr.f_magic != I386MAGIC) {
742
error("bad COFF header");
746
/* read section headers */
747
shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
749
/* read all section data */
750
sdata = malloc(sizeof(void *) * fhdr.f_nscns);
751
memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
754
for(i = 0;i < fhdr.f_nscns; i++) {
756
if (!strstart(sec->s_name, ".bss", &p))
757
sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
762
text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
764
error("could not find .text section");
765
coff_text_shndx = text_sec - shdr;
766
text = sdata[coff_text_shndx];
769
data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
771
error("could not find .data section");
772
coff_data_shndx = data_sec - shdr;
774
coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
775
for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
777
printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
782
n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
783
strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
785
nb_syms = fhdr.f_nsyms;
787
for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
788
if (strstart(ext_sym->e.e_name, ".text", NULL))
789
text_shndx = ext_sym->e_scnum;
790
if (strstart(ext_sym->e.e_name, ".data", NULL))
791
data_shndx = ext_sym->e_scnum;
794
/* set coff symbol */
795
symtab = malloc(sizeof(struct coff_sym) * nb_syms);
798
for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
799
memset(sym, 0, sizeof(*sym));
800
sym->st_syment = ext_sym;
801
sym_ent_name(ext_sym, sym);
802
sym->st_value = ext_sym->e_value;
804
aux_size = *(int8_t *)ext_sym->e_numaux;
805
if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
806
for (j = aux_size + 1; j < nb_syms - i; j++) {
807
if ((ext_sym + j)->e_scnum == text_shndx &&
808
(ext_sym + j)->e_type == T_FUNCTION ){
809
sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
811
} else if (j == nb_syms - i - 1) {
812
sec = &shdr[coff_text_shndx];
813
sym->st_size = sec->s_size - ext_sym->e_value;
817
} else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
818
for (j = aux_size + 1; j < nb_syms - i; j++) {
819
if ((ext_sym + j)->e_scnum == data_shndx) {
820
sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
822
} else if (j == nb_syms - i - 1) {
823
sec = &shdr[coff_data_shndx];
824
sym->st_size = sec->s_size - ext_sym->e_value;
832
sym->st_type = ext_sym->e_type;
833
sym->st_shndx = ext_sym->e_scnum;
837
/* find text relocations, if any */
838
sec = &shdr[coff_text_shndx];
839
coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
840
nb_relocs = sec->s_nreloc;
842
/* set coff relocation */
843
relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
844
for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
845
i++, ext_rel++, rel++) {
846
memset(rel, 0, sizeof(*rel));
847
rel->r_reloc = ext_rel;
848
rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
849
rel->r_type = *(uint16_t *)ext_rel->r_type;
854
#endif /* CONFIG_FORMAT_COFF */
856
#ifdef CONFIG_FORMAT_MACH
859
struct mach_header mach_hdr;
862
struct segment_command *segment = 0;
863
struct dysymtab_command *dysymtabcmd = 0;
864
struct symtab_command *symtabcmd = 0;
867
struct section *section_hdr;
868
struct section *text_sec_hdr;
872
struct relocation_info *relocs;
876
struct nlist *symtab_std;
879
/* indirect symbols */
882
/* Utility functions */
884
static inline char *find_str_by_index(int index)
889
/* Used by dyngen common code */
890
static char *get_sym_name(EXE_SYM *sym)
892
char *name = find_str_by_index(sym->n_un.n_strx);
894
if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
905
/* find a section index given its segname, sectname */
906
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
907
const char *sectname)
910
struct section *sec = section_hdr;
912
for(i = 0; i < shnum; i++, sec++) {
913
if (!sec->segname || !sec->sectname)
915
if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
921
/* find a section header given its segname, sectname */
922
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
923
const char *sectname)
925
int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
928
return section_hdr+index;
932
#if defined(HOST_PPC)
933
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
935
struct scattered_relocation_info * scarel;
937
if(R_SCATTERED & rel->r_address) {
938
scarel = (struct scattered_relocation_info*)rel;
939
if(scarel->r_type != PPC_RELOC_PAIR)
940
error("fetch_next_pair_value: looking for a pair which was not found (1)");
941
*value = scarel->r_value;
943
if(rel->r_type != PPC_RELOC_PAIR)
944
error("fetch_next_pair_value: looking for a pair which was not found (2)");
945
*value = rel->r_address;
950
/* find a sym name given its value, in a section number */
951
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
955
for( i = 0 ; i < nb_syms; i++ )
957
if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
958
(symtab[i].n_sect == sectnum) && (symtab[i].st_value <= value) )
960
if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
968
*offset = value - symtab[ret].st_value;
969
return get_sym_name(&symtab[ret]);
974
* Find symbol name given a (virtual) address, and a section which is of type
975
* S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
977
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
979
unsigned int tocindex, symindex, size;
980
const char *name = 0;
983
if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
986
if( sec_hdr->flags & S_SYMBOL_STUBS ){
987
size = sec_hdr->reserved2;
992
else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
993
sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
994
size = sizeof(unsigned long);
998
/* Compute our index in toc */
999
tocindex = (address - sec_hdr->addr)/size;
1000
symindex = tocdylib[sec_hdr->reserved1 + tocindex];
1002
name = get_sym_name(&symtab[symindex]);
1007
static const char * find_reloc_name_given_its_address(int address)
1010
for(i = 0; i < segment->nsects ; i++)
1012
const char * name = find_reloc_name_in_sec_ptr(address, §ion_hdr[i]);
1013
if((long)name != -1)
1019
static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
1022
struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1023
int sectnum = rel->r_symbolnum;
1027
/* init the slide value */
1030
if(R_SCATTERED & rel->r_address)
1031
return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1035
/* ignore debug sym */
1036
if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1038
return get_sym_name(&symtab[rel->r_symbolnum]);
1041
#if defined(HOST_I386)
1042
/* ignore internal pc relative fixups where both ends are in the text section. */
1043
if (rel->r_pcrel && !rel->r_extern && rel->r_symbolnum == 1 /* ASSUMES text */)
1047
/* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1048
sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1050
if(sectnum==0xffffff)
1054
if(sectnum > segment->nsects)
1055
error("sectnum > segment->nsects");
1057
#if defined(HOST_PPC)
1060
case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1062
case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1064
case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1066
case PPC_RELOC_BR24:
1067
sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1068
if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1071
error("switch(rel->type) not found");
1073
#elif defined(HOST_I386)
1074
/* The intruction contains the addend. */
1075
sectoffset = *(uint32_t *)(text + rel->r_address);
1077
#error unsupported mach-o host
1081
sectoffset += rel->r_address;
1083
#if defined(HOST_PPC)
1084
if (rel->r_type == PPC_RELOC_BR24)
1085
name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, §ion_hdr[sectnum-1]);
1088
/* search it in the full symbol list, if not found */
1090
name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1095
#if defined(HOST_I386)
1096
static const char *get_rel_sym_name_and_addend(EXE_RELOC *rel, int *addend)
1098
const char *name = NULL;
1100
if (R_SCATTERED & rel->r_address) {
1102
struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1103
if (sca_rel->r_length != 2 || rel->r_pcrel) {
1104
error("Fully implement R_SCATTERED! r_address=%#x r_type=%#x r_length=%d r_pcrel=%d r_value=%#x\n",
1105
(int)sca_rel->r_address, sca_rel->r_type, sca_rel->r_length, sca_rel->r_pcrel, sca_rel->r_value);
1108
/* this seems to be the way to calc the addend. */
1109
*addend = *(int32_t *)(text + sca_rel->r_address) - sca_rel->r_value;
1111
/* todo: do we need to ignore internal relocations? */
1113
if (sca_rel->r_pcrel ...)
1117
/* find_reloc_name_given_its_address doesn't do the right thing here, so
1118
we locate the section and use find_sym_with_value_and_sec_number */
1119
for (i = 0; i < segment->nsects ; i++) {
1120
if ((uintptr_t)sca_rel->r_value - section_hdr[i].addr < section_hdr[i].size) {
1122
name = find_sym_with_value_and_sec_number(sca_rel->r_value, i + 1, &off);
1130
error("Fully implement R_SCATTERED! r_address=%#x r_type=%#x r_length=%d r_pcrel=%d r_value=%#x\n",
1131
(int)sca_rel->r_address, sca_rel->r_type, sca_rel->r_length, sca_rel->r_pcrel, sca_rel->r_value);
1135
/* ignore debug syms (paranoia). */
1136
if (symtab[rel->r_symbolnum].n_type & N_STAB)
1139
/* ignore internal pc relative fixups where both ends are in the text section. */
1140
if (rel->r_pcrel && !rel->r_extern && rel->r_symbolnum == 1 /* ASSUMES text */)
1143
/* get the addend, it is in the instruction stream. */
1144
*addend = *(int32_t *)(text + rel->r_address);
1146
*addend += rel->r_address;
1148
/* external fixups are easy. */
1151
if (rel->r_symbolnum >= nb_syms)
1152
error("rel->r_symbolnum (%d) >= nb_syms (%d)", rel->r_symbolnum, nb_syms);
1153
name = get_sym_name(&symtab[rel->r_symbolnum]);
1157
/* sanity checks. */
1158
if (rel->r_symbolnum == 0xffffff)
1160
if (rel->r_symbolnum > segment->nsects)
1161
error("sectnum (%d) > segment->nsects (%d)", rel->r_symbolnum, segment->nsects);
1163
error("internal pcrel fixups not implemented");
1165
/* search for the symbol. */
1166
name = find_sym_with_value_and_sec_number(*addend, rel->r_symbolnum, addend);
1171
#endif /* HOST_I386 */
1173
/* Used by dyngen common code */
1174
static const char * get_rel_sym_name(EXE_RELOC * rel)
1177
#if defined(HOST_I386)
1178
return get_rel_sym_name_and_addend(rel, &sslide);
1180
return get_reloc_name( rel, &sslide);
1184
/* Used by dyngen common code */
1185
static host_ulong get_rel_offset(EXE_RELOC *rel)
1187
struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1188
if(R_SCATTERED & rel->r_address)
1189
return sca_rel->r_address;
1191
return rel->r_address;
1194
/* load a mach-o object file */
1195
int load_object(const char *filename)
1198
unsigned int offset_to_segment = 0;
1199
unsigned int offset_to_dysymtab = 0;
1200
unsigned int offset_to_symtab = 0;
1201
struct load_command lc;
1204
struct nlist *syment;
1206
fd = open(filename, O_RDONLY
1212
error("can't open file '%s'", filename);
1214
/* Read Mach header. */
1215
if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1216
error("unable to read file header");
1218
/* Check Mach identification. */
1219
if (!check_mach_header(mach_hdr)) {
1220
error("bad Mach header");
1223
#if defined(HOST_PPC)
1224
if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1225
#elif defined(HOST_I386)
1226
if (mach_hdr.cputype != CPU_TYPE_X86)
1228
#error unsupported host
1230
error("Unsupported CPU");
1232
if (mach_hdr.filetype != MH_OBJECT)
1233
error("Unsupported Mach Object");
1235
/* read segment headers */
1236
for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1238
if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1239
error("unable to read load_command");
1240
if(lc.cmd == LC_SEGMENT)
1242
offset_to_segment = j;
1243
lseek(fd, offset_to_segment, SEEK_SET);
1244
segment = malloc(sizeof(struct segment_command));
1245
if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1246
error("unable to read LC_SEGMENT");
1248
if(lc.cmd == LC_DYSYMTAB)
1250
offset_to_dysymtab = j;
1251
lseek(fd, offset_to_dysymtab, SEEK_SET);
1252
dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1253
if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1254
error("unable to read LC_DYSYMTAB");
1256
if(lc.cmd == LC_SYMTAB)
1258
offset_to_symtab = j;
1259
lseek(fd, offset_to_symtab, SEEK_SET);
1260
symtabcmd = malloc(sizeof(struct symtab_command));
1261
if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1262
error("unable to read LC_SYMTAB");
1266
lseek(fd, j, SEEK_SET);
1270
error("unable to find LC_SEGMENT");
1272
/* read section headers */
1273
section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1275
/* read all section data */
1276
sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1277
memset(sdata, 0, sizeof(void *) * segment->nsects);
1279
/* Load the data in section data */
1280
for(i = 0; i < segment->nsects; i++) {
1281
sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1285
text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1286
i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1287
if (i == -1 || !text_sec_hdr)
1288
error("could not find __TEXT,__text section");
1291
/* Make sure dysym was loaded */
1292
if(!(int)dysymtabcmd)
1293
error("could not find __DYSYMTAB segment");
1295
/* read the table of content of the indirect sym */
1296
tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1298
/* Make sure symtab was loaded */
1300
error("could not find __SYMTAB segment");
1301
nb_syms = symtabcmd->nsyms;
1303
symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1304
strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1306
symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1308
/* Now transform the symtab, to an extended version, with the sym size, and the C name */
1309
for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1310
struct nlist *sym_cur, *sym_next = 0;
1312
memset(sym, 0, sizeof(*sym));
1314
if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1317
memcpy(sym, syment, sizeof(*syment));
1320
/* don't bother calcing size of internal symbol local symbols. */
1321
if (strstart(find_str_by_index(sym->n_un.n_strx), ".L", NULL)) {
1327
/* Find the following symbol in order to get the current symbol size */
1328
for (j = 0, sym_cur = symtab_std; j < nb_syms; j++, sym_cur++) {
1329
if ( sym_cur->n_sect != /*syment->n_sect*/ 1
1330
|| (sym_cur->n_type & N_STAB)
1331
|| sym_cur->n_value <= syment->n_value)
1334
&& sym_next->n_value <= sym_cur->n_value)
1336
#if defined(HOST_I386)
1337
/* Ignore local labels (.Lxxx). */
1338
if (strstart(find_str_by_index(sym_cur->n_un.n_strx), ".L", NULL))
1345
sym->st_size = sym_next->n_value - sym->st_value;
1347
sym->st_size = text_sec_hdr->size - sym->st_value;
1351
relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1352
nb_relocs = text_sec_hdr->nreloc;
1358
#endif /* CONFIG_FORMAT_MACH */
1360
#ifdef CONFIG_FORMAT_AOUT
1362
struct exec *aout_hdr;
1363
struct nlist *symtab_std;
1367
/* Utility functions */
1369
static inline char *find_str_by_index(int index)
1371
return strtab+index;
1374
/* Used by dyngen common code */
1375
static char *get_sym_name(EXE_SYM *sym)
1377
char *name = find_str_by_index(sym->n_un.n_strx);
1379
if (sym->n_type & N_STAB) /* Debug symbols are ignored */
1381
if (name && name[0] == '_')
1386
static int type_to_sec_number(unsigned type)
1390
case 0: case 0 |N_EXT: case N_WEAKU: return N_UNDF;
1391
case N_ABS: case N_ABS |N_EXT: case N_WEAKA: return N_ABS;
1392
case N_TEXT: case N_TEXT|N_EXT: case N_WEAKT: return N_TEXT;
1393
case N_DATA: case N_DATA|N_EXT: case N_WEAKD: return N_DATA;
1394
case N_BSS: case N_BSS |N_EXT: case N_WEAKB: return N_BSS;
1395
case N_SETA: case N_SETA|N_EXT: return N_SETA;
1396
case N_SETT: case N_SETT|N_EXT: return N_SETT;
1397
case N_SETD: case N_SETD|N_EXT: return N_SETD;
1404
/* find a sym name given its value, in a section number */
1405
static const char *find_sym_with_value_and_sec_number(long value, int sec, int *offset)
1409
for (i = 0; i < nb_syms; i++) {
1410
if ( !(symtab[i].n_type & N_STAB)
1411
&& type_to_sec_number(symtab[i].n_type) == sec
1412
&& symtab[i].st_value <= value
1414
|| symtab[i].st_value >= symtab[ret].st_value)) {
1422
*offset = value - symtab[ret].st_value;
1423
return get_sym_name(&symtab[ret]);
1426
static const char *get_rel_sym_name_and_addend(EXE_RELOC *rel, int *sslide)
1435
/* ignore debug sym */
1436
if (symtab[rel->r_symbolnum].n_type & N_STAB)
1439
/* The intruction contains the addend. */
1440
off = *(uint32_t *)(text + rel->r_address);
1442
off += rel->r_address;
1444
return get_sym_name(&symtab[rel->r_symbolnum]);
1446
if (rel->r_symbolnum == 0xffffff)
1449
sec = rel->r_symbolnum & ~N_EXT;
1453
case N_TEXT: case N_DATA: case N_BSS: case N_ABS: break;
1454
default: error("invalid section %d", sec);
1457
/* The intruction contains the addend. */
1458
off = *(uint32_t *)(text + rel->r_address);
1460
off += rel->r_address;
1462
/* search it in the full symbol list, if not found */
1463
return find_sym_with_value_and_sec_number(off, sec, sslide);
1466
/* Used by dyngen common code */
1467
static const char * get_rel_sym_name(EXE_RELOC *rel)
1470
return get_rel_sym_name_and_addend(rel, &ignored);
1473
/* Used by dyngen common code */
1474
static host_ulong get_rel_offset(EXE_RELOC *rel)
1476
return rel->r_address;
1479
/* load an a.out object file */
1480
int load_object(const char *filename)
1486
struct nlist *src_sym;
1489
* Open the file and validate the header.
1491
pf = fopen(filename, "rb");
1493
error("can't open file '%s'", filename);
1495
/* we're optimistic, read the entire file first. */
1496
if (fseek(pf, 0, SEEK_END) != 0)
1497
error("Input file '%s' is not seekable", filename);
1498
file_size = ftell(pf);
1499
fseek(pf, 0L, SEEK_SET);
1501
aout_hdr = malloc(file_size + 1);
1503
error("malloc(%ld) failed", file_size + 1);
1504
if (fread(aout_hdr, 1, file_size, pf) != file_size)
1505
error("error reading '%s'", filename);
1508
/* validate the header. */
1509
if (N_MAGIC(*aout_hdr) != OMAGIC)
1510
error("unknown magic: %lo", N_MAGIC(*aout_hdr));
1511
if (N_MACHTYPE(*aout_hdr) != M_386 && N_MACHTYPE(*aout_hdr) != 0)
1512
error("unsupported machtype: %d", N_MACHTYPE(*aout_hdr));
1514
/* setup globals. */
1515
strtab = (char *)((uint8_t *)aout_hdr + N_STROFF(*aout_hdr));
1516
symtab_std = (struct nlist *)((uint8_t *)aout_hdr + N_SYMOFF(*aout_hdr));
1518
relocs = (struct relocation_info *)((uint8_t *)aout_hdr + N_TRELOFF(*aout_hdr));
1519
nb_syms = aout_hdr->a_syms / sizeof(struct nlist);
1521
text = (uint8_t *)aout_hdr + N_TXTOFF(*aout_hdr);
1522
nb_relocs = aout_hdr->a_trsize / sizeof(relocs[0]);
1525
* Now transform the symtab, to an extended version, with the sym size, and the C name
1527
src_sym = symtab_std;
1528
dst_sym = symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1530
error("malloc(%zd) failed", sizeof(EXE_SYM) * nb_syms);
1531
for (i = 0; i < nb_syms; i++, src_sym++, dst_sym++) {
1532
struct nlist *sym_next = NULL;
1533
struct nlist *sym_cur;
1537
/* copy the symbol and find the name. */
1538
dst_sym->n_un.n_strx = src_sym->n_un.n_strx;
1539
dst_sym->n_type = src_sym->n_type;
1540
dst_sym->n_other = src_sym->n_other;
1541
dst_sym->n_desc = src_sym->n_desc;
1542
dst_sym->st_value = src_sym->n_value;
1543
dst_sym->st_size = 0;
1544
if (src_sym->n_type & N_STAB)
1545
continue; /* skip debug symbols. */
1547
/* Find the following symbol in order to get the current symbol size */
1548
sec = type_to_sec_number(dst_sym->n_type);
1549
for (j = 0, sym_cur = symtab_std; j < nb_syms; j++, sym_cur++) {
1550
if ( type_to_sec_number(sym_cur->n_type) != sec
1551
|| (sym_cur->n_type & N_STAB)
1552
|| sym_cur->n_value <= dst_sym->st_value)
1555
&& sym_next->n_value <= sym_cur->n_value)
1561
dst_sym->st_size = sym_next->n_value - dst_sym->st_value;
1563
dst_sym->st_size = aout_hdr->a_text - dst_sym->st_value;
1569
#endif /* CONFIG_FORMAT_AOUT */
1572
void get_reloc_expr(char *name, int name_size, const char *sym_name)
1576
if (strstart(sym_name, "__op_param", &p)) {
1577
snprintf(name, name_size, "param%s", p);
1578
} else if (strstart(sym_name, "__op_gen_label", &p)) {
1579
snprintf(name, name_size, "gen_labels[param%s]", p);
1582
if (sym_name[0] == '.')
1583
snprintf(name, name_size,
1584
"(long)(&__dot_%s)",
1588
snprintf(name, name_size, "(long)(&%s)", sym_name);
1594
#define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1597
struct plt_entry *next;
1599
unsigned long addend;
1603
get_plt_index (const char *name, unsigned long addend)
1605
struct plt_entry *plt, *prev= NULL;
1608
/* see if we already have an entry for this target: */
1609
for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1610
if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1613
/* nope; create a new PLT entry: */
1615
plt = malloc(sizeof(*plt));
1620
memset(plt, 0, sizeof(*plt));
1621
plt->name = strdup(name);
1622
plt->addend = addend;
1624
/* append to plt-list: */
1636
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1637
FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1638
ELF_RELOC *relocs, int nb_relocs)
1642
int offset, min_offset, pc_offset, data_size, spare, max_pool;
1643
uint8_t data_allocated[1024];
1644
unsigned int data_index;
1647
memset(data_allocated, 0, sizeof(data_allocated));
1650
min_offset = p_end - p_start;
1652
while (p < p_start + min_offset) {
1653
insn = get32((uint32_t *)p);
1654
/* TODO: Armv5e ldrd. */
1655
/* TODO: VFP load. */
1656
if ((insn & 0x0d5f0000) == 0x051f0000) {
1657
/* ldr reg, [pc, #im] */
1658
offset = insn & 0xfff;
1659
if (!(insn & 0x00800000))
1663
} else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1665
offset = (insn & 0xff) << 2;
1666
if (!(insn & 0x00800000))
1670
} else if ((insn & 0x0fff0000) == 0x028f0000) {
1671
/* Some gcc load a doubleword immediate with
1673
ldmia regN, {regN, regM}
1674
Hope and pray the compiler never generates somethin like
1675
add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1678
r = (insn & 0xf00) >> 7;
1679
offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1687
/* PC-relative load needs fixing up. */
1688
if (spare > max_pool - offset)
1689
spare = max_pool - offset;
1690
if ((offset & 3) !=0)
1691
error("%s:%04x: pc offset must be 32 bit aligned",
1692
name, start_offset + p - p_start);
1694
error("%s:%04x: Embedded literal value",
1695
name, start_offset + p - p_start);
1696
pc_offset = p - p_start + offset + 8;
1697
if (pc_offset <= (p - p_start) ||
1698
pc_offset >= (p_end - p_start))
1699
error("%s:%04x: pc offset must point inside the function code",
1700
name, start_offset + p - p_start);
1701
if (pc_offset < min_offset)
1702
min_offset = pc_offset;
1704
/* The intruction position */
1705
fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1707
/* The position of the constant pool data. */
1708
data_index = ((p_end - p_start) - pc_offset) >> 2;
1709
fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1711
fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
1712
fprintf(outfile, " arm_ldr_ptr++;\n");
1718
/* Copy and relocate the constant pool data. */
1719
data_size = (p_end - p_start) - min_offset;
1720
if (data_size > 0 && outfile) {
1721
spare += min_offset;
1722
fprintf(outfile, " arm_data_ptr -= %d;\n", data_size >> 2);
1723
fprintf(outfile, " arm_pool_ptr -= %d;\n", data_size);
1724
fprintf(outfile, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1725
" arm_pool_ptr = gen_code_ptr + %d;\n",
1729
for (pc_offset = min_offset;
1730
pc_offset < p_end - p_start;
1734
int i, addend, type;
1735
const char *sym_name;
1739
addend = get32((uint32_t *)(p_start + pc_offset));
1741
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1742
if (rel->r_offset == (pc_offset + start_offset)) {
1743
sym_name = get_rel_sym_name(rel);
1744
/* the compiler leave some unnecessary references to the code */
1745
get_reloc_expr(relname, sizeof(relname), sym_name);
1746
type = ELF32_R_TYPE(rel->r_info);
1747
if (type != R_ARM_ABS32)
1748
error("%s: unsupported data relocation", name);
1752
fprintf(outfile, " arm_data_ptr[%d] = 0x%x",
1753
data_index, addend);
1754
if (relname[0] != '\0')
1755
fprintf(outfile, " + %s", relname);
1756
fprintf(outfile, ";\n");
1765
insn = get32((uint32_t *)p);
1766
/* The last instruction must be an ldm instruction. There are several
1767
forms generated by gcc:
1768
ldmib sp, {..., pc} (implies a sp adjustment of +4)
1770
ldmea fp, {..., pc} */
1771
if ((insn & 0xffff8000) == 0xe99d8000) {
1774
" *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1778
} else if ((insn & 0xffff8000) != 0xe89d8000
1779
&& (insn & 0xffff8000) != 0xe91b8000) {
1782
printf("%s: invalid epilog\n", name);
1791
/* generate op code */
1792
void gen_code(const char *name, host_ulong offset, host_ulong size,
1793
FILE *outfile, int gen_switch)
1796
uint8_t *p_start, *p_end;
1797
host_ulong start_offset;
1799
uint8_t args_present[MAX_ARGS];
1800
const char *sym_name, *p;
1803
/* Compute exact size excluding prologue and epilogue instructions.
1804
* Increment start_offset to skip epilogue instructions, then compute
1805
* copy_size the indicate the size of the remaining instructions (in
1808
p_start = text + offset;
1809
p_end = p_start + size;
1810
start_offset = offset;
1811
#if defined(HOST_I386) || defined(HOST_X86_64)
1812
#if defined(CONFIG_FORMAT_COFF) || defined(CONFIG_FORMAT_AOUT) || defined(CONFIG_FORMAT_MACH)
1817
error("empty code for %s", name);
1818
while (*p != 0xc3) {
1821
error("ret or jmp expected at the end of %s", name);
1823
copy_size = p - p_start;
1828
len = p_end - p_start;
1830
error("empty code for %s", name);
1831
if (p_end[-1] == 0xc3) {
1834
error("ret or jmp expected at the end of %s", name);
1839
#elif defined(HOST_PPC)
1842
p = (void *)(p_end - 4);
1844
error("empty code for %s", name);
1845
if (get32((uint32_t *)p) != 0x4e800020)
1846
error("blr expected at the end of %s", name);
1847
copy_size = p - p_start;
1849
#elif defined(HOST_S390)
1852
p = (void *)(p_end - 2);
1854
error("empty code for %s", name);
1855
if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
1856
error("br %%r14 expected at the end of %s", name);
1857
copy_size = p - p_start;
1859
#elif defined(HOST_ALPHA)
1864
/* XXX: check why it occurs */
1866
error("empty code for %s", name);
1868
if (get32((uint32_t *)p) != 0x6bfa8001)
1869
error("ret expected at the end of %s", name);
1870
copy_size = p - p_start;
1872
#elif defined(HOST_IA64)
1875
p = (void *)(p_end - 4);
1877
error("empty code for %s", name);
1878
/* br.ret.sptk.many b0;; */
1880
if (get32((uint32_t *)p) != 0x00840008)
1881
error("br.ret.sptk.many b0;; expected at the end of %s", name);
1882
copy_size = p_end - p_start;
1884
#elif defined(HOST_SPARC)
1886
#define INSN_SAVE 0x9de3a000
1887
#define INSN_RET 0x81c7e008
1888
#define INSN_RETL 0x81c3e008
1889
#define INSN_RESTORE 0x81e80000
1890
#define INSN_RETURN 0x81cfe008
1891
#define INSN_NOP 0x01000000
1892
#define INSN_ADD_SP 0x9c03a000 /* add %sp, nn, %sp */
1893
#define INSN_SUB_SP 0x9c23a000 /* sub %sp, nn, %sp */
1895
uint32_t start_insn, end_insn1, end_insn2;
1897
p = (void *)(p_end - 8);
1899
error("empty code for %s", name);
1900
start_insn = get32((uint32_t *)(p_start + 0x0));
1901
end_insn1 = get32((uint32_t *)(p + 0x0));
1902
end_insn2 = get32((uint32_t *)(p + 0x4));
1903
if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1904
(start_insn & ~0x1fff) == INSN_ADD_SP) {
1906
start_offset += 0x4;
1907
if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1908
/* SPARC v7: ret; restore; */ ;
1909
else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1910
/* SPARC v9: return; nop; */ ;
1911
else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1912
/* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1915
error("ret; restore; not found at end of %s", name);
1916
} else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1919
error("No save at the beginning of %s", name);
1922
/* Skip a preceeding nop, if present. */
1924
skip_insn = get32((uint32_t *)(p - 0x4));
1925
if (skip_insn == INSN_NOP)
1929
copy_size = p - p_start;
1931
#elif defined(HOST_SPARC64)
1933
#define INSN_SAVE 0x9de3a000
1934
#define INSN_RET 0x81c7e008
1935
#define INSN_RETL 0x81c3e008
1936
#define INSN_RESTORE 0x81e80000
1937
#define INSN_RETURN 0x81cfe008
1938
#define INSN_NOP 0x01000000
1939
#define INSN_ADD_SP 0x9c03a000 /* add %sp, nn, %sp */
1940
#define INSN_SUB_SP 0x9c23a000 /* sub %sp, nn, %sp */
1942
uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1944
p = (void *)(p_end - 8);
1946
/* XXX: check why it occurs */
1948
error("empty code for %s", name);
1950
start_insn = get32((uint32_t *)(p_start + 0x0));
1951
end_insn1 = get32((uint32_t *)(p + 0x0));
1952
end_insn2 = get32((uint32_t *)(p + 0x4));
1953
if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1954
(start_insn & ~0x1fff) == INSN_ADD_SP) {
1956
start_offset += 0x4;
1957
if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1958
/* SPARC v7: ret; restore; */ ;
1959
else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1960
/* SPARC v9: return; nop; */ ;
1961
else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1962
/* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1965
error("ret; restore; not found at end of %s", name);
1966
} else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1969
error("No save at the beginning of %s", name);
1972
/* Skip a preceeding nop, if present. */
1974
skip_insn = get32((uint32_t *)(p - 0x4));
1975
if (skip_insn == 0x01000000)
1979
copy_size = p - p_start;
1981
#elif defined(HOST_ARM)
1985
if ((p_end - p_start) <= 16)
1986
error("%s: function too small", name);
1987
if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1988
(get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1989
get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1990
error("%s: invalid prolog", name);
1993
insn = get32((uint32_t *)p_start);
1994
if ((insn & 0xffffff00) == 0xe24dd000) {
1995
/* Stack adjustment. Assume op uses the frame pointer. */
1999
copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
2002
#elif defined(HOST_M68K)
2005
p = (void *)(p_end - 2);
2007
error("empty code for %s", name);
2008
/* remove NOP's, probably added for alignment */
2009
while ((get16((uint16_t *)p) == 0x4e71) &&
2012
if (get16((uint16_t *)p) != 0x4e75)
2013
error("rts expected at the end of %s", name);
2014
copy_size = p - p_start;
2017
#error unsupported CPU
2020
/* compute the number of arguments by looking at the relocations */
2021
for(i = 0;i < MAX_ARGS; i++)
2022
args_present[i] = 0;
2024
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2025
host_ulong offset = get_rel_offset(rel);
2026
if (offset >= start_offset &&
2027
offset < start_offset + (p_end - p_start)) {
2028
sym_name = get_rel_sym_name(rel);
2031
if (strstart(sym_name, "__op_param", &p) ||
2032
strstart(sym_name, "__op_gen_label", &p)) {
2033
n = strtoul(p, NULL, 10);
2035
error("too many arguments in %s", name);
2036
args_present[n - 1] = 1;
2042
while (nb_args < MAX_ARGS && args_present[nb_args])
2044
for(i = nb_args; i < MAX_ARGS; i++) {
2045
if (args_present[i])
2046
error("inconsistent argument numbering in %s", name);
2049
if (gen_switch == 2) {
2050
fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
2051
} else if (gen_switch == 1) {
2054
fprintf(outfile, "case INDEX_%s: {\n", name);
2056
fprintf(outfile, " long ");
2057
for(i = 0; i < nb_args; i++) {
2059
fprintf(outfile, ", ");
2060
fprintf(outfile, "param%d", i + 1);
2062
fprintf(outfile, ";\n");
2064
#if defined(HOST_IA64)
2065
fprintf(outfile, " extern char %s;\n", name);
2067
fprintf(outfile, " extern void %s();\n", name);
2070
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2071
host_ulong offset = get_rel_offset(rel);
2072
if (offset >= start_offset &&
2073
offset < start_offset + (p_end - p_start)) {
2074
sym_name = get_rel_sym_name(rel);
2079
!strstart(sym_name, "remR3PhysWrite", NULL) &&
2080
!strstart(sym_name, "remR3PhysRead", NULL) &&
2082
!strstart(sym_name, "__op_param", NULL) &&
2083
!strstart(sym_name, "__op_jmp", NULL) &&
2084
!strstart(sym_name, "__op_gen_label", NULL)) {
2085
#if defined(HOST_SPARC)
2086
if (sym_name[0] == '.') {
2088
"extern char __dot_%s __asm__(\"%s\");\n",
2089
sym_name+1, sym_name);
2093
#if defined(__APPLE__)
2094
/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
2095
fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
2096
#elif defined(HOST_IA64)
2097
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2099
* PCREL21 br.call targets generally
2100
* are out of range and need to go
2101
* through an "import stub".
2103
fprintf(outfile, " extern char %s;\n",
2106
fprintf(outfile, "extern char %s;\n", sym_name);
2112
fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
2113
name, (int)(start_offset - offset), copy_size);
2115
/* emit code offset information */
2118
const char *sym_name, *p;
2122
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2123
sym_name = get_sym_name(sym);
2124
if (strstart(sym_name, "__op_label", &p)) {
2126
unsigned long offset;
2128
/* test if the variable refers to a label inside
2129
the code we are generating */
2130
#ifdef CONFIG_FORMAT_COFF
2131
if (sym->st_shndx == text_shndx) {
2132
ptr = sdata[coff_text_shndx];
2133
} else if (sym->st_shndx == data_shndx) {
2134
ptr = sdata[coff_data_shndx];
2138
#elif defined(CONFIG_FORMAT_MACH)
2141
ptr = sdata[sym->n_sect-1];
2142
#elif defined(CONFIG_FORMAT_AOUT)
2143
switch (type_to_sec_number(sym->n_type))
2145
case N_TEXT: ptr = (uint8_t *)aout_hdr + N_TXTOFF(*aout_hdr); break;
2146
case N_DATA: ptr = (uint8_t *)aout_hdr + N_DATOFF(*aout_hdr); break;
2147
default: ptr = NULL;
2150
ptr = sdata[sym->st_shndx];
2153
error("__op_labelN in invalid section");
2154
offset = sym->st_value;
2155
#ifdef CONFIG_FORMAT_MACH
2156
offset -= section_hdr[sym->n_sect-1].addr;
2157
#elif defined(CONFIG_FORMAT_AOUT)
2158
if (type_to_sec_number(sym->n_type) == N_DATA)
2159
offset -= aout_hdr->a_text;
2161
val = *(unsigned long *)(ptr + offset);
2162
#ifdef ELF_USES_RELOCA
2164
int reloc_shndx, nb_relocs1, j;
2166
/* try to find a matching relocation */
2167
reloc_shndx = find_reloc(sym->st_shndx);
2169
nb_relocs1 = shdr[reloc_shndx].sh_size /
2170
shdr[reloc_shndx].sh_entsize;
2171
rel = (ELF_RELOC *)sdata[reloc_shndx];
2172
for(j = 0; j < nb_relocs1; j++) {
2173
if (rel->r_offset == offset) {
2174
val = rel->r_addend;
2182
if (val >= start_offset && val <= start_offset + copy_size) {
2183
n = strtol(p, NULL, 10);
2184
fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
2190
/* load parameres in variables */
2191
for(i = 0; i < nb_args; i++) {
2192
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
2195
/* patch relocations */
2196
#if defined(HOST_I386)
2202
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2203
host_ulong offset = get_rel_offset(rel);
2204
if (offset >= start_offset &&
2205
offset < start_offset + copy_size) {
2206
#if defined(CONFIG_FORMAT_AOUT) || defined(CONFIG_FORMAT_MACH)
2207
sym_name = get_rel_sym_name_and_addend(rel, &addend);
2209
sym_name = get_rel_sym_name(rel);
2213
reloc_offset = offset - start_offset;
2214
if (strstart(sym_name, "__op_jmp", &p)) {
2216
n = strtol(p, NULL, 10);
2217
/* __op_jmp relocations are done at
2218
runtime to do translated block
2219
chaining: the offset of the instruction
2220
needs to be stored */
2221
fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2226
get_reloc_expr(name, sizeof(name), sym_name);
2227
#if !defined(CONFIG_FORMAT_AOUT) && !defined(CONFIG_FORMAT_MACH)
2228
addend = get32((uint32_t *)(text + offset));
2230
#ifdef CONFIG_FORMAT_ELF
2231
type = ELF32_R_TYPE(rel->r_info);
2234
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2235
reloc_offset, name, addend);
2238
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2239
reloc_offset, name, reloc_offset, addend);
2242
error("unsupported i386 relocation (%d)", type);
2244
#elif defined(CONFIG_FORMAT_COFF)
2249
temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
2250
if (!strcmp(temp_name, ".data")) {
2251
for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
2252
if (strstart(sym->st_name, sym_name, NULL)) {
2253
addend -= sym->st_value;
2261
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2262
reloc_offset, name, addend);
2265
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
2266
reloc_offset, name, reloc_offset, addend);
2269
error("unsupported i386 relocation (%d)", type);
2271
#elif defined(CONFIG_FORMAT_AOUT) || defined(CONFIG_FORMAT_MACH)
2273
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2274
offset - start_offset, name, offset - start_offset, addend);
2276
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2277
offset - start_offset, name, addend);
2281
#error unsupport object format
2286
#elif defined(HOST_X86_64)
2292
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2293
if (rel->r_offset >= start_offset &&
2294
rel->r_offset < start_offset + copy_size) {
2295
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2296
get_reloc_expr(name, sizeof(name), sym_name);
2297
type = ELF32_R_TYPE(rel->r_info);
2298
addend = rel->r_addend;
2299
reloc_offset = rel->r_offset - start_offset;
2302
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2303
reloc_offset, name, addend);
2306
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2307
reloc_offset, name, addend);
2310
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2311
reloc_offset, name, reloc_offset, addend);
2313
#ifdef VBOX /** @todo Re-check the sanity of this */
2315
fprintf(outfile, " *(uint64_t *)(gen_code_ptr + %d) = (uint64_t)%s + %d;\n",
2316
reloc_offset, name, addend);
2320
error("unsupported X86_64 relocation (%d)", type);
2325
#elif defined(HOST_PPC)
2327
#ifdef CONFIG_FORMAT_ELF
2332
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2333
if (rel->r_offset >= start_offset &&
2334
rel->r_offset < start_offset + copy_size) {
2335
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2336
reloc_offset = rel->r_offset - start_offset;
2337
if (strstart(sym_name, "__op_jmp", &p)) {
2339
n = strtol(p, NULL, 10);
2340
/* __op_jmp relocations are done at
2341
runtime to do translated block
2342
chaining: the offset of the instruction
2343
needs to be stored */
2344
fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2349
get_reloc_expr(name, sizeof(name), sym_name);
2350
type = ELF32_R_TYPE(rel->r_info);
2351
addend = rel->r_addend;
2354
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2355
reloc_offset, name, addend);
2357
case R_PPC_ADDR16_LO:
2358
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2359
reloc_offset, name, addend);
2361
case R_PPC_ADDR16_HI:
2362
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2363
reloc_offset, name, addend);
2365
case R_PPC_ADDR16_HA:
2366
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2367
reloc_offset, name, addend);
2370
/* warning: must be at 32 MB distancy */
2371
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2372
reloc_offset, reloc_offset, name, reloc_offset, addend);
2375
error("unsupported powerpc relocation (%d)", type);
2379
#elif defined(CONFIG_FORMAT_MACH)
2380
struct scattered_relocation_info *scarel;
2381
struct relocation_info * rel;
2382
char final_sym_name[256];
2383
const char *sym_name;
2388
for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2389
unsigned int offset, length, value = 0;
2390
unsigned int type, pcrel, isym = 0;
2391
unsigned int usesym = 0;
2393
if(R_SCATTERED & rel->r_address) {
2394
scarel = (struct scattered_relocation_info*)rel;
2395
offset = (unsigned int)scarel->r_address;
2396
length = scarel->r_length;
2397
pcrel = scarel->r_pcrel;
2398
type = scarel->r_type;
2399
value = scarel->r_value;
2401
value = isym = rel->r_symbolnum;
2402
usesym = (rel->r_extern);
2403
offset = rel->r_address;
2404
length = rel->r_length;
2405
pcrel = rel->r_pcrel;
2409
slide = offset - start_offset;
2411
if (!(offset >= start_offset && offset < start_offset + size))
2412
continue; /* not in our range */
2414
sym_name = get_reloc_name(rel, &sslide);
2416
if(usesym && symtab[isym].n_type & N_STAB)
2417
continue; /* don't handle STAB (debug sym) */
2419
if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2421
n = strtol(p, NULL, 10);
2422
fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2424
continue; /* Nothing more to do */
2429
fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2430
name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2431
continue; /* dunno how to handle without final_sym_name */
2434
get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2437
case PPC_RELOC_BR24:
2438
if (!strstart(sym_name,"__op_gen_label",&p)) {
2439
fprintf(outfile, "{\n");
2440
fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2441
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
2442
slide, slide, name, sslide );
2443
fprintf(outfile, "}\n");
2445
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2446
slide, slide, final_sym_name, slide);
2449
case PPC_RELOC_HI16:
2450
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2451
slide, final_sym_name, sslide);
2453
case PPC_RELOC_LO16:
2454
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2455
slide, final_sym_name, sslide);
2457
case PPC_RELOC_HA16:
2458
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2459
slide, final_sym_name, sslide);
2462
error("unsupported powerpc relocation (%d)", type);
2466
#error unsupport object format
2469
#elif defined(HOST_S390)
2475
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2476
if (rel->r_offset >= start_offset &&
2477
rel->r_offset < start_offset + copy_size) {
2478
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2479
get_reloc_expr(name, sizeof(name), sym_name);
2480
type = ELF32_R_TYPE(rel->r_info);
2481
addend = rel->r_addend;
2482
reloc_offset = rel->r_offset - start_offset;
2485
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2486
reloc_offset, name, addend);
2489
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2490
reloc_offset, name, addend);
2493
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2494
reloc_offset, name, addend);
2497
error("unsupported s390 relocation (%d)", type);
2502
#elif defined(HOST_ALPHA)
2504
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2505
if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2509
type = ELF64_R_TYPE(rel->r_info);
2510
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2511
reloc_offset = rel->r_offset - start_offset;
2513
case R_ALPHA_GPDISP:
2514
/* The gp is just 32 bit, and never changes, so it's easiest to emit it
2515
as an immediate instead of constructing it from the pv or ra. */
2516
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2518
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2519
reloc_offset + (int)rel->r_addend);
2521
case R_ALPHA_LITUSE:
2522
/* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2523
now, since some called functions (libc) need pv to be set up. */
2526
/* Branch target prediction hint. Ignore for now. Should be already
2527
correct for in-function jumps. */
2529
case R_ALPHA_LITERAL:
2530
/* Load a literal from the GOT relative to the gp. Since there's only a
2531
single gp, nothing is to be done. */
2533
case R_ALPHA_GPRELHIGH:
2534
/* Handle fake relocations against __op_param symbol. Need to emit the
2535
high part of the immediate value instead. Other symbols need no
2536
special treatment. */
2537
if (strstart(sym_name, "__op_param", &p))
2538
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2541
case R_ALPHA_GPRELLOW:
2542
if (strstart(sym_name, "__op_param", &p))
2543
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2547
/* PC-relative jump. Tweak offset to skip the two instructions that try to
2548
set up the gp from the pv. */
2549
fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2550
reloc_offset, sym_name, reloc_offset);
2553
error("unsupported Alpha relocation (%d)", type);
2558
#elif defined(HOST_IA64)
2560
unsigned long sym_idx;
2566
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2567
sym_idx = ELF64_R_SYM(rel->r_info);
2568
if (rel->r_offset < start_offset
2569
|| rel->r_offset >= start_offset + copy_size)
2571
sym_name = (strtab + symtab[sym_idx].st_name);
2572
code_offset = rel->r_offset - start_offset;
2573
if (strstart(sym_name, "__op_jmp", &p)) {
2575
n = strtol(p, NULL, 10);
2576
/* __op_jmp relocations are done at
2577
runtime to do translated block
2578
chaining: the offset of the instruction
2579
needs to be stored */
2580
fprintf(outfile, " jmp_offsets[%d] ="
2581
"%ld + (gen_code_ptr - gen_code_buf);\n",
2585
get_reloc_expr(name, sizeof(name), sym_name);
2586
type = ELF64_R_TYPE(rel->r_info);
2587
addend = rel->r_addend;
2591
" ia64_imm64(gen_code_ptr + %ld, "
2593
code_offset, name, addend);
2595
case R_IA64_LTOFF22X:
2596
case R_IA64_LTOFF22:
2597
fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
2598
" %s + %ld, %d);\n",
2599
code_offset, name, addend,
2600
(type == R_IA64_LTOFF22X));
2604
" ia64_ldxmov(gen_code_ptr + %ld,"
2605
" %s + %ld);\n", code_offset, name, addend);
2608
case R_IA64_PCREL21B:
2609
if (strstart(sym_name, "__op_gen_label", NULL)) {
2611
" ia64_imm21b(gen_code_ptr + %ld,"
2612
" (long) (%s + %ld -\n\t\t"
2613
"((long) gen_code_ptr + %ld)) >> 4);\n",
2614
code_offset, name, addend,
2615
code_offset & ~0xfUL);
2618
" IA64_PLT(gen_code_ptr + %ld, "
2619
"%d);\t/* %s + %ld */\n",
2621
get_plt_index(sym_name, addend),
2626
error("unsupported ia64 relocation (0x%x)",
2630
fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2631
copy_size - 16 + 2);
2633
#elif defined(HOST_SPARC)
2639
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2640
if (rel->r_offset >= start_offset &&
2641
rel->r_offset < start_offset + copy_size) {
2642
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2643
get_reloc_expr(name, sizeof(name), sym_name);
2644
type = ELF32_R_TYPE(rel->r_info);
2645
addend = rel->r_addend;
2646
reloc_offset = rel->r_offset - start_offset;
2649
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2650
reloc_offset, name, addend);
2654
" *(uint32_t *)(gen_code_ptr + %d) = "
2655
"((*(uint32_t *)(gen_code_ptr + %d)) "
2657
" | (((%s + %d) >> 10) & 0x3fffff);\n",
2658
reloc_offset, reloc_offset, name, addend);
2662
" *(uint32_t *)(gen_code_ptr + %d) = "
2663
"((*(uint32_t *)(gen_code_ptr + %d)) "
2665
" | ((%s + %d) & 0x3ff);\n",
2666
reloc_offset, reloc_offset, name, addend);
2668
case R_SPARC_WDISP30:
2670
" *(uint32_t *)(gen_code_ptr + %d) = "
2671
"((*(uint32_t *)(gen_code_ptr + %d)) "
2673
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2674
" & 0x3fffffff);\n",
2675
reloc_offset, reloc_offset, name, addend,
2678
case R_SPARC_WDISP22:
2680
" *(uint32_t *)(gen_code_ptr + %d) = "
2681
"((*(uint32_t *)(gen_code_ptr + %d)) "
2683
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2685
rel->r_offset - start_offset,
2686
rel->r_offset - start_offset,
2688
rel->r_offset - start_offset);
2691
error("unsupported sparc relocation (%d)", type);
2696
#elif defined(HOST_SPARC64)
2702
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2703
if (rel->r_offset >= start_offset &&
2704
rel->r_offset < start_offset + copy_size) {
2705
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2706
get_reloc_expr(name, sizeof(name), sym_name);
2707
type = ELF32_R_TYPE(rel->r_info);
2708
addend = rel->r_addend;
2709
reloc_offset = rel->r_offset - start_offset;
2712
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2713
reloc_offset, name, addend);
2717
" *(uint32_t *)(gen_code_ptr + %d) = "
2718
"((*(uint32_t *)(gen_code_ptr + %d)) "
2720
" | (((%s + %d) >> 10) & 0x3fffff);\n",
2721
reloc_offset, reloc_offset, name, addend);
2725
" *(uint32_t *)(gen_code_ptr + %d) = "
2726
"((*(uint32_t *)(gen_code_ptr + %d)) "
2728
" | ((%s + %d) & 0x3ff);\n",
2729
reloc_offset, reloc_offset, name, addend);
2732
addend += ELF64_R_TYPE_DATA (rel->r_info);
2734
" *(uint32_t *)(gen_code_ptr + %d) = "
2735
"((*(uint32_t *)(gen_code_ptr + %d)) "
2737
" | ((%s + %d) & 0x3ff);\n",
2738
reloc_offset, reloc_offset, name, addend);
2740
case R_SPARC_WDISP30:
2742
" *(uint32_t *)(gen_code_ptr + %d) = "
2743
"((*(uint32_t *)(gen_code_ptr + %d)) "
2745
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2746
" & 0x3fffffff);\n",
2747
reloc_offset, reloc_offset, name, addend,
2750
case R_SPARC_WDISP22:
2752
" *(uint32_t *)(gen_code_ptr + %d) = "
2753
"((*(uint32_t *)(gen_code_ptr + %d)) "
2755
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2757
reloc_offset, reloc_offset, name, addend,
2761
error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
2766
#elif defined(HOST_ARM)
2774
insn = get32((uint32_t *)(p_start + 4));
2775
/* If prologue ends in sub sp, sp, #const then assume
2776
op has a stack frame and needs the frame pointer. */
2777
if ((insn & 0xffffff00) == 0xe24dd000) {
2780
opcode = 0xe28db000; /* add fp, sp, #0. */
2782
/* ??? Need to undo the extra stack adjustment at the end of the op.
2783
For now just leave the stack misaligned and hope it doesn't break anything
2785
if ((insn & 4) != 0) {
2786
/* Preserve doubleword stack alignment. */
2788
" *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2793
insn = get32((uint32_t *)(p_start - 4));
2794
/* Calculate the size of the saved registers,
2796
for (i = 0; i < 15; i++) {
2797
if (insn & (1 << i))
2801
" *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2803
arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
2806
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2807
if (rel->r_offset >= start_offset &&
2808
rel->r_offset < start_offset + copy_size) {
2809
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2810
/* the compiler leave some unnecessary references to the code */
2811
if (sym_name[0] == '\0')
2813
get_reloc_expr(name, sizeof(name), sym_name);
2814
type = ELF32_R_TYPE(rel->r_info);
2815
addend = get32((uint32_t *)(text + rel->r_offset));
2816
reloc_offset = rel->r_offset - start_offset;
2819
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2820
reloc_offset, name, addend);
2825
fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2826
reloc_offset, addend, name);
2829
error("unsupported arm relocation (%d)", type);
2834
#elif defined(HOST_M68K)
2841
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2842
if (rel->r_offset >= start_offset &&
2843
rel->r_offset < start_offset + copy_size) {
2844
sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2845
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2846
get_reloc_expr(name, sizeof(name), sym_name);
2847
type = ELF32_R_TYPE(rel->r_info);
2848
addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2849
reloc_offset = rel->r_offset - start_offset;
2852
fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2853
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2854
reloc_offset, name, addend );
2857
fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2858
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2859
reloc_offset, name, reloc_offset, /*sym->st_value+*/ addend);
2862
error("unsupported m68k relocation (%d)", type);
2868
#error unsupported CPU
2870
fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
2871
fprintf(outfile, "}\n");
2872
fprintf(outfile, "break;\n\n");
2874
fprintf(outfile, "static inline void gen_%s(", name);
2876
fprintf(outfile, "void");
2878
for(i = 0; i < nb_args; i++) {
2880
fprintf(outfile, ", ");
2881
fprintf(outfile, "long param%d", i + 1);
2884
fprintf(outfile, ")\n");
2885
fprintf(outfile, "{\n");
2886
for(i = 0; i < nb_args; i++) {
2887
fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1);
2889
fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2890
fprintf(outfile, "}\n\n");
2894
int gen_file(FILE *outfile, int out_type)
2899
if (out_type == OUT_INDEX_OP) {
2900
fprintf(outfile, "DEF(end, 0, 0)\n");
2901
fprintf(outfile, "DEF(nop, 0, 0)\n");
2902
fprintf(outfile, "DEF(nop1, 1, 0)\n");
2903
fprintf(outfile, "DEF(nop2, 2, 0)\n");
2904
fprintf(outfile, "DEF(nop3, 3, 0)\n");
2905
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2907
name = get_sym_name(sym);
2908
if (strstart(name, OP_PREFIX, NULL)) {
2909
gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2912
} else if (out_type == OUT_GEN_OP) {
2913
/* generate gen_xxx functions */
2914
fprintf(outfile, "#include \"dyngen-op.h\"\n");
2915
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2917
name = get_sym_name(sym);
2918
if (strstart(name, OP_PREFIX, NULL)) {
2919
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2920
if (sym->st_shndx != text_shndx)
2921
error("invalid section for opcode (0x%x)", sym->st_shndx);
2923
gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2928
/* generate big code generation switch */
2931
/* We need to know the size of all the ops so we can figure out when
2932
to emit constant pools. This must be consistent with opc.h. */
2934
"static const uint32_t arm_opc_size[] = {\n"
2939
" 0,\n"); /* nop3 */
2940
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2942
name = get_sym_name(sym);
2943
if (strstart(name, OP_PREFIX, NULL)) {
2944
fprintf(outfile, " %d,\n", sym->st_size);
2952
"int dyngen_code(uint8_t *gen_code_buf,\n"
2953
" uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2954
" const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2956
" uint8_t *gen_code_ptr;\n"
2957
" const uint16_t *opc_ptr;\n"
2958
" const uint32_t *opparam_ptr;\n");
2961
/* Arm is tricky because it uses constant pools for loading immediate values.
2962
We assume (and require) each function is code followed by a constant pool.
2963
All the ops are small so this should be ok. For each op we figure
2964
out how much "spare" range we have in the load instructions. This allows
2965
us to insert subsequent ops in between the op and the constant pool,
2966
eliminating the neeed to jump around the pool.
2968
We currently generate:
2970
[ For this example we assume merging would move op1_pool out of range.
2971
In practice we should be able to combine many ops before the offset
2972
limits are reached. ]
2983
Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2986
" uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2987
" LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2988
" uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2989
/* Initialise the parmissible pool offset to an arbitary large value. */
2990
" uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2994
long addend, not_first = 0;
2995
unsigned long sym_idx;
2996
int index, max_index;
2997
const char *sym_name;
3001
for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
3002
sym_idx = ELF64_R_SYM(rel->r_info);
3003
sym_name = (strtab + symtab[sym_idx].st_name);
3004
if (strstart(sym_name, "__op_gen_label", NULL))
3006
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
3009
addend = rel->r_addend;
3010
index = get_plt_index(sym_name, addend);
3011
if (index <= max_index)
3014
fprintf(outfile, " extern void %s(void);\n", sym_name);
3018
" struct ia64_fixup *plt_fixes = NULL, "
3019
"*ltoff_fixes = NULL;\n"
3020
" static long plt_target[] = {\n\t");
3023
for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
3024
sym_idx = ELF64_R_SYM(rel->r_info);
3025
sym_name = (strtab + symtab[sym_idx].st_name);
3026
if (strstart(sym_name, "__op_gen_label", NULL))
3028
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
3031
addend = rel->r_addend;
3032
index = get_plt_index(sym_name, addend);
3033
if (index <= max_index)
3038
fprintf(outfile, ",\n\t");
3041
fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
3043
fprintf(outfile, "(long) &%s", sym_name);
3045
fprintf(outfile, "\n };\n"
3046
" unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
3052
" gen_code_ptr = gen_code_buf;\n"
3053
" opc_ptr = opc_buf;\n"
3054
" opparam_ptr = opparam_buf;\n");
3056
/* Generate prologue, if needed. */
3062
/* Generate constant pool if needed */
3064
" if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
3065
" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
3066
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
3067
" last_gen_code_ptr = gen_code_ptr;\n"
3068
" arm_ldr_ptr = arm_ldr_table;\n"
3069
" arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
3070
" arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
3075
" switch(*opc_ptr++) {\n");
3077
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
3079
name = get_sym_name(sym);
3080
if (strstart(name, OP_PREFIX, NULL)) {
3082
printf("%4d: %s pos=0x%08x len=%d\n",
3083
i, name, sym->st_value, sym->st_size);
3085
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
3086
if (sym->st_shndx != text_shndx)
3087
error("invalid section for opcode (0x%x)", sym->st_shndx);
3089
gen_code(name, sym->st_value, sym->st_size, outfile, 1);
3094
" case INDEX_op_nop:\n"
3096
" case INDEX_op_nop1:\n"
3099
" case INDEX_op_nop2:\n"
3100
" opparam_ptr += 2;\n"
3102
" case INDEX_op_nop3:\n"
3103
" opparam_ptr += 3;\n"
3117
" extern char code_gen_buffer[];\n"
3118
" ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
3119
"(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
3120
"sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
3121
"plt_target, plt_offset);\n }\n");
3124
/* generate some code patching */
3127
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
3128
" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
3129
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
3131
/* flush instruction cache */
3132
fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
3134
fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n");
3135
fprintf(outfile, "}\n\n");
3144
printf("dyngen (c) 2003 Fabrice Bellard\n"
3145
"usage: dyngen [-o outfile] [-c] objfile\n"
3146
"Generate a dynamic code generator from an object file\n"
3147
"-c output enum of operations\n"
3148
"-g output gen_op_xx() functions\n"
3153
int main(int argc, char **argv)
3156
const char *filename, *outfilename;
3159
outfilename = "out.c";
3160
out_type = OUT_CODE;
3162
c = getopt(argc, argv, "ho:cg");
3170
outfilename = optarg;
3173
out_type = OUT_INDEX_OP;
3176
out_type = OUT_GEN_OP;
3182
filename = argv[optind];
3183
outfile = fopen(outfilename, "w");
3185
error("could not open '%s'", outfilename);
3187
load_object(filename);
3188
gen_file(outfile, out_type);
3200
* indent-tabs-mode: t