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
42 #define CONFIG_FORMAT_ELF
45 #ifdef CONFIG_FORMAT_ELF
47 /* elf format definitions. We use these macros to test the CPU to
48 allow cross compilation (this tool must be ran on the build
50 #if defined(HOST_I386)
52 #define ELF_CLASS ELFCLASS32
53 #define ELF_ARCH EM_386
54 #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
55 #undef ELF_USES_RELOCA
57 #elif defined(HOST_X86_64)
59 #define ELF_CLASS ELFCLASS64
60 #define ELF_ARCH EM_X86_64
61 #define elf_check_arch(x) ((x) == EM_X86_64)
62 #define ELF_USES_RELOCA
64 #elif defined(HOST_PPC)
66 #define ELF_CLASS ELFCLASS32
67 #define ELF_ARCH EM_PPC
68 #define elf_check_arch(x) ((x) == EM_PPC)
69 #define ELF_USES_RELOCA
71 #elif defined(HOST_S390)
73 #define ELF_CLASS ELFCLASS32
74 #define ELF_ARCH EM_S390
75 #define elf_check_arch(x) ((x) == EM_S390)
76 #define ELF_USES_RELOCA
78 #elif defined(HOST_ALPHA)
80 #define ELF_CLASS ELFCLASS64
81 #define ELF_ARCH EM_ALPHA
82 #define elf_check_arch(x) ((x) == EM_ALPHA)
83 #define ELF_USES_RELOCA
85 #elif defined(HOST_IA64)
87 #define ELF_CLASS ELFCLASS64
88 #define ELF_ARCH EM_IA_64
89 #define elf_check_arch(x) ((x) == EM_IA_64)
90 #define ELF_USES_RELOCA
92 #elif defined(HOST_SPARC)
94 #define ELF_CLASS ELFCLASS32
95 #define ELF_ARCH EM_SPARC
96 #define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
97 #define ELF_USES_RELOCA
99 #elif defined(HOST_SPARC64)
101 #define ELF_CLASS ELFCLASS64
102 #define ELF_ARCH EM_SPARCV9
103 #define elf_check_arch(x) ((x) == EM_SPARCV9)
104 #define ELF_USES_RELOCA
106 #elif defined(HOST_ARM)
108 #define ELF_CLASS ELFCLASS32
109 #define ELF_ARCH EM_ARM
110 #define elf_check_arch(x) ((x) == EM_ARM)
111 #define ELF_USES_RELOC
113 #elif defined(HOST_M68K)
115 #define ELF_CLASS ELFCLASS32
116 #define ELF_ARCH EM_68K
117 #define elf_check_arch(x) ((x) == EM_68K)
118 #define ELF_USES_RELOCA
120 #elif defined(HOST_MIPS)
122 #define ELF_CLASS ELFCLASS32
123 #define ELF_ARCH EM_MIPS
124 #define elf_check_arch(x) ((x) == EM_MIPS)
125 #define ELF_USES_RELOC
127 #elif defined(HOST_MIPS64)
129 /* Assume n32 ABI here, which is ELF32. */
130 #define ELF_CLASS ELFCLASS32
131 #define ELF_ARCH EM_MIPS
132 #define elf_check_arch(x) ((x) == EM_MIPS)
133 #define ELF_USES_RELOCA
136 #error unsupported CPU - please update the code
141 #if ELF_CLASS == ELFCLASS32
142 typedef int32_t host_long
;
143 typedef uint32_t host_ulong
;
144 #define swabls(x) swab32s(x)
145 #define swablss(x) swab32ss(x)
147 typedef int64_t host_long
;
148 typedef uint64_t host_ulong
;
149 #define swabls(x) swab64s(x)
150 #define swablss(x) swab64ss(x)
153 #ifdef ELF_USES_RELOCA
154 #define SHT_RELOC SHT_RELA
156 #define SHT_RELOC SHT_REL
159 #define EXE_RELOC ELF_RELOC
160 #define EXE_SYM ElfW(Sym)
162 #endif /* CONFIG_FORMAT_ELF */
164 #ifdef CONFIG_FORMAT_COFF
166 typedef int32_t host_long
;
167 typedef uint32_t host_ulong
;
171 #define FILENAMELEN 256
173 typedef struct coff_sym
{
174 struct external_syment
*st_syment
;
175 char st_name
[FILENAMELEN
];
182 typedef struct coff_rel
{
183 struct external_reloc
*r_reloc
;
188 #define EXE_RELOC struct coff_rel
189 #define EXE_SYM struct coff_sym
191 #endif /* CONFIG_FORMAT_COFF */
193 #ifdef CONFIG_FORMAT_MACH
195 #include <mach-o/loader.h>
196 #include <mach-o/nlist.h>
197 #include <mach-o/reloc.h>
198 #include <mach-o/ppc/reloc.h>
200 # define check_mach_header(x) (x.magic == MH_MAGIC)
201 typedef int32_t host_long
;
202 typedef uint32_t host_ulong
;
204 struct nlist_extended
210 unsigned char n_type
;
211 unsigned char n_sect
;
213 unsigned long st_value
;
214 unsigned long st_size
;
217 #define EXE_RELOC struct relocation_info
218 #define EXE_SYM struct nlist_extended
220 #endif /* CONFIG_FORMAT_MACH */
230 /* all dynamically generated functions begin with this code */
231 #define OP_PREFIX "op_"
235 static void __attribute__((noreturn
)) __attribute__((format (printf
, 1, 2))) error(const char *fmt
, ...)
239 fprintf(stderr
, "dyngen: ");
240 vfprintf(stderr
, fmt
, ap
);
241 fprintf(stderr
, "\n");
246 static void *load_data(int fd
, long offset
, unsigned int size
)
253 lseek(fd
, offset
, SEEK_SET
);
254 if (read(fd
, data
, size
) != size
) {
261 int strstart(const char *str
, const char *val
, const char **ptr
)
277 void pstrcpy(char *buf
, int buf_size
, const char *str
)
287 if (c
== 0 || q
>= buf
+ buf_size
- 1)
294 void swab16s(uint16_t *p
)
299 void swab32s(uint32_t *p
)
304 void swab32ss(int32_t *p
)
309 void swab64s(uint64_t *p
)
314 void swab64ss(int64_t *p
)
319 uint16_t get16(uint16_t *p
)
328 uint32_t get32(uint32_t *p
)
337 void put16(uint16_t *p
, uint16_t val
)
344 void put32(uint32_t *p
, uint32_t val
)
351 /* executable information */
359 #ifdef CONFIG_FORMAT_ELF
362 struct elf_shdr
*shdr
;
367 int elf_must_swap(struct elfhdr
*h
)
375 return (h
->e_ident
[EI_DATA
] == ELFDATA2MSB
) !=
376 (swaptest
.b
[0] == 0);
379 void elf_swap_ehdr(struct elfhdr
*h
)
381 swab16s(&h
->e_type
); /* Object file type */
382 swab16s(&h
-> e_machine
); /* Architecture */
383 swab32s(&h
-> e_version
); /* Object file version */
384 swabls(&h
-> e_entry
); /* Entry point virtual address */
385 swabls(&h
-> e_phoff
); /* Program header table file offset */
386 swabls(&h
-> e_shoff
); /* Section header table file offset */
387 swab32s(&h
-> e_flags
); /* Processor-specific flags */
388 swab16s(&h
-> e_ehsize
); /* ELF header size in bytes */
389 swab16s(&h
-> e_phentsize
); /* Program header table entry size */
390 swab16s(&h
-> e_phnum
); /* Program header table entry count */
391 swab16s(&h
-> e_shentsize
); /* Section header table entry size */
392 swab16s(&h
-> e_shnum
); /* Section header table entry count */
393 swab16s(&h
-> e_shstrndx
); /* Section header string table index */
396 void elf_swap_shdr(struct elf_shdr
*h
)
398 swab32s(&h
-> sh_name
); /* Section name (string tbl index) */
399 swab32s(&h
-> sh_type
); /* Section type */
400 swabls(&h
-> sh_flags
); /* Section flags */
401 swabls(&h
-> sh_addr
); /* Section virtual addr at execution */
402 swabls(&h
-> sh_offset
); /* Section file offset */
403 swabls(&h
-> sh_size
); /* Section size in bytes */
404 swab32s(&h
-> sh_link
); /* Link to another section */
405 swab32s(&h
-> sh_info
); /* Additional section information */
406 swabls(&h
-> sh_addralign
); /* Section alignment */
407 swabls(&h
-> sh_entsize
); /* Entry size if section holds table */
410 void elf_swap_phdr(struct elf_phdr
*h
)
412 swab32s(&h
->p_type
); /* Segment type */
413 swabls(&h
->p_offset
); /* Segment file offset */
414 swabls(&h
->p_vaddr
); /* Segment virtual address */
415 swabls(&h
->p_paddr
); /* Segment physical address */
416 swabls(&h
->p_filesz
); /* Segment size in file */
417 swabls(&h
->p_memsz
); /* Segment size in memory */
418 swab32s(&h
->p_flags
); /* Segment flags */
419 swabls(&h
->p_align
); /* Segment alignment */
422 void elf_swap_rel(ELF_RELOC
*rel
)
424 swabls(&rel
->r_offset
);
425 swabls(&rel
->r_info
);
426 #ifdef ELF_USES_RELOCA
427 swablss(&rel
->r_addend
);
431 struct elf_shdr
*find_elf_section(struct elf_shdr
*shdr
, int shnum
, const char *shstr
,
436 struct elf_shdr
*sec
;
438 for(i
= 0; i
< shnum
; i
++) {
442 shname
= shstr
+ sec
->sh_name
;
443 if (!strcmp(shname
, name
))
449 int find_reloc(int sh_index
)
451 struct elf_shdr
*sec
;
454 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
456 if (sec
->sh_type
== SHT_RELOC
&& sec
->sh_info
== sh_index
)
462 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
464 return rel
->r_offset
;
467 static char *get_rel_sym_name(EXE_RELOC
*rel
)
469 return strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
472 static char *get_sym_name(EXE_SYM
*sym
)
474 return strtab
+ sym
->st_name
;
477 /* load an elf object file */
478 int load_object(const char *filename
)
481 struct elf_shdr
*sec
, *symtab_sec
, *strtab_sec
, *text_sec
;
487 fd
= open(filename
, O_RDONLY
);
489 error("can't open file '%s'", filename
);
491 /* Read ELF header. */
492 if (read(fd
, &ehdr
, sizeof (ehdr
)) != sizeof (ehdr
))
493 error("unable to read file header");
495 /* Check ELF identification. */
496 if (ehdr
.e_ident
[EI_MAG0
] != ELFMAG0
497 || ehdr
.e_ident
[EI_MAG1
] != ELFMAG1
498 || ehdr
.e_ident
[EI_MAG2
] != ELFMAG2
499 || ehdr
.e_ident
[EI_MAG3
] != ELFMAG3
500 || ehdr
.e_ident
[EI_VERSION
] != EV_CURRENT
) {
501 error("bad ELF header");
504 do_swap
= elf_must_swap(&ehdr
);
506 elf_swap_ehdr(&ehdr
);
507 if (ehdr
.e_ident
[EI_CLASS
] != ELF_CLASS
)
508 error("Unsupported ELF class");
509 if (ehdr
.e_type
!= ET_REL
)
510 error("ELF object file expected");
511 if (ehdr
.e_version
!= EV_CURRENT
)
512 error("Invalid ELF version");
513 if (!elf_check_arch(ehdr
.e_machine
))
514 error("Unsupported CPU (e_machine=%d)", ehdr
.e_machine
);
516 /* read section headers */
517 shdr
= load_data(fd
, ehdr
.e_shoff
, ehdr
.e_shnum
* sizeof(struct elf_shdr
));
519 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
520 elf_swap_shdr(&shdr
[i
]);
524 /* read all section data */
525 sdata
= malloc(sizeof(void *) * ehdr
.e_shnum
);
526 memset(sdata
, 0, sizeof(void *) * ehdr
.e_shnum
);
528 for(i
= 0;i
< ehdr
.e_shnum
; i
++) {
530 if (sec
->sh_type
!= SHT_NOBITS
)
531 sdata
[i
] = load_data(fd
, sec
->sh_offset
, sec
->sh_size
);
534 sec
= &shdr
[ehdr
.e_shstrndx
];
535 shstr
= (char *)sdata
[ehdr
.e_shstrndx
];
537 /* swap relocations */
538 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
540 if (sec
->sh_type
== SHT_RELOC
) {
541 nb_relocs
= sec
->sh_size
/ sec
->sh_entsize
;
543 for(j
= 0, rel
= (ELF_RELOC
*)sdata
[i
]; j
< nb_relocs
; j
++, rel
++)
550 text_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".text");
552 error("could not find .text section");
553 text_shndx
= text_sec
- shdr
;
554 text
= sdata
[text_shndx
];
556 /* find text relocations, if any */
559 i
= find_reloc(text_shndx
);
561 relocs
= (ELF_RELOC
*)sdata
[i
];
562 nb_relocs
= shdr
[i
].sh_size
/ shdr
[i
].sh_entsize
;
565 symtab_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".symtab");
567 error("could not find .symtab section");
568 strtab_sec
= &shdr
[symtab_sec
->sh_link
];
570 symtab
= (ElfW(Sym
) *)sdata
[symtab_sec
- shdr
];
571 strtab
= (char *)sdata
[symtab_sec
->sh_link
];
573 nb_syms
= symtab_sec
->sh_size
/ sizeof(ElfW(Sym
));
575 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
576 swab32s(&sym
->st_name
);
577 swabls(&sym
->st_value
);
578 swabls(&sym
->st_size
);
579 swab16s(&sym
->st_shndx
);
586 #endif /* CONFIG_FORMAT_ELF */
588 #ifdef CONFIG_FORMAT_COFF
591 struct external_scnhdr
*shdr
;
593 struct external_filehdr fhdr
;
594 struct external_syment
*coff_symtab
;
596 int coff_text_shndx
, coff_data_shndx
;
600 #define STRTAB_SIZE 4
605 #define T_FUNCTION 0x20
608 void sym_ent_name(struct external_syment
*ext_sym
, EXE_SYM
*sym
)
613 if (ext_sym
->e
.e
.e_zeroes
!= 0) {
615 for(i
= 0; i
< 8; i
++) {
616 c
= ext_sym
->e
.e_name
[i
];
623 pstrcpy(sym
->st_name
, sizeof(sym
->st_name
), strtab
+ ext_sym
->e
.e
.e_offset
);
626 /* now convert the name to a C name (suppress the leading '_') */
627 if (sym
->st_name
[0] == '_') {
628 len
= strlen(sym
->st_name
);
629 memmove(sym
->st_name
, sym
->st_name
+ 1, len
- 1);
630 sym
->st_name
[len
- 1] = '\0';
634 char *name_for_dotdata(struct coff_rel
*rel
)
637 struct coff_sym
*sym
;
640 text_data
= *(uint32_t *)(text
+ rel
->r_offset
);
642 for (i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
643 if (sym
->st_syment
->e_scnum
== data_shndx
&&
644 text_data
>= sym
->st_value
&&
645 text_data
< sym
->st_value
+ sym
->st_size
) {
654 static char *get_sym_name(EXE_SYM
*sym
)
659 static char *get_rel_sym_name(EXE_RELOC
*rel
)
662 name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
663 if (!strcmp(name
, ".data"))
664 name
= name_for_dotdata(rel
);
670 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
672 return rel
->r_offset
;
675 struct external_scnhdr
*find_coff_section(struct external_scnhdr
*shdr
, int shnum
, const char *name
)
679 struct external_scnhdr
*sec
;
681 for(i
= 0; i
< shnum
; i
++) {
685 shname
= sec
->s_name
;
686 if (!strcmp(shname
, name
))
692 /* load a coff object file */
693 int load_object(const char *filename
)
696 struct external_scnhdr
*sec
, *text_sec
, *data_sec
;
698 struct external_syment
*ext_sym
;
699 struct external_reloc
*coff_relocs
;
700 struct external_reloc
*ext_rel
;
707 fd
= open(filename
, O_RDONLY
713 error("can't open file '%s'", filename
);
715 /* Read COFF header. */
716 if (read(fd
, &fhdr
, sizeof (fhdr
)) != sizeof (fhdr
))
717 error("unable to read file header");
719 /* Check COFF identification. */
720 if (fhdr
.f_magic
!= I386MAGIC
) {
721 error("bad COFF header");
725 /* read section headers */
726 shdr
= load_data(fd
, sizeof(struct external_filehdr
) + fhdr
.f_opthdr
, fhdr
.f_nscns
* sizeof(struct external_scnhdr
));
728 /* read all section data */
729 sdata
= malloc(sizeof(void *) * fhdr
.f_nscns
);
730 memset(sdata
, 0, sizeof(void *) * fhdr
.f_nscns
);
732 for(i
= 0;i
< fhdr
.f_nscns
; i
++) {
734 if (!strstart(sec
->s_name
, ".bss", &p
))
735 sdata
[i
] = load_data(fd
, sec
->s_scnptr
, sec
->s_size
);
740 text_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".text");
742 error("could not find .text section");
743 coff_text_shndx
= text_sec
- shdr
;
744 text
= sdata
[coff_text_shndx
];
747 data_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".data");
749 error("could not find .data section");
750 coff_data_shndx
= data_sec
- shdr
;
752 coff_symtab
= load_data(fd
, fhdr
.f_symptr
, fhdr
.f_nsyms
*SYMESZ
);
753 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
755 printf(" %02x", ((uint8_t *)ext_sym
->e
.e_name
)[i
]);
760 n_strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), STRTAB_SIZE
);
761 strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), *n_strtab
);
763 nb_syms
= fhdr
.f_nsyms
;
765 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
766 if (strstart(ext_sym
->e
.e_name
, ".text", NULL
))
767 text_shndx
= ext_sym
->e_scnum
;
768 if (strstart(ext_sym
->e
.e_name
, ".data", NULL
))
769 data_shndx
= ext_sym
->e_scnum
;
772 /* set coff symbol */
773 symtab
= malloc(sizeof(struct coff_sym
) * nb_syms
);
775 for (i
= 0, ext_sym
= coff_symtab
, sym
= symtab
; i
< nb_syms
; i
++, ext_sym
++, sym
++) {
776 memset(sym
, 0, sizeof(*sym
));
777 sym
->st_syment
= ext_sym
;
778 sym_ent_name(ext_sym
, sym
);
779 sym
->st_value
= ext_sym
->e_value
;
781 aux_size
= *(int8_t *)ext_sym
->e_numaux
;
782 if (ext_sym
->e_scnum
== text_shndx
&& ext_sym
->e_type
== T_FUNCTION
) {
783 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
784 if ((ext_sym
+ j
)->e_scnum
== text_shndx
&&
785 (ext_sym
+ j
)->e_type
== T_FUNCTION
){
786 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
788 } else if (j
== nb_syms
- i
- 1) {
789 sec
= &shdr
[coff_text_shndx
];
790 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
794 } else if (ext_sym
->e_scnum
== data_shndx
&& *(uint8_t *)ext_sym
->e_sclass
== C_EXTERNAL
) {
795 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
796 if ((ext_sym
+ j
)->e_scnum
== data_shndx
) {
797 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
799 } else if (j
== nb_syms
- i
- 1) {
800 sec
= &shdr
[coff_data_shndx
];
801 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
809 sym
->st_type
= ext_sym
->e_type
;
810 sym
->st_shndx
= ext_sym
->e_scnum
;
814 /* find text relocations, if any */
815 sec
= &shdr
[coff_text_shndx
];
816 coff_relocs
= load_data(fd
, sec
->s_relptr
, sec
->s_nreloc
*RELSZ
);
817 nb_relocs
= sec
->s_nreloc
;
819 /* set coff relocation */
820 relocs
= malloc(sizeof(struct coff_rel
) * nb_relocs
);
821 for (i
= 0, ext_rel
= coff_relocs
, rel
= relocs
; i
< nb_relocs
;
822 i
++, ext_rel
++, rel
++) {
823 memset(rel
, 0, sizeof(*rel
));
824 rel
->r_reloc
= ext_rel
;
825 rel
->r_offset
= *(uint32_t *)ext_rel
->r_vaddr
;
826 rel
->r_type
= *(uint16_t *)ext_rel
->r_type
;
831 #endif /* CONFIG_FORMAT_COFF */
833 #ifdef CONFIG_FORMAT_MACH
836 struct mach_header mach_hdr
;
839 struct segment_command
*segment
= 0;
840 struct dysymtab_command
*dysymtabcmd
= 0;
841 struct symtab_command
*symtabcmd
= 0;
844 struct section
*section_hdr
;
845 struct section
*text_sec_hdr
;
849 struct relocation_info
*relocs
;
853 struct nlist
*symtab_std
;
856 /* indirect symbols */
859 /* Utility functions */
861 static inline char *find_str_by_index(int index
)
866 /* Used by dyngen common code */
867 static char *get_sym_name(EXE_SYM
*sym
)
869 char *name
= find_str_by_index(sym
->n_un
.n_strx
);
871 if ( sym
->n_type
& N_STAB
) /* Debug symbols are ignored */
882 /* find a section index given its segname, sectname */
883 static int find_mach_sec_index(struct section
*section_hdr
, int shnum
, const char *segname
,
884 const char *sectname
)
887 struct section
*sec
= section_hdr
;
889 for(i
= 0; i
< shnum
; i
++, sec
++) {
890 if (!sec
->segname
|| !sec
->sectname
)
892 if (!strcmp(sec
->sectname
, sectname
) && !strcmp(sec
->segname
, segname
))
898 /* find a section header given its segname, sectname */
899 struct section
*find_mach_sec_hdr(struct section
*section_hdr
, int shnum
, const char *segname
,
900 const char *sectname
)
902 int index
= find_mach_sec_index(section_hdr
, shnum
, segname
, sectname
);
905 return section_hdr
+index
;
909 static inline void fetch_next_pair_value(struct relocation_info
* rel
, unsigned int *value
)
911 struct scattered_relocation_info
* scarel
;
913 if(R_SCATTERED
& rel
->r_address
) {
914 scarel
= (struct scattered_relocation_info
*)rel
;
915 if(scarel
->r_type
!= PPC_RELOC_PAIR
)
916 error("fetch_next_pair_value: looking for a pair which was not found (1)");
917 *value
= scarel
->r_value
;
919 if(rel
->r_type
!= PPC_RELOC_PAIR
)
920 error("fetch_next_pair_value: looking for a pair which was not found (2)");
921 *value
= rel
->r_address
;
925 /* find a sym name given its value, in a section number */
926 static const char * find_sym_with_value_and_sec_number( int value
, int sectnum
, int * offset
)
930 for( i
= 0 ; i
< nb_syms
; i
++ )
932 if( !(symtab
[i
].n_type
& N_STAB
) && (symtab
[i
].n_type
& N_SECT
) &&
933 (symtab
[i
].n_sect
== sectnum
) && (symtab
[i
].st_value
<= value
) )
935 if( (ret
<0) || (symtab
[i
].st_value
>= symtab
[ret
].st_value
) )
943 *offset
= value
- symtab
[ret
].st_value
;
944 return get_sym_name(&symtab
[ret
]);
949 * Find symbol name given a (virtual) address, and a section which is of type
950 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
952 static const char * find_reloc_name_in_sec_ptr(int address
, struct section
* sec_hdr
)
954 unsigned int tocindex
, symindex
, size
;
955 const char *name
= 0;
958 if(!( address
>= sec_hdr
->addr
&& address
< (sec_hdr
->addr
+ sec_hdr
->size
) ) )
961 if( sec_hdr
->flags
& S_SYMBOL_STUBS
){
962 size
= sec_hdr
->reserved2
;
967 else if( sec_hdr
->flags
& S_LAZY_SYMBOL_POINTERS
||
968 sec_hdr
->flags
& S_NON_LAZY_SYMBOL_POINTERS
)
969 size
= sizeof(unsigned long);
973 /* Compute our index in toc */
974 tocindex
= (address
- sec_hdr
->addr
)/size
;
975 symindex
= tocdylib
[sec_hdr
->reserved1
+ tocindex
];
977 name
= get_sym_name(&symtab
[symindex
]);
982 static const char * find_reloc_name_given_its_address(int address
)
985 for(i
= 0; i
< segment
->nsects
; i
++)
987 const char * name
= find_reloc_name_in_sec_ptr(address
, §ion_hdr
[i
]);
994 static const char * get_reloc_name(EXE_RELOC
* rel
, int * sslide
)
997 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
998 int sectnum
= rel
->r_symbolnum
;
1002 /* init the slide value */
1005 if(R_SCATTERED
& rel
->r_address
)
1006 return (char *)find_reloc_name_given_its_address(sca_rel
->r_value
);
1010 /* ignore debug sym */
1011 if ( symtab
[rel
->r_symbolnum
].n_type
& N_STAB
)
1013 return get_sym_name(&symtab
[rel
->r_symbolnum
]);
1016 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1017 sectoffset
= *(uint32_t *)(text
+ rel
->r_address
) & 0xffff;
1019 if(sectnum
==0xffffff)
1023 if(sectnum
> segment
->nsects
)
1024 error("sectnum > segment->nsects");
1028 case PPC_RELOC_LO16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
|= (other_half
<< 16);
1030 case PPC_RELOC_HI16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) | (uint16_t)(other_half
& 0xffff);
1032 case PPC_RELOC_HA16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) + (int16_t)(other_half
& 0xffff);
1034 case PPC_RELOC_BR24
:
1035 sectoffset
= ( *(uint32_t *)(text
+ rel
->r_address
) & 0x03fffffc );
1036 if (sectoffset
& 0x02000000) sectoffset
|= 0xfc000000;
1039 error("switch(rel->type) not found");
1043 sectoffset
+= rel
->r_address
;
1045 if (rel
->r_type
== PPC_RELOC_BR24
)
1046 name
= (char *)find_reloc_name_in_sec_ptr((int)sectoffset
, §ion_hdr
[sectnum
-1]);
1048 /* search it in the full symbol list, if not found */
1050 name
= (char *)find_sym_with_value_and_sec_number(sectoffset
, sectnum
, sslide
);
1055 /* Used by dyngen common code */
1056 static const char * get_rel_sym_name(EXE_RELOC
* rel
)
1059 return get_reloc_name( rel
, &sslide
);
1062 /* Used by dyngen common code */
1063 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
1065 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
1066 if(R_SCATTERED
& rel
->r_address
)
1067 return sca_rel
->r_address
;
1069 return rel
->r_address
;
1072 /* load a mach-o object file */
1073 int load_object(const char *filename
)
1076 unsigned int offset_to_segment
= 0;
1077 unsigned int offset_to_dysymtab
= 0;
1078 unsigned int offset_to_symtab
= 0;
1079 struct load_command lc
;
1082 struct nlist
*syment
;
1084 fd
= open(filename
, O_RDONLY
);
1086 error("can't open file '%s'", filename
);
1088 /* Read Mach header. */
1089 if (read(fd
, &mach_hdr
, sizeof (mach_hdr
)) != sizeof (mach_hdr
))
1090 error("unable to read file header");
1092 /* Check Mach identification. */
1093 if (!check_mach_header(mach_hdr
)) {
1094 error("bad Mach header");
1097 if (mach_hdr
.cputype
!= CPU_TYPE_POWERPC
)
1098 error("Unsupported CPU");
1100 if (mach_hdr
.filetype
!= MH_OBJECT
)
1101 error("Unsupported Mach Object");
1103 /* read segment headers */
1104 for(i
=0, j
=sizeof(mach_hdr
); i
<mach_hdr
.ncmds
; i
++)
1106 if(read(fd
, &lc
, sizeof(struct load_command
)) != sizeof(struct load_command
))
1107 error("unable to read load_command");
1108 if(lc
.cmd
== LC_SEGMENT
)
1110 offset_to_segment
= j
;
1111 lseek(fd
, offset_to_segment
, SEEK_SET
);
1112 segment
= malloc(sizeof(struct segment_command
));
1113 if(read(fd
, segment
, sizeof(struct segment_command
)) != sizeof(struct segment_command
))
1114 error("unable to read LC_SEGMENT");
1116 if(lc
.cmd
== LC_DYSYMTAB
)
1118 offset_to_dysymtab
= j
;
1119 lseek(fd
, offset_to_dysymtab
, SEEK_SET
);
1120 dysymtabcmd
= malloc(sizeof(struct dysymtab_command
));
1121 if(read(fd
, dysymtabcmd
, sizeof(struct dysymtab_command
)) != sizeof(struct dysymtab_command
))
1122 error("unable to read LC_DYSYMTAB");
1124 if(lc
.cmd
== LC_SYMTAB
)
1126 offset_to_symtab
= j
;
1127 lseek(fd
, offset_to_symtab
, SEEK_SET
);
1128 symtabcmd
= malloc(sizeof(struct symtab_command
));
1129 if(read(fd
, symtabcmd
, sizeof(struct symtab_command
)) != sizeof(struct symtab_command
))
1130 error("unable to read LC_SYMTAB");
1134 lseek(fd
, j
, SEEK_SET
);
1138 error("unable to find LC_SEGMENT");
1140 /* read section headers */
1141 section_hdr
= load_data(fd
, offset_to_segment
+ sizeof(struct segment_command
), segment
->nsects
* sizeof(struct section
));
1143 /* read all section data */
1144 sdata
= (uint8_t **)malloc(sizeof(void *) * segment
->nsects
);
1145 memset(sdata
, 0, sizeof(void *) * segment
->nsects
);
1147 /* Load the data in section data */
1148 for(i
= 0; i
< segment
->nsects
; i
++) {
1149 sdata
[i
] = load_data(fd
, section_hdr
[i
].offset
, section_hdr
[i
].size
);
1153 text_sec_hdr
= find_mach_sec_hdr(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1154 i
= find_mach_sec_index(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1155 if (i
== -1 || !text_sec_hdr
)
1156 error("could not find __TEXT,__text section");
1159 /* Make sure dysym was loaded */
1160 if(!(int)dysymtabcmd
)
1161 error("could not find __DYSYMTAB segment");
1163 /* read the table of content of the indirect sym */
1164 tocdylib
= load_data( fd
, dysymtabcmd
->indirectsymoff
, dysymtabcmd
->nindirectsyms
* sizeof(uint32_t) );
1166 /* Make sure symtab was loaded */
1168 error("could not find __SYMTAB segment");
1169 nb_syms
= symtabcmd
->nsyms
;
1171 symtab_std
= load_data(fd
, symtabcmd
->symoff
, symtabcmd
->nsyms
* sizeof(struct nlist
));
1172 strtab
= load_data(fd
, symtabcmd
->stroff
, symtabcmd
->strsize
);
1174 symtab
= malloc(sizeof(EXE_SYM
) * nb_syms
);
1176 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1177 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< nb_syms
; i
++, sym
++, syment
++) {
1178 struct nlist
*sym_follow
, *sym_next
= 0;
1180 memset(sym
, 0, sizeof(*sym
));
1182 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
1185 memcpy(sym
, syment
, sizeof(*syment
));
1187 /* Find the following symbol in order to get the current symbol size */
1188 for(j
= 0, sym_follow
= symtab_std
; j
< nb_syms
; j
++, sym_follow
++) {
1189 if ( sym_follow
->n_sect
!= 1 || sym_follow
->n_type
& N_STAB
|| !(sym_follow
->n_value
> sym
->st_value
))
1192 sym_next
= sym_follow
;
1195 if(!(sym_next
->n_value
> sym_follow
->n_value
))
1197 sym_next
= sym_follow
;
1200 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
1202 sym
->st_size
= text_sec_hdr
->size
- sym
->st_value
;
1206 relocs
= load_data(fd
, text_sec_hdr
->reloff
, text_sec_hdr
->nreloc
* sizeof(struct relocation_info
));
1207 nb_relocs
= text_sec_hdr
->nreloc
;
1213 #endif /* CONFIG_FORMAT_MACH */
1215 /* return true if the expression is a label reference */
1216 int get_reloc_expr(char *name
, int name_size
, const char *sym_name
)
1220 if (strstart(sym_name
, "__op_param", &p
)) {
1221 snprintf(name
, name_size
, "param%s", p
);
1222 } else if (strstart(sym_name
, "__op_gen_label", &p
)) {
1223 snprintf(name
, name_size
, "param%s", p
);
1227 if (sym_name
[0] == '.')
1228 snprintf(name
, name_size
,
1229 "(long)(&__dot_%s)",
1233 snprintf(name
, name_size
, "(long)(&%s)", sym_name
);
1240 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1243 struct plt_entry
*next
;
1245 unsigned long addend
;
1249 get_plt_index (const char *name
, unsigned long addend
)
1251 struct plt_entry
*plt
, *prev
= NULL
;
1254 /* see if we already have an entry for this target: */
1255 for (plt
= plt_list
; plt
; ++index
, prev
= plt
, plt
= plt
->next
)
1256 if (strcmp(plt
->name
, name
) == 0 && plt
->addend
== addend
)
1259 /* nope; create a new PLT entry: */
1261 plt
= malloc(sizeof(*plt
));
1266 memset(plt
, 0, sizeof(*plt
));
1267 plt
->name
= strdup(name
);
1268 plt
->addend
= addend
;
1270 /* append to plt-list: */
1282 int arm_emit_ldr_info(const char *name
, unsigned long start_offset
,
1283 FILE *outfile
, uint8_t *p_start
, uint8_t *p_end
,
1284 ELF_RELOC
*relocs
, int nb_relocs
)
1288 int offset
, min_offset
, pc_offset
, data_size
, spare
, max_pool
;
1289 uint8_t data_allocated
[1024];
1290 unsigned int data_index
;
1293 memset(data_allocated
, 0, sizeof(data_allocated
));
1296 min_offset
= p_end
- p_start
;
1298 while (p
< p_start
+ min_offset
) {
1299 insn
= get32((uint32_t *)p
);
1300 /* TODO: Armv5e ldrd. */
1301 /* TODO: VFP load. */
1302 if ((insn
& 0x0d5f0000) == 0x051f0000) {
1303 /* ldr reg, [pc, #im] */
1304 offset
= insn
& 0xfff;
1305 if (!(insn
& 0x00800000))
1309 } else if ((insn
& 0x0e5f0f00) == 0x0c1f0100) {
1311 offset
= (insn
& 0xff) << 2;
1312 if (!(insn
& 0x00800000))
1316 } else if ((insn
& 0x0fff0000) == 0x028f0000) {
1317 /* Some gcc load a doubleword immediate with
1319 ldmia regN, {regN, regM}
1320 Hope and pray the compiler never generates somethin like
1321 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1324 r
= (insn
& 0xf00) >> 7;
1325 offset
= ((insn
& 0xff) >> r
) | ((insn
& 0xff) << (32 - r
));
1333 /* PC-relative load needs fixing up. */
1334 if (spare
> max_pool
- offset
)
1335 spare
= max_pool
- offset
;
1336 if ((offset
& 3) !=0)
1337 error("%s:%04x: pc offset must be 32 bit aligned",
1338 name
, start_offset
+ p
- p_start
);
1340 error("%s:%04x: Embedded literal value",
1341 name
, start_offset
+ p
- p_start
);
1342 pc_offset
= p
- p_start
+ offset
+ 8;
1343 if (pc_offset
<= (p
- p_start
) ||
1344 pc_offset
>= (p_end
- p_start
))
1345 error("%s:%04x: pc offset must point inside the function code",
1346 name
, start_offset
+ p
- p_start
);
1347 if (pc_offset
< min_offset
)
1348 min_offset
= pc_offset
;
1350 /* The intruction position */
1351 fprintf(outfile
, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1353 /* The position of the constant pool data. */
1354 data_index
= ((p_end
- p_start
) - pc_offset
) >> 2;
1355 fprintf(outfile
, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1357 fprintf(outfile
, " arm_ldr_ptr->type = %d;\n", type
);
1358 fprintf(outfile
, " arm_ldr_ptr++;\n");
1364 /* Copy and relocate the constant pool data. */
1365 data_size
= (p_end
- p_start
) - min_offset
;
1366 if (data_size
> 0 && outfile
) {
1367 spare
+= min_offset
;
1368 fprintf(outfile
, " arm_data_ptr -= %d;\n", data_size
>> 2);
1369 fprintf(outfile
, " arm_pool_ptr -= %d;\n", data_size
);
1370 fprintf(outfile
, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1371 " arm_pool_ptr = gen_code_ptr + %d;\n",
1375 for (pc_offset
= min_offset
;
1376 pc_offset
< p_end
- p_start
;
1380 int i
, addend
, type
;
1381 const char *sym_name
;
1385 addend
= get32((uint32_t *)(p_start
+ pc_offset
));
1387 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1388 if (rel
->r_offset
== (pc_offset
+ start_offset
)) {
1389 sym_name
= get_rel_sym_name(rel
);
1390 /* the compiler leave some unnecessary references to the code */
1391 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1392 type
= ELF32_R_TYPE(rel
->r_info
);
1393 if (type
!= R_ARM_ABS32
)
1394 error("%s: unsupported data relocation", name
);
1398 fprintf(outfile
, " arm_data_ptr[%d] = 0x%x",
1399 data_index
, addend
);
1400 if (relname
[0] != '\0')
1401 fprintf(outfile
, " + %s", relname
);
1402 fprintf(outfile
, ";\n");
1411 insn
= get32((uint32_t *)p
);
1412 /* The last instruction must be an ldm instruction. There are several
1413 forms generated by gcc:
1414 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1416 ldmea fp, {..., pc} */
1417 if ((insn
& 0xffff8000) == 0xe99d8000) {
1420 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1424 } else if ((insn
& 0xffff8000) != 0xe89d8000
1425 && (insn
& 0xffff8000) != 0xe91b8000) {
1428 printf("%s: invalid epilog\n", name
);
1437 /* generate op code */
1438 void gen_code(const char *name
, host_ulong offset
, host_ulong size
,
1439 FILE *outfile
, int gen_switch
)
1442 uint8_t *p_start
, *p_end
;
1443 host_ulong start_offset
;
1445 uint8_t args_present
[MAX_ARGS
];
1446 const char *sym_name
, *p
;
1449 /* Compute exact size excluding prologue and epilogue instructions.
1450 * Increment start_offset to skip epilogue instructions, then compute
1451 * copy_size the indicate the size of the remaining instructions (in
1454 p_start
= text
+ offset
;
1455 p_end
= p_start
+ size
;
1456 start_offset
= offset
;
1457 #if defined(HOST_I386) || defined(HOST_X86_64)
1458 #ifdef CONFIG_FORMAT_COFF
1463 error("empty code for %s", name
);
1464 while (*p
!= 0xc3) {
1467 error("ret or jmp expected at the end of %s", name
);
1469 copy_size
= p
- p_start
;
1474 len
= p_end
- p_start
;
1476 error("empty code for %s", name
);
1477 if (p_end
[-1] == 0xc3) {
1480 error("ret or jmp expected at the end of %s", name
);
1485 #elif defined(HOST_PPC)
1488 p
= (void *)(p_end
- 4);
1490 error("empty code for %s", name
);
1491 if (get32((uint32_t *)p
) != 0x4e800020)
1492 error("blr expected at the end of %s", name
);
1493 copy_size
= p
- p_start
;
1495 #elif defined(HOST_S390)
1498 p
= (void *)(p_end
- 2);
1500 error("empty code for %s", name
);
1501 if ((get16((uint16_t *)p
) & 0xfff0) != 0x07f0)
1502 error("br expected at the end of %s", name
);
1503 copy_size
= p
- p_start
;
1505 #elif defined(HOST_ALPHA)
1510 /* XXX: check why it occurs */
1512 error("empty code for %s", name
);
1514 if (get32((uint32_t *)p
) != 0x6bfa8001)
1515 error("ret expected at the end of %s", name
);
1516 copy_size
= p
- p_start
;
1518 #elif defined(HOST_IA64)
1521 p
= (void *)(p_end
- 4);
1523 error("empty code for %s", name
);
1524 /* br.ret.sptk.many b0;; */
1526 if (get32((uint32_t *)p
) != 0x00840008)
1527 error("br.ret.sptk.many b0;; expected at the end of %s", name
);
1528 copy_size
= p_end
- p_start
;
1530 #elif defined(HOST_SPARC)
1532 #define INSN_SAVE 0x9de3a000
1533 #define INSN_RET 0x81c7e008
1534 #define INSN_RETL 0x81c3e008
1535 #define INSN_RESTORE 0x81e80000
1536 #define INSN_RETURN 0x81cfe008
1537 #define INSN_NOP 0x01000000
1538 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1539 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1541 uint32_t start_insn
, end_insn1
, end_insn2
;
1543 p
= (void *)(p_end
- 8);
1545 error("empty code for %s", name
);
1546 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1547 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1548 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1549 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1550 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1552 start_offset
+= 0x4;
1553 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1554 /* SPARC v7: ret; restore; */ ;
1555 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1556 /* SPARC v9: return; nop; */ ;
1557 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1558 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1561 error("ret; restore; not found at end of %s", name
);
1562 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1565 error("No save at the beginning of %s", name
);
1568 /* Skip a preceeding nop, if present. */
1570 skip_insn
= get32((uint32_t *)(p
- 0x4));
1571 if (skip_insn
== INSN_NOP
)
1575 copy_size
= p
- p_start
;
1577 #elif defined(HOST_SPARC64)
1579 #define INSN_SAVE 0x9de3a000
1580 #define INSN_RET 0x81c7e008
1581 #define INSN_RETL 0x81c3e008
1582 #define INSN_RESTORE 0x81e80000
1583 #define INSN_RETURN 0x81cfe008
1584 #define INSN_NOP 0x01000000
1585 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1586 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1588 uint32_t start_insn
, end_insn1
, end_insn2
, skip_insn
;
1590 p
= (void *)(p_end
- 8);
1592 /* XXX: check why it occurs */
1594 error("empty code for %s", name
);
1596 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1597 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1598 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1599 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1600 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1602 start_offset
+= 0x4;
1603 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1604 /* SPARC v7: ret; restore; */ ;
1605 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1606 /* SPARC v9: return; nop; */ ;
1607 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1608 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1611 error("ret; restore; not found at end of %s", name
);
1612 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1615 error("No save at the beginning of %s", name
);
1619 /* Skip a preceeding nop, if present. */
1621 skip_insn
= get32((uint32_t *)(p
- 0x4));
1622 if (skip_insn
== 0x01000000)
1627 copy_size
= p
- p_start
;
1629 #elif defined(HOST_ARM)
1633 if ((p_end
- p_start
) <= 16)
1634 error("%s: function too small", name
);
1635 if (get32((uint32_t *)p_start
) != 0xe1a0c00d ||
1636 (get32((uint32_t *)(p_start
+ 4)) & 0xffff0000) != 0xe92d0000 ||
1637 get32((uint32_t *)(p_start
+ 8)) != 0xe24cb004)
1638 error("%s: invalid prolog", name
);
1641 insn
= get32((uint32_t *)p_start
);
1642 if ((insn
& 0xffffff00) == 0xe24dd000) {
1643 /* Stack adjustment. Assume op uses the frame pointer. */
1647 copy_size
= arm_emit_ldr_info(name
, start_offset
, NULL
, p_start
, p_end
,
1650 #elif defined(HOST_M68K)
1653 p
= (void *)(p_end
- 2);
1655 error("empty code for %s", name
);
1656 // remove NOP's, probably added for alignment
1657 while ((get16((uint16_t *)p
) == 0x4e71) &&
1660 if (get16((uint16_t *)p
) != 0x4e75)
1661 error("rts expected at the end of %s", name
);
1662 copy_size
= p
- p_start
;
1664 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1666 #define INSN_RETURN 0x03e00008
1667 #define INSN_NOP 0x00000000
1671 if (p
< (p_start
+ 0x8)) {
1672 error("empty code for %s", name
);
1674 uint32_t end_insn1
, end_insn2
;
1677 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1678 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1679 if (end_insn1
!= INSN_RETURN
&& end_insn2
!= INSN_NOP
)
1680 error("jr ra not found at end of %s", name
);
1682 copy_size
= p
- p_start
;
1685 #error unsupported CPU
1688 /* compute the number of arguments by looking at the relocations */
1689 for(i
= 0;i
< MAX_ARGS
; i
++)
1690 args_present
[i
] = 0;
1692 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1693 host_ulong offset
= get_rel_offset(rel
);
1694 if (offset
>= start_offset
&&
1695 offset
< start_offset
+ (p_end
- p_start
)) {
1696 sym_name
= get_rel_sym_name(rel
);
1699 if (strstart(sym_name
, "__op_param", &p
) ||
1700 strstart(sym_name
, "__op_gen_label", &p
)) {
1701 n
= strtoul(p
, NULL
, 10);
1703 error("too many arguments in %s", name
);
1704 args_present
[n
- 1] = 1;
1710 while (nb_args
< MAX_ARGS
&& args_present
[nb_args
])
1712 for(i
= nb_args
; i
< MAX_ARGS
; i
++) {
1713 if (args_present
[i
])
1714 error("inconsistent argument numbering in %s", name
);
1717 if (gen_switch
== 2) {
1718 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, copy_size
);
1719 } else if (gen_switch
== 1) {
1722 fprintf(outfile
, "case INDEX_%s: {\n", name
);
1724 fprintf(outfile
, " long ");
1725 for(i
= 0; i
< nb_args
; i
++) {
1727 fprintf(outfile
, ", ");
1728 fprintf(outfile
, "param%d", i
+ 1);
1730 fprintf(outfile
, ";\n");
1732 #if defined(HOST_IA64)
1733 fprintf(outfile
, " extern char %s;\n", name
);
1735 fprintf(outfile
, " extern void %s();\n", name
);
1738 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1739 host_ulong offset
= get_rel_offset(rel
);
1740 if (offset
>= start_offset
&&
1741 offset
< start_offset
+ (p_end
- p_start
)) {
1742 sym_name
= get_rel_sym_name(rel
);
1746 !strstart(sym_name
, "__op_param", NULL
) &&
1747 !strstart(sym_name
, "__op_jmp", NULL
) &&
1748 !strstart(sym_name
, "__op_gen_label", NULL
)) {
1749 #if defined(HOST_SPARC)
1750 if (sym_name
[0] == '.') {
1752 "extern char __dot_%s __asm__(\"%s\");\n",
1753 sym_name
+1, sym_name
);
1757 #if defined(__APPLE__)
1758 /* Set __attribute((unused)) on darwin because we
1759 want to avoid warning when we don't use the symbol. */
1760 fprintf(outfile
, " extern char %s __attribute__((unused));\n", sym_name
);
1761 #elif defined(HOST_IA64)
1762 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
1764 * PCREL21 br.call targets generally
1765 * are out of range and need to go
1766 * through an "import stub".
1768 fprintf(outfile
, " extern char %s;\n",
1771 fprintf(outfile
, "extern char %s;\n", sym_name
);
1777 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1778 name
, (int)(start_offset
- offset
), copy_size
);
1780 /* emit code offset information */
1783 const char *sym_name
, *p
;
1787 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
1788 sym_name
= get_sym_name(sym
);
1789 if (strstart(sym_name
, "__op_label", &p
)) {
1791 unsigned long offset
;
1793 /* test if the variable refers to a label inside
1794 the code we are generating */
1795 #ifdef CONFIG_FORMAT_COFF
1796 if (sym
->st_shndx
== text_shndx
) {
1797 ptr
= sdata
[coff_text_shndx
];
1798 } else if (sym
->st_shndx
== data_shndx
) {
1799 ptr
= sdata
[coff_data_shndx
];
1803 #elif defined(CONFIG_FORMAT_MACH)
1806 ptr
= sdata
[sym
->n_sect
-1];
1808 ptr
= sdata
[sym
->st_shndx
];
1811 error("__op_labelN in invalid section");
1812 offset
= sym
->st_value
;
1813 #ifdef CONFIG_FORMAT_MACH
1814 offset
-= section_hdr
[sym
->n_sect
-1].addr
;
1816 val
= *(host_ulong
*)(ptr
+ offset
);
1817 #ifdef ELF_USES_RELOCA
1819 int reloc_shndx
, nb_relocs1
, j
;
1821 /* try to find a matching relocation */
1822 reloc_shndx
= find_reloc(sym
->st_shndx
);
1824 nb_relocs1
= shdr
[reloc_shndx
].sh_size
/
1825 shdr
[reloc_shndx
].sh_entsize
;
1826 rel
= (ELF_RELOC
*)sdata
[reloc_shndx
];
1827 for(j
= 0; j
< nb_relocs1
; j
++) {
1828 if (rel
->r_offset
== offset
) {
1829 val
= rel
->r_addend
;
1837 if (val
>= start_offset
&& val
<= start_offset
+ copy_size
) {
1838 n
= strtol(p
, NULL
, 10);
1839 fprintf(outfile
, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n
, (long)(val
- start_offset
));
1845 /* load parameters in variables */
1846 for(i
= 0; i
< nb_args
; i
++) {
1847 fprintf(outfile
, " param%d = *opparam_ptr++;\n", i
+ 1);
1850 /* patch relocations */
1851 #if defined(HOST_I386)
1857 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1858 if (rel
->r_offset
>= start_offset
&&
1859 rel
->r_offset
< start_offset
+ copy_size
) {
1860 sym_name
= get_rel_sym_name(rel
);
1863 reloc_offset
= rel
->r_offset
- start_offset
;
1864 if (strstart(sym_name
, "__op_jmp", &p
)) {
1866 n
= strtol(p
, NULL
, 10);
1867 /* __op_jmp relocations are done at
1868 runtime to do translated block
1869 chaining: the offset of the instruction
1870 needs to be stored */
1871 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1876 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1877 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
1878 #ifdef CONFIG_FORMAT_ELF
1879 type
= ELF32_R_TYPE(rel
->r_info
);
1884 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1885 reloc_offset
, type
, relname
, addend
);
1888 error("unsupported i386 relocation (%d)", type
);
1893 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1894 reloc_offset
, relname
, addend
);
1897 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1898 reloc_offset
, relname
, reloc_offset
, addend
);
1901 error("unsupported i386 relocation (%d)", type
);
1904 #elif defined(CONFIG_FORMAT_COFF)
1909 temp_name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
1910 if (!strcmp(temp_name
, ".data")) {
1911 for (j
= 0, sym
= symtab
; j
< nb_syms
; j
++, sym
++) {
1912 if (strstart(sym
->st_name
, sym_name
, NULL
)) {
1913 addend
-= sym
->st_value
;
1920 /* TCG uses elf relocation constants */
1922 #define R_386_PC32 2
1931 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1932 reloc_offset
, type
, relname
, addend
);
1935 error("unsupported i386 relocation (%d)", type
);
1940 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1941 reloc_offset
, relname
, addend
);
1944 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1945 reloc_offset
, relname
, reloc_offset
, addend
);
1948 error("unsupported i386 relocation (%d)", type
);
1952 #error unsupport object format
1957 #elif defined(HOST_X86_64)
1963 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1964 if (rel
->r_offset
>= start_offset
&&
1965 rel
->r_offset
< start_offset
+ copy_size
) {
1966 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1967 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1968 type
= ELF32_R_TYPE(rel
->r_info
);
1969 addend
= rel
->r_addend
;
1970 reloc_offset
= rel
->r_offset
- start_offset
;
1976 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1977 reloc_offset
, type
, relname
, addend
);
1980 error("unsupported X86_64 relocation (%d)", type
);
1985 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1986 reloc_offset
, relname
, addend
);
1989 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1990 reloc_offset
, relname
, addend
);
1993 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1994 reloc_offset
, relname
, reloc_offset
, addend
);
1997 error("unsupported X86_64 relocation (%d)", type
);
2003 #elif defined(HOST_PPC)
2005 #ifdef CONFIG_FORMAT_ELF
2010 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2011 if (rel
->r_offset
>= start_offset
&&
2012 rel
->r_offset
< start_offset
+ copy_size
) {
2013 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2014 reloc_offset
= rel
->r_offset
- start_offset
;
2015 if (strstart(sym_name
, "__op_jmp", &p
)) {
2017 n
= strtol(p
, NULL
, 10);
2018 /* __op_jmp relocations are done at
2019 runtime to do translated block
2020 chaining: the offset of the instruction
2021 needs to be stored */
2022 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2027 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2028 type
= ELF32_R_TYPE(rel
->r_info
);
2029 addend
= rel
->r_addend
;
2032 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2033 reloc_offset
, relname
, addend
);
2035 case R_PPC_ADDR16_LO
:
2036 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2037 reloc_offset
, relname
, addend
);
2039 case R_PPC_ADDR16_HI
:
2040 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2041 reloc_offset
, relname
, addend
);
2043 case R_PPC_ADDR16_HA
:
2044 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2045 reloc_offset
, relname
, addend
);
2048 /* warning: must be at 32 MB distancy */
2049 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2050 reloc_offset
, reloc_offset
, relname
, reloc_offset
, addend
);
2053 error("unsupported powerpc relocation (%d)", type
);
2057 #elif defined(CONFIG_FORMAT_MACH)
2058 struct scattered_relocation_info
*scarel
;
2059 struct relocation_info
* rel
;
2060 char final_sym_name
[256];
2061 const char *sym_name
;
2066 for(i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2067 unsigned int offset
, length
, value
= 0;
2068 unsigned int type
, pcrel
, isym
= 0;
2069 unsigned int usesym
= 0;
2071 if(R_SCATTERED
& rel
->r_address
) {
2072 scarel
= (struct scattered_relocation_info
*)rel
;
2073 offset
= (unsigned int)scarel
->r_address
;
2074 length
= scarel
->r_length
;
2075 pcrel
= scarel
->r_pcrel
;
2076 type
= scarel
->r_type
;
2077 value
= scarel
->r_value
;
2079 value
= isym
= rel
->r_symbolnum
;
2080 usesym
= (rel
->r_extern
);
2081 offset
= rel
->r_address
;
2082 length
= rel
->r_length
;
2083 pcrel
= rel
->r_pcrel
;
2087 slide
= offset
- start_offset
;
2089 if (!(offset
>= start_offset
&& offset
< start_offset
+ size
))
2090 continue; /* not in our range */
2092 sym_name
= get_reloc_name(rel
, &sslide
);
2094 if(usesym
&& symtab
[isym
].n_type
& N_STAB
)
2095 continue; /* don't handle STAB (debug sym) */
2097 if (sym_name
&& strstart(sym_name
, "__op_jmp", &p
)) {
2099 n
= strtol(p
, NULL
, 10);
2100 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2102 continue; /* Nothing more to do */
2106 fprintf(outfile
, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2107 name
, value
, usesym
? "use sym" : "don't use sym", offset
, length
, pcrel
? "pcrel":"", type
);
2108 continue; /* dunno how to handle without final_sym_name */
2111 get_reloc_expr(final_sym_name
, sizeof(final_sym_name
),
2114 case PPC_RELOC_BR24
:
2115 if (!strstart(sym_name
,"__op_gen_label",&p
)) {
2116 fprintf(outfile
, "{\n");
2117 fprintf(outfile
, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide
);
2118 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",
2119 slide
, slide
, name
, sslide
);
2120 fprintf(outfile
, "}\n");
2122 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2123 slide
, slide
, final_sym_name
, slide
);
2126 case PPC_RELOC_HI16
:
2127 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2128 slide
, final_sym_name
, sslide
);
2130 case PPC_RELOC_LO16
:
2131 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2132 slide
, final_sym_name
, sslide
);
2134 case PPC_RELOC_HA16
:
2135 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2136 slide
, final_sym_name
, sslide
);
2139 error("unsupported powerpc relocation (%d)", type
);
2143 #error unsupport object format
2146 #elif defined(HOST_S390)
2152 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2153 if (rel
->r_offset
>= start_offset
&&
2154 rel
->r_offset
< start_offset
+ copy_size
) {
2155 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2156 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2157 type
= ELF32_R_TYPE(rel
->r_info
);
2158 addend
= rel
->r_addend
;
2159 reloc_offset
= rel
->r_offset
- start_offset
;
2162 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2163 reloc_offset
, relname
, addend
);
2166 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2167 reloc_offset
, relname
, addend
);
2170 fprintf(outfile
, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2171 reloc_offset
, relname
, addend
);
2174 if (ELF32_ST_TYPE(symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_info
) == STT_SECTION
) {
2176 " *(uint32_t *)(gen_code_ptr + %d) += "
2177 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2178 reloc_offset
, name
);
2182 " *(uint32_t *)(gen_code_ptr + %d) = "
2183 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2184 reloc_offset
, relname
, addend
, reloc_offset
);
2187 error("unsupported s390 relocation (%d)", type
);
2192 #elif defined(HOST_ALPHA)
2194 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2195 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2199 type
= ELF64_R_TYPE(rel
->r_info
);
2200 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2201 reloc_offset
= rel
->r_offset
- start_offset
;
2203 case R_ALPHA_GPDISP
:
2204 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2205 as an immediate instead of constructing it from the pv or ra. */
2206 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2208 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2209 reloc_offset
+ (int)rel
->r_addend
);
2211 case R_ALPHA_LITUSE
:
2212 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2213 now, since some called functions (libc) need pv to be set up. */
2216 /* Branch target prediction hint. Ignore for now. Should be already
2217 correct for in-function jumps. */
2219 case R_ALPHA_LITERAL
:
2220 /* Load a literal from the GOT relative to the gp. Since there's only a
2221 single gp, nothing is to be done. */
2223 case R_ALPHA_GPRELHIGH
:
2224 /* Handle fake relocations against __op_param symbol. Need to emit the
2225 high part of the immediate value instead. Other symbols need no
2226 special treatment. */
2227 if (strstart(sym_name
, "__op_param", &p
))
2228 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2231 case R_ALPHA_GPRELLOW
:
2232 if (strstart(sym_name
, "__op_param", &p
))
2233 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2237 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2238 set up the gp from the pv. */
2239 fprintf(outfile
, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2240 reloc_offset
, sym_name
, reloc_offset
);
2243 error("unsupported Alpha relocation (%d)", type
);
2248 #elif defined(HOST_IA64)
2250 unsigned long sym_idx
;
2256 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2257 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2258 if (rel
->r_offset
< start_offset
2259 || rel
->r_offset
>= start_offset
+ copy_size
)
2261 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2262 code_offset
= rel
->r_offset
- start_offset
;
2263 if (strstart(sym_name
, "__op_jmp", &p
)) {
2265 n
= strtol(p
, NULL
, 10);
2266 /* __op_jmp relocations are done at
2267 runtime to do translated block
2268 chaining: the offset of the instruction
2269 needs to be stored */
2270 fprintf(outfile
, " jmp_offsets[%d] ="
2271 "%ld + (gen_code_ptr - gen_code_buf);\n",
2275 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2276 type
= ELF64_R_TYPE(rel
->r_info
);
2277 addend
= rel
->r_addend
;
2281 " ia64_imm64(gen_code_ptr + %ld, "
2283 code_offset
, relname
, addend
);
2285 case R_IA64_LTOFF22X
:
2286 case R_IA64_LTOFF22
:
2287 fprintf(outfile
, " IA64_LTOFF(gen_code_ptr + %ld,"
2288 " %s + %ld, %d);\n",
2289 code_offset
, relname
, addend
,
2290 (type
== R_IA64_LTOFF22X
));
2294 " ia64_ldxmov(gen_code_ptr + %ld,"
2295 " %s + %ld);\n", code_offset
, relname
, addend
);
2298 case R_IA64_PCREL21B
:
2299 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2301 " ia64_imm21b(gen_code_ptr + %ld,"
2302 " (long) (%s + %ld -\n\t\t"
2303 "((long) gen_code_ptr + %ld)) >> 4);\n",
2304 code_offset
, relname
, addend
,
2305 code_offset
& ~0xfUL
);
2308 " IA64_PLT(gen_code_ptr + %ld, "
2309 "%d);\t/* %s + %ld */\n",
2311 get_plt_index(sym_name
, addend
),
2316 error("unsupported ia64 relocation (0x%x)",
2320 fprintf(outfile
, " ia64_nop_b(gen_code_ptr + %d);\n",
2321 copy_size
- 16 + 2);
2323 #elif defined(HOST_SPARC)
2329 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2330 if (rel
->r_offset
>= start_offset
&&
2331 rel
->r_offset
< start_offset
+ copy_size
) {
2332 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2333 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2334 type
= ELF32_R_TYPE(rel
->r_info
);
2335 addend
= rel
->r_addend
;
2336 reloc_offset
= rel
->r_offset
- start_offset
;
2339 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2340 reloc_offset
, relname
, addend
);
2344 " *(uint32_t *)(gen_code_ptr + %d) = "
2345 "((*(uint32_t *)(gen_code_ptr + %d)) "
2347 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2348 reloc_offset
, reloc_offset
, relname
, addend
);
2352 " *(uint32_t *)(gen_code_ptr + %d) = "
2353 "((*(uint32_t *)(gen_code_ptr + %d)) "
2355 " | ((%s + %d) & 0x3ff);\n",
2356 reloc_offset
, reloc_offset
, relname
, addend
);
2358 case R_SPARC_WDISP30
:
2360 " *(uint32_t *)(gen_code_ptr + %d) = "
2361 "((*(uint32_t *)(gen_code_ptr + %d)) "
2363 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2364 " & 0x3fffffff);\n",
2365 reloc_offset
, reloc_offset
, relname
, addend
,
2368 case R_SPARC_WDISP22
:
2370 " *(uint32_t *)(gen_code_ptr + %d) = "
2371 "((*(uint32_t *)(gen_code_ptr + %d)) "
2373 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2375 rel
->r_offset
- start_offset
,
2376 rel
->r_offset
- start_offset
,
2378 rel
->r_offset
- start_offset
);
2381 error("unsupported sparc relocation (%d)", type
);
2386 #elif defined(HOST_SPARC64)
2392 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2393 if (rel
->r_offset
>= start_offset
&&
2394 rel
->r_offset
< start_offset
+ copy_size
) {
2395 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2396 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2397 type
= ELF32_R_TYPE(rel
->r_info
);
2398 addend
= rel
->r_addend
;
2399 reloc_offset
= rel
->r_offset
- start_offset
;
2402 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2403 reloc_offset
, relname
, addend
);
2407 " *(uint32_t *)(gen_code_ptr + %d) = "
2408 "((*(uint32_t *)(gen_code_ptr + %d)) "
2410 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2411 reloc_offset
, reloc_offset
, relname
, addend
);
2415 " *(uint32_t *)(gen_code_ptr + %d) = "
2416 "((*(uint32_t *)(gen_code_ptr + %d)) "
2418 " | ((%s + %d) & 0x3ff);\n",
2419 reloc_offset
, reloc_offset
, relname
, addend
);
2422 addend
+= ELF64_R_TYPE_DATA (rel
->r_info
);
2424 " *(uint32_t *)(gen_code_ptr + %d) = "
2425 "((*(uint32_t *)(gen_code_ptr + %d)) "
2427 " | ((%s + %d) & 0x3ff);\n",
2428 reloc_offset
, reloc_offset
, relname
, addend
);
2430 case R_SPARC_WDISP30
:
2432 " *(uint32_t *)(gen_code_ptr + %d) = "
2433 "((*(uint32_t *)(gen_code_ptr + %d)) "
2435 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2436 " & 0x3fffffff);\n",
2437 reloc_offset
, reloc_offset
, relname
, addend
,
2440 case R_SPARC_WDISP22
:
2442 " *(uint32_t *)(gen_code_ptr + %d) = "
2443 "((*(uint32_t *)(gen_code_ptr + %d)) "
2445 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2447 reloc_offset
, reloc_offset
, relname
, addend
,
2452 " *(uint32_t *)(gen_code_ptr + %d) = "
2453 "((*(uint32_t *)(gen_code_ptr + %d)) "
2455 " | (((%s + %d) >> 42) & 0x00000000);\n",
2456 reloc_offset
, reloc_offset
, relname
, addend
);
2461 " *(uint32_t *)(gen_code_ptr + %d) = "
2462 "((*(uint32_t *)(gen_code_ptr + %d)) "
2464 " | (((%s + %d) >> 10) & 0x00000000);\n",
2465 reloc_offset
, reloc_offset
, relname
, addend
);
2470 " *(uint32_t *)(gen_code_ptr + %d) = "
2471 "((*(uint32_t *)(gen_code_ptr + %d)) "
2473 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2474 reloc_offset
, reloc_offset
, relname
, addend
);
2478 error("unsupported sparc64 relocation (%d) for symbol %s", type
, relname
);
2483 #elif defined(HOST_ARM)
2491 insn
= get32((uint32_t *)(p_start
+ 4));
2492 /* If prologue ends in sub sp, sp, #const then assume
2493 op has a stack frame and needs the frame pointer. */
2494 if ((insn
& 0xffffff00) == 0xe24dd000) {
2497 opcode
= 0xe28db000; /* add fp, sp, #0. */
2499 /* ??? Need to undo the extra stack adjustment at the end of the op.
2500 For now just leave the stack misaligned and hope it doesn't break anything
2502 if ((insn
& 4) != 0) {
2503 /* Preserve doubleword stack alignment. */
2505 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2510 insn
= get32((uint32_t *)(p_start
- 4));
2511 /* Calculate the size of the saved registers,
2513 for (i
= 0; i
< 15; i
++) {
2514 if (insn
& (1 << i
))
2518 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode
);
2520 arm_emit_ldr_info(relname
, start_offset
, outfile
, p_start
, p_end
,
2523 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2524 if (rel
->r_offset
>= start_offset
&&
2525 rel
->r_offset
< start_offset
+ copy_size
) {
2526 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2527 /* the compiler leave some unnecessary references to the code */
2528 if (sym_name
[0] == '\0')
2530 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2531 type
= ELF32_R_TYPE(rel
->r_info
);
2532 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2533 reloc_offset
= rel
->r_offset
- start_offset
;
2536 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2537 reloc_offset
, relname
, addend
);
2542 fprintf(outfile
, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2543 reloc_offset
, addend
, relname
);
2546 error("unsupported arm relocation (%d)", type
);
2551 #elif defined(HOST_M68K)
2558 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2559 if (rel
->r_offset
>= start_offset
&&
2560 rel
->r_offset
< start_offset
+ copy_size
) {
2561 sym
= &(symtab
[ELFW(R_SYM
)(rel
->r_info
)]);
2562 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2563 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2564 type
= ELF32_R_TYPE(rel
->r_info
);
2565 addend
= get32((uint32_t *)(text
+ rel
->r_offset
)) + rel
->r_addend
;
2566 reloc_offset
= rel
->r_offset
- start_offset
;
2569 fprintf(outfile
, " /* R_68K_32 RELOC, offset %x */\n", rel
->r_offset
) ;
2570 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2571 reloc_offset
, relname
, addend
);
2574 fprintf(outfile
, " /* R_68K_PC32 RELOC, offset %x */\n", rel
->r_offset
);
2575 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2576 reloc_offset
, relname
, reloc_offset
, /*sym->st_value+*/ addend
);
2579 error("unsupported m68k relocation (%d)", type
);
2584 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2586 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2587 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2593 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2594 /* the compiler leave some unnecessary references to the code */
2595 if (sym_name
[0] == '\0')
2597 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2598 type
= ELF32_R_TYPE(rel
->r_info
);
2599 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2600 reloc_offset
= rel
->r_offset
- start_offset
;
2603 fprintf(outfile
, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2604 rel
->r_offset
, sym_name
);
2606 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2607 "(0x%x & ~0x3fffff) "
2608 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2610 reloc_offset
, addend
, addend
, relname
, reloc_offset
);
2613 fprintf(outfile
, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2614 rel
->r_offset
, sym_name
);
2616 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2617 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2619 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2620 reloc_offset
, reloc_offset
, relname
);
2623 fprintf(outfile
, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2624 rel
->r_offset
, sym_name
);
2626 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2627 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2629 " | (%s & 0xffff);\n",
2630 reloc_offset
, reloc_offset
, relname
);
2633 fprintf(outfile
, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2634 rel
->r_offset
, sym_name
);
2636 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2638 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2640 reloc_offset
, addend
, addend
, relname
, reloc_offset
);
2644 fprintf(outfile
, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2645 rel
->r_offset
, sym_name
);
2647 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2648 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2650 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2651 reloc_offset
, reloc_offset
, relname
);
2654 error("unsupported MIPS relocation (%d)", type
);
2660 #error unsupported CPU
2662 fprintf(outfile
, " gen_code_ptr += %d;\n", copy_size
);
2663 fprintf(outfile
, "}\n");
2664 fprintf(outfile
, "break;\n\n");
2666 fprintf(outfile
, "static inline void gen_%s(", name
);
2668 fprintf(outfile
, "void");
2670 for(i
= 0; i
< nb_args
; i
++) {
2672 fprintf(outfile
, ", ");
2673 fprintf(outfile
, "long param%d", i
+ 1);
2676 fprintf(outfile
, ")\n");
2677 fprintf(outfile
, "{\n");
2678 for(i
= 0; i
< nb_args
; i
++) {
2679 fprintf(outfile
, " *gen_opparam_ptr++ = param%d;\n", i
+ 1);
2681 fprintf(outfile
, " *gen_opc_ptr++ = INDEX_%s;\n", name
);
2682 fprintf(outfile
, "}\n\n");
2686 int gen_file(FILE *outfile
, int out_type
)
2691 if (out_type
== OUT_INDEX_OP
) {
2692 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2694 name
= get_sym_name(sym
);
2695 if (strstart(name
, OP_PREFIX
, NULL
)) {
2696 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 2);
2699 } else if (out_type
== OUT_GEN_OP
) {
2700 /* generate gen_xxx functions */
2701 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2703 name
= get_sym_name(sym
);
2704 if (strstart(name
, OP_PREFIX
, NULL
)) {
2705 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2706 if (sym
->st_shndx
!= text_shndx
)
2707 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2709 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 0);
2714 /* generate big code generation switch */
2718 /* We need to know the size of all the ops so we can figure out when
2719 to emit constant pools. This must be consistent with opc.h. */
2721 "static const uint32_t arm_opc_size[] = {\n"
2726 " 0,\n"); /* nop3 */
2727 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2729 name
= get_sym_name(sym
);
2730 if (strstart(name
, OP_PREFIX
, NULL
)) {
2731 fprintf(outfile
, " %d,\n", sym
->st_size
);
2740 /* Arm is tricky because it uses constant pools for loading immediate values.
2741 We assume (and require) each function is code followed by a constant pool.
2742 All the ops are small so this should be ok. For each op we figure
2743 out how much "spare" range we have in the load instructions. This allows
2744 us to insert subsequent ops in between the op and the constant pool,
2745 eliminating the neeed to jump around the pool.
2747 We currently generate:
2749 [ For this example we assume merging would move op1_pool out of range.
2750 In practice we should be able to combine many ops before the offset
2751 limits are reached. ]
2762 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2765 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2766 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2767 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2768 /* Initialise the parmissible pool offset to an arbitary large value. */
2769 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2773 long addend
, not_first
= 0;
2774 unsigned long sym_idx
;
2775 int index
, max_index
;
2776 const char *sym_name
;
2780 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2781 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2782 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2783 if (strstart(sym_name
, "__op_gen_label", NULL
))
2785 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2788 addend
= rel
->r_addend
;
2789 index
= get_plt_index(sym_name
, addend
);
2790 if (index
<= max_index
)
2793 fprintf(outfile
, " extern void %s(void);\n", sym_name
);
2797 " struct ia64_fixup *plt_fixes = NULL, "
2798 "*ltoff_fixes = NULL;\n"
2799 " static long plt_target[] = {\n\t");
2802 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2803 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2804 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2805 if (strstart(sym_name
, "__op_gen_label", NULL
))
2807 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2810 addend
= rel
->r_addend
;
2811 index
= get_plt_index(sym_name
, addend
);
2812 if (index
<= max_index
)
2817 fprintf(outfile
, ",\n\t");
2820 fprintf(outfile
, "(long) &%s + %ld", sym_name
, addend
);
2822 fprintf(outfile
, "(long) &%s", sym_name
);
2824 fprintf(outfile
, "\n };\n"
2825 " unsigned int plt_offset[%u] = { 0 };\n", max_index
+ 1);
2831 /* Generate constant pool if needed */
2833 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2834 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2835 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2836 " last_gen_code_ptr = gen_code_ptr;\n"
2837 " arm_ldr_ptr = arm_ldr_table;\n"
2838 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2839 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2843 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2845 name
= get_sym_name(sym
);
2846 if (strstart(name
, OP_PREFIX
, NULL
)) {
2848 printf("%4d: %s pos=0x%08x len=%d\n",
2849 i
, name
, sym
->st_value
, sym
->st_size
);
2851 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2852 if (sym
->st_shndx
!= text_shndx
)
2853 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2855 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 1);
2865 printf("dyngen (c) 2003 Fabrice Bellard\n"
2866 "usage: dyngen [-o outfile] [-c] objfile\n"
2867 "Generate a dynamic code generator from an object file\n"
2868 "-c output enum of operations\n"
2869 "-g output gen_op_xx() functions\n"
2874 int main(int argc
, char **argv
)
2877 const char *filename
, *outfilename
;
2880 outfilename
= "out.c";
2881 out_type
= OUT_CODE
;
2883 c
= getopt(argc
, argv
, "ho:cg");
2891 outfilename
= optarg
;
2894 out_type
= OUT_INDEX_OP
;
2897 out_type
= OUT_GEN_OP
;
2903 filename
= argv
[optind
];
2904 outfile
= fopen(outfilename
, "w");
2906 error("could not open '%s'", outfilename
);
2908 load_object(filename
);
2909 gen_file(outfile
, out_type
);