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
128 #error unsupported CPU - please update the code
133 #if ELF_CLASS == ELFCLASS32
134 typedef int32_t host_long
;
135 typedef uint32_t host_ulong
;
136 #define swabls(x) swab32s(x)
137 #define swablss(x) swab32ss(x)
139 typedef int64_t host_long
;
140 typedef uint64_t host_ulong
;
141 #define swabls(x) swab64s(x)
142 #define swablss(x) swab64ss(x)
145 #ifdef ELF_USES_RELOCA
146 #define SHT_RELOC SHT_RELA
148 #define SHT_RELOC SHT_REL
151 #define EXE_RELOC ELF_RELOC
152 #define EXE_SYM ElfW(Sym)
154 #endif /* CONFIG_FORMAT_ELF */
156 #ifdef CONFIG_FORMAT_COFF
158 typedef int32_t host_long
;
159 typedef uint32_t host_ulong
;
163 #define FILENAMELEN 256
165 typedef struct coff_sym
{
166 struct external_syment
*st_syment
;
167 char st_name
[FILENAMELEN
];
174 typedef struct coff_rel
{
175 struct external_reloc
*r_reloc
;
180 #define EXE_RELOC struct coff_rel
181 #define EXE_SYM struct coff_sym
183 #endif /* CONFIG_FORMAT_COFF */
185 #ifdef CONFIG_FORMAT_MACH
187 #include <mach-o/loader.h>
188 #include <mach-o/nlist.h>
189 #include <mach-o/reloc.h>
190 #include <mach-o/ppc/reloc.h>
192 # define check_mach_header(x) (x.magic == MH_MAGIC)
193 typedef int32_t host_long
;
194 typedef uint32_t host_ulong
;
196 struct nlist_extended
202 unsigned char n_type
;
203 unsigned char n_sect
;
205 unsigned long st_value
;
206 unsigned long st_size
;
209 #define EXE_RELOC struct relocation_info
210 #define EXE_SYM struct nlist_extended
212 #endif /* CONFIG_FORMAT_MACH */
222 /* all dynamically generated functions begin with this code */
223 #define OP_PREFIX "op_"
227 void __attribute__((noreturn
)) __attribute__((format (printf
, 1, 2))) error(const char *fmt
, ...)
231 fprintf(stderr
, "dyngen: ");
232 vfprintf(stderr
, fmt
, ap
);
233 fprintf(stderr
, "\n");
238 void *load_data(int fd
, long offset
, unsigned int size
)
245 lseek(fd
, offset
, SEEK_SET
);
246 if (read(fd
, data
, size
) != size
) {
253 int strstart(const char *str
, const char *val
, const char **ptr
)
269 void pstrcpy(char *buf
, int buf_size
, const char *str
)
279 if (c
== 0 || q
>= buf
+ buf_size
- 1)
286 void swab16s(uint16_t *p
)
291 void swab32s(uint32_t *p
)
296 void swab32ss(int32_t *p
)
301 void swab64s(uint64_t *p
)
306 void swab64ss(int64_t *p
)
311 uint16_t get16(uint16_t *p
)
320 uint32_t get32(uint32_t *p
)
329 void put16(uint16_t *p
, uint16_t val
)
336 void put32(uint32_t *p
, uint32_t val
)
343 /* executable information */
351 #ifdef CONFIG_FORMAT_ELF
354 struct elf_shdr
*shdr
;
359 int elf_must_swap(struct elfhdr
*h
)
367 return (h
->e_ident
[EI_DATA
] == ELFDATA2MSB
) !=
368 (swaptest
.b
[0] == 0);
371 void elf_swap_ehdr(struct elfhdr
*h
)
373 swab16s(&h
->e_type
); /* Object file type */
374 swab16s(&h
-> e_machine
); /* Architecture */
375 swab32s(&h
-> e_version
); /* Object file version */
376 swabls(&h
-> e_entry
); /* Entry point virtual address */
377 swabls(&h
-> e_phoff
); /* Program header table file offset */
378 swabls(&h
-> e_shoff
); /* Section header table file offset */
379 swab32s(&h
-> e_flags
); /* Processor-specific flags */
380 swab16s(&h
-> e_ehsize
); /* ELF header size in bytes */
381 swab16s(&h
-> e_phentsize
); /* Program header table entry size */
382 swab16s(&h
-> e_phnum
); /* Program header table entry count */
383 swab16s(&h
-> e_shentsize
); /* Section header table entry size */
384 swab16s(&h
-> e_shnum
); /* Section header table entry count */
385 swab16s(&h
-> e_shstrndx
); /* Section header string table index */
388 void elf_swap_shdr(struct elf_shdr
*h
)
390 swab32s(&h
-> sh_name
); /* Section name (string tbl index) */
391 swab32s(&h
-> sh_type
); /* Section type */
392 swabls(&h
-> sh_flags
); /* Section flags */
393 swabls(&h
-> sh_addr
); /* Section virtual addr at execution */
394 swabls(&h
-> sh_offset
); /* Section file offset */
395 swabls(&h
-> sh_size
); /* Section size in bytes */
396 swab32s(&h
-> sh_link
); /* Link to another section */
397 swab32s(&h
-> sh_info
); /* Additional section information */
398 swabls(&h
-> sh_addralign
); /* Section alignment */
399 swabls(&h
-> sh_entsize
); /* Entry size if section holds table */
402 void elf_swap_phdr(struct elf_phdr
*h
)
404 swab32s(&h
->p_type
); /* Segment type */
405 swabls(&h
->p_offset
); /* Segment file offset */
406 swabls(&h
->p_vaddr
); /* Segment virtual address */
407 swabls(&h
->p_paddr
); /* Segment physical address */
408 swabls(&h
->p_filesz
); /* Segment size in file */
409 swabls(&h
->p_memsz
); /* Segment size in memory */
410 swab32s(&h
->p_flags
); /* Segment flags */
411 swabls(&h
->p_align
); /* Segment alignment */
414 void elf_swap_rel(ELF_RELOC
*rel
)
416 swabls(&rel
->r_offset
);
417 swabls(&rel
->r_info
);
418 #ifdef ELF_USES_RELOCA
419 swablss(&rel
->r_addend
);
423 struct elf_shdr
*find_elf_section(struct elf_shdr
*shdr
, int shnum
, const char *shstr
,
428 struct elf_shdr
*sec
;
430 for(i
= 0; i
< shnum
; i
++) {
434 shname
= shstr
+ sec
->sh_name
;
435 if (!strcmp(shname
, name
))
441 int find_reloc(int sh_index
)
443 struct elf_shdr
*sec
;
446 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
448 if (sec
->sh_type
== SHT_RELOC
&& sec
->sh_info
== sh_index
)
454 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
456 return rel
->r_offset
;
459 static char *get_rel_sym_name(EXE_RELOC
*rel
)
461 return strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
464 static char *get_sym_name(EXE_SYM
*sym
)
466 return strtab
+ sym
->st_name
;
469 /* load an elf object file */
470 int load_object(const char *filename
)
473 struct elf_shdr
*sec
, *symtab_sec
, *strtab_sec
, *text_sec
;
479 fd
= open(filename
, O_RDONLY
);
481 error("can't open file '%s'", filename
);
483 /* Read ELF header. */
484 if (read(fd
, &ehdr
, sizeof (ehdr
)) != sizeof (ehdr
))
485 error("unable to read file header");
487 /* Check ELF identification. */
488 if (ehdr
.e_ident
[EI_MAG0
] != ELFMAG0
489 || ehdr
.e_ident
[EI_MAG1
] != ELFMAG1
490 || ehdr
.e_ident
[EI_MAG2
] != ELFMAG2
491 || ehdr
.e_ident
[EI_MAG3
] != ELFMAG3
492 || ehdr
.e_ident
[EI_VERSION
] != EV_CURRENT
) {
493 error("bad ELF header");
496 do_swap
= elf_must_swap(&ehdr
);
498 elf_swap_ehdr(&ehdr
);
499 if (ehdr
.e_ident
[EI_CLASS
] != ELF_CLASS
)
500 error("Unsupported ELF class");
501 if (ehdr
.e_type
!= ET_REL
)
502 error("ELF object file expected");
503 if (ehdr
.e_version
!= EV_CURRENT
)
504 error("Invalid ELF version");
505 if (!elf_check_arch(ehdr
.e_machine
))
506 error("Unsupported CPU (e_machine=%d)", ehdr
.e_machine
);
508 /* read section headers */
509 shdr
= load_data(fd
, ehdr
.e_shoff
, ehdr
.e_shnum
* sizeof(struct elf_shdr
));
511 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
512 elf_swap_shdr(&shdr
[i
]);
516 /* read all section data */
517 sdata
= malloc(sizeof(void *) * ehdr
.e_shnum
);
518 memset(sdata
, 0, sizeof(void *) * ehdr
.e_shnum
);
520 for(i
= 0;i
< ehdr
.e_shnum
; i
++) {
522 if (sec
->sh_type
!= SHT_NOBITS
)
523 sdata
[i
] = load_data(fd
, sec
->sh_offset
, sec
->sh_size
);
526 sec
= &shdr
[ehdr
.e_shstrndx
];
527 shstr
= (char *)sdata
[ehdr
.e_shstrndx
];
529 /* swap relocations */
530 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
532 if (sec
->sh_type
== SHT_RELOC
) {
533 nb_relocs
= sec
->sh_size
/ sec
->sh_entsize
;
535 for(j
= 0, rel
= (ELF_RELOC
*)sdata
[i
]; j
< nb_relocs
; j
++, rel
++)
542 text_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".text");
544 error("could not find .text section");
545 text_shndx
= text_sec
- shdr
;
546 text
= sdata
[text_shndx
];
548 /* find text relocations, if any */
551 i
= find_reloc(text_shndx
);
553 relocs
= (ELF_RELOC
*)sdata
[i
];
554 nb_relocs
= shdr
[i
].sh_size
/ shdr
[i
].sh_entsize
;
557 symtab_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".symtab");
559 error("could not find .symtab section");
560 strtab_sec
= &shdr
[symtab_sec
->sh_link
];
562 symtab
= (ElfW(Sym
) *)sdata
[symtab_sec
- shdr
];
563 strtab
= (char *)sdata
[symtab_sec
->sh_link
];
565 nb_syms
= symtab_sec
->sh_size
/ sizeof(ElfW(Sym
));
567 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
568 swab32s(&sym
->st_name
);
569 swabls(&sym
->st_value
);
570 swabls(&sym
->st_size
);
571 swab16s(&sym
->st_shndx
);
578 #endif /* CONFIG_FORMAT_ELF */
580 #ifdef CONFIG_FORMAT_COFF
583 struct external_scnhdr
*shdr
;
585 struct external_filehdr fhdr
;
586 struct external_syment
*coff_symtab
;
588 int coff_text_shndx
, coff_data_shndx
;
592 #define STRTAB_SIZE 4
597 #define T_FUNCTION 0x20
600 void sym_ent_name(struct external_syment
*ext_sym
, EXE_SYM
*sym
)
605 if (ext_sym
->e
.e
.e_zeroes
!= 0) {
607 for(i
= 0; i
< 8; i
++) {
608 c
= ext_sym
->e
.e_name
[i
];
615 pstrcpy(sym
->st_name
, sizeof(sym
->st_name
), strtab
+ ext_sym
->e
.e
.e_offset
);
618 /* now convert the name to a C name (suppress the leading '_') */
619 if (sym
->st_name
[0] == '_') {
620 len
= strlen(sym
->st_name
);
621 memmove(sym
->st_name
, sym
->st_name
+ 1, len
- 1);
622 sym
->st_name
[len
- 1] = '\0';
626 char *name_for_dotdata(struct coff_rel
*rel
)
629 struct coff_sym
*sym
;
632 text_data
= *(uint32_t *)(text
+ rel
->r_offset
);
634 for (i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
635 if (sym
->st_syment
->e_scnum
== data_shndx
&&
636 text_data
>= sym
->st_value
&&
637 text_data
< sym
->st_value
+ sym
->st_size
) {
646 static char *get_sym_name(EXE_SYM
*sym
)
651 static char *get_rel_sym_name(EXE_RELOC
*rel
)
654 name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
655 if (!strcmp(name
, ".data"))
656 name
= name_for_dotdata(rel
);
662 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
664 return rel
->r_offset
;
667 struct external_scnhdr
*find_coff_section(struct external_scnhdr
*shdr
, int shnum
, const char *name
)
671 struct external_scnhdr
*sec
;
673 for(i
= 0; i
< shnum
; i
++) {
677 shname
= sec
->s_name
;
678 if (!strcmp(shname
, name
))
684 /* load a coff object file */
685 int load_object(const char *filename
)
688 struct external_scnhdr
*sec
, *text_sec
, *data_sec
;
690 struct external_syment
*ext_sym
;
691 struct external_reloc
*coff_relocs
;
692 struct external_reloc
*ext_rel
;
697 fd
= open(filename
, O_RDONLY
703 error("can't open file '%s'", filename
);
705 /* Read COFF header. */
706 if (read(fd
, &fhdr
, sizeof (fhdr
)) != sizeof (fhdr
))
707 error("unable to read file header");
709 /* Check COFF identification. */
710 if (fhdr
.f_magic
!= I386MAGIC
) {
711 error("bad COFF header");
715 /* read section headers */
716 shdr
= load_data(fd
, sizeof(struct external_filehdr
) + fhdr
.f_opthdr
, fhdr
.f_nscns
* sizeof(struct external_scnhdr
));
718 /* read all section data */
719 sdata
= malloc(sizeof(void *) * fhdr
.f_nscns
);
720 memset(sdata
, 0, sizeof(void *) * fhdr
.f_nscns
);
723 for(i
= 0;i
< fhdr
.f_nscns
; i
++) {
725 if (!strstart(sec
->s_name
, ".bss", &p
))
726 sdata
[i
] = load_data(fd
, sec
->s_scnptr
, sec
->s_size
);
731 text_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".text");
733 error("could not find .text section");
734 coff_text_shndx
= text_sec
- shdr
;
735 text
= sdata
[coff_text_shndx
];
738 data_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".data");
740 error("could not find .data section");
741 coff_data_shndx
= data_sec
- shdr
;
743 coff_symtab
= load_data(fd
, fhdr
.f_symptr
, fhdr
.f_nsyms
*SYMESZ
);
744 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
746 printf(" %02x", ((uint8_t *)ext_sym
->e
.e_name
)[i
]);
751 n_strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), STRTAB_SIZE
);
752 strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), *n_strtab
);
754 nb_syms
= fhdr
.f_nsyms
;
756 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
757 if (strstart(ext_sym
->e
.e_name
, ".text", NULL
))
758 text_shndx
= ext_sym
->e_scnum
;
759 if (strstart(ext_sym
->e
.e_name
, ".data", NULL
))
760 data_shndx
= ext_sym
->e_scnum
;
763 /* set coff symbol */
764 symtab
= malloc(sizeof(struct coff_sym
) * nb_syms
);
767 for (i
= 0, ext_sym
= coff_symtab
, sym
= symtab
; i
< nb_syms
; i
++, ext_sym
++, sym
++) {
768 memset(sym
, 0, sizeof(*sym
));
769 sym
->st_syment
= ext_sym
;
770 sym_ent_name(ext_sym
, sym
);
771 sym
->st_value
= ext_sym
->e_value
;
773 aux_size
= *(int8_t *)ext_sym
->e_numaux
;
774 if (ext_sym
->e_scnum
== text_shndx
&& ext_sym
->e_type
== T_FUNCTION
) {
775 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
776 if ((ext_sym
+ j
)->e_scnum
== text_shndx
&&
777 (ext_sym
+ j
)->e_type
== T_FUNCTION
){
778 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
780 } else if (j
== nb_syms
- i
- 1) {
781 sec
= &shdr
[coff_text_shndx
];
782 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
786 } else if (ext_sym
->e_scnum
== data_shndx
&& *(uint8_t *)ext_sym
->e_sclass
== C_EXTERNAL
) {
787 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
788 if ((ext_sym
+ j
)->e_scnum
== data_shndx
) {
789 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
791 } else if (j
== nb_syms
- i
- 1) {
792 sec
= &shdr
[coff_data_shndx
];
793 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
801 sym
->st_type
= ext_sym
->e_type
;
802 sym
->st_shndx
= ext_sym
->e_scnum
;
806 /* find text relocations, if any */
807 sec
= &shdr
[coff_text_shndx
];
808 coff_relocs
= load_data(fd
, sec
->s_relptr
, sec
->s_nreloc
*RELSZ
);
809 nb_relocs
= sec
->s_nreloc
;
811 /* set coff relocation */
812 relocs
= malloc(sizeof(struct coff_rel
) * nb_relocs
);
813 for (i
= 0, ext_rel
= coff_relocs
, rel
= relocs
; i
< nb_relocs
;
814 i
++, ext_rel
++, rel
++) {
815 memset(rel
, 0, sizeof(*rel
));
816 rel
->r_reloc
= ext_rel
;
817 rel
->r_offset
= *(uint32_t *)ext_rel
->r_vaddr
;
818 rel
->r_type
= *(uint16_t *)ext_rel
->r_type
;
823 #endif /* CONFIG_FORMAT_COFF */
825 #ifdef CONFIG_FORMAT_MACH
828 struct mach_header mach_hdr
;
831 struct segment_command
*segment
= 0;
832 struct dysymtab_command
*dysymtabcmd
= 0;
833 struct symtab_command
*symtabcmd
= 0;
836 struct section
*section_hdr
;
837 struct section
*text_sec_hdr
;
841 struct relocation_info
*relocs
;
845 struct nlist
*symtab_std
;
848 /* indirect symbols */
851 /* Utility functions */
853 static inline char *find_str_by_index(int index
)
858 /* Used by dyngen common code */
859 static char *get_sym_name(EXE_SYM
*sym
)
861 char *name
= find_str_by_index(sym
->n_un
.n_strx
);
863 if ( sym
->n_type
& N_STAB
) /* Debug symbols are ignored */
874 /* find a section index given its segname, sectname */
875 static int find_mach_sec_index(struct section
*section_hdr
, int shnum
, const char *segname
,
876 const char *sectname
)
879 struct section
*sec
= section_hdr
;
881 for(i
= 0; i
< shnum
; i
++, sec
++) {
882 if (!sec
->segname
|| !sec
->sectname
)
884 if (!strcmp(sec
->sectname
, sectname
) && !strcmp(sec
->segname
, segname
))
890 /* find a section header given its segname, sectname */
891 struct section
*find_mach_sec_hdr(struct section
*section_hdr
, int shnum
, const char *segname
,
892 const char *sectname
)
894 int index
= find_mach_sec_index(section_hdr
, shnum
, segname
, sectname
);
897 return section_hdr
+index
;
901 static inline void fetch_next_pair_value(struct relocation_info
* rel
, unsigned int *value
)
903 struct scattered_relocation_info
* scarel
;
905 if(R_SCATTERED
& rel
->r_address
) {
906 scarel
= (struct scattered_relocation_info
*)rel
;
907 if(scarel
->r_type
!= PPC_RELOC_PAIR
)
908 error("fetch_next_pair_value: looking for a pair which was not found (1)");
909 *value
= scarel
->r_value
;
911 if(rel
->r_type
!= PPC_RELOC_PAIR
)
912 error("fetch_next_pair_value: looking for a pair which was not found (2)");
913 *value
= rel
->r_address
;
917 /* find a sym name given its value, in a section number */
918 static const char * find_sym_with_value_and_sec_number( int value
, int sectnum
, int * offset
)
922 for( i
= 0 ; i
< nb_syms
; i
++ )
924 if( !(symtab
[i
].n_type
& N_STAB
) && (symtab
[i
].n_type
& N_SECT
) &&
925 (symtab
[i
].n_sect
== sectnum
) && (symtab
[i
].st_value
<= value
) )
927 if( (ret
<0) || (symtab
[i
].st_value
>= symtab
[ret
].st_value
) )
935 *offset
= value
- symtab
[ret
].st_value
;
936 return get_sym_name(&symtab
[ret
]);
941 * Find symbol name given a (virtual) address, and a section which is of type
942 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
944 static const char * find_reloc_name_in_sec_ptr(int address
, struct section
* sec_hdr
)
946 unsigned int tocindex
, symindex
, size
;
947 const char *name
= 0;
950 if(!( address
>= sec_hdr
->addr
&& address
< (sec_hdr
->addr
+ sec_hdr
->size
) ) )
953 if( sec_hdr
->flags
& S_SYMBOL_STUBS
){
954 size
= sec_hdr
->reserved2
;
959 else if( sec_hdr
->flags
& S_LAZY_SYMBOL_POINTERS
||
960 sec_hdr
->flags
& S_NON_LAZY_SYMBOL_POINTERS
)
961 size
= sizeof(unsigned long);
965 /* Compute our index in toc */
966 tocindex
= (address
- sec_hdr
->addr
)/size
;
967 symindex
= tocdylib
[sec_hdr
->reserved1
+ tocindex
];
969 name
= get_sym_name(&symtab
[symindex
]);
974 static const char * find_reloc_name_given_its_address(int address
)
977 for(i
= 0; i
< segment
->nsects
; i
++)
979 const char * name
= find_reloc_name_in_sec_ptr(address
, §ion_hdr
[i
]);
986 static const char * get_reloc_name(EXE_RELOC
* rel
, int * sslide
)
989 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
990 int sectnum
= rel
->r_symbolnum
;
994 /* init the slide value */
997 if(R_SCATTERED
& rel
->r_address
)
998 return (char *)find_reloc_name_given_its_address(sca_rel
->r_value
);
1002 /* ignore debug sym */
1003 if ( symtab
[rel
->r_symbolnum
].n_type
& N_STAB
)
1005 return get_sym_name(&symtab
[rel
->r_symbolnum
]);
1008 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1009 sectoffset
= *(uint32_t *)(text
+ rel
->r_address
) & 0xffff;
1011 if(sectnum
==0xffffff)
1015 if(sectnum
> segment
->nsects
)
1016 error("sectnum > segment->nsects");
1020 case PPC_RELOC_LO16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
|= (other_half
<< 16);
1022 case PPC_RELOC_HI16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) | (uint16_t)(other_half
& 0xffff);
1024 case PPC_RELOC_HA16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) + (int16_t)(other_half
& 0xffff);
1026 case PPC_RELOC_BR24
:
1027 sectoffset
= ( *(uint32_t *)(text
+ rel
->r_address
) & 0x03fffffc );
1028 if (sectoffset
& 0x02000000) sectoffset
|= 0xfc000000;
1031 error("switch(rel->type) not found");
1035 sectoffset
+= rel
->r_address
;
1037 if (rel
->r_type
== PPC_RELOC_BR24
)
1038 name
= (char *)find_reloc_name_in_sec_ptr((int)sectoffset
, §ion_hdr
[sectnum
-1]);
1040 /* search it in the full symbol list, if not found */
1042 name
= (char *)find_sym_with_value_and_sec_number(sectoffset
, sectnum
, sslide
);
1047 /* Used by dyngen common code */
1048 static const char * get_rel_sym_name(EXE_RELOC
* rel
)
1051 return get_reloc_name( rel
, &sslide
);
1054 /* Used by dyngen common code */
1055 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
1057 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
1058 if(R_SCATTERED
& rel
->r_address
)
1059 return sca_rel
->r_address
;
1061 return rel
->r_address
;
1064 /* load a mach-o object file */
1065 int load_object(const char *filename
)
1068 unsigned int offset_to_segment
= 0;
1069 unsigned int offset_to_dysymtab
= 0;
1070 unsigned int offset_to_symtab
= 0;
1071 struct load_command lc
;
1074 struct nlist
*syment
;
1076 fd
= open(filename
, O_RDONLY
);
1078 error("can't open file '%s'", filename
);
1080 /* Read Mach header. */
1081 if (read(fd
, &mach_hdr
, sizeof (mach_hdr
)) != sizeof (mach_hdr
))
1082 error("unable to read file header");
1084 /* Check Mach identification. */
1085 if (!check_mach_header(mach_hdr
)) {
1086 error("bad Mach header");
1089 if (mach_hdr
.cputype
!= CPU_TYPE_POWERPC
)
1090 error("Unsupported CPU");
1092 if (mach_hdr
.filetype
!= MH_OBJECT
)
1093 error("Unsupported Mach Object");
1095 /* read segment headers */
1096 for(i
=0, j
=sizeof(mach_hdr
); i
<mach_hdr
.ncmds
; i
++)
1098 if(read(fd
, &lc
, sizeof(struct load_command
)) != sizeof(struct load_command
))
1099 error("unable to read load_command");
1100 if(lc
.cmd
== LC_SEGMENT
)
1102 offset_to_segment
= j
;
1103 lseek(fd
, offset_to_segment
, SEEK_SET
);
1104 segment
= malloc(sizeof(struct segment_command
));
1105 if(read(fd
, segment
, sizeof(struct segment_command
)) != sizeof(struct segment_command
))
1106 error("unable to read LC_SEGMENT");
1108 if(lc
.cmd
== LC_DYSYMTAB
)
1110 offset_to_dysymtab
= j
;
1111 lseek(fd
, offset_to_dysymtab
, SEEK_SET
);
1112 dysymtabcmd
= malloc(sizeof(struct dysymtab_command
));
1113 if(read(fd
, dysymtabcmd
, sizeof(struct dysymtab_command
)) != sizeof(struct dysymtab_command
))
1114 error("unable to read LC_DYSYMTAB");
1116 if(lc
.cmd
== LC_SYMTAB
)
1118 offset_to_symtab
= j
;
1119 lseek(fd
, offset_to_symtab
, SEEK_SET
);
1120 symtabcmd
= malloc(sizeof(struct symtab_command
));
1121 if(read(fd
, symtabcmd
, sizeof(struct symtab_command
)) != sizeof(struct symtab_command
))
1122 error("unable to read LC_SYMTAB");
1126 lseek(fd
, j
, SEEK_SET
);
1130 error("unable to find LC_SEGMENT");
1132 /* read section headers */
1133 section_hdr
= load_data(fd
, offset_to_segment
+ sizeof(struct segment_command
), segment
->nsects
* sizeof(struct section
));
1135 /* read all section data */
1136 sdata
= (uint8_t **)malloc(sizeof(void *) * segment
->nsects
);
1137 memset(sdata
, 0, sizeof(void *) * segment
->nsects
);
1139 /* Load the data in section data */
1140 for(i
= 0; i
< segment
->nsects
; i
++) {
1141 sdata
[i
] = load_data(fd
, section_hdr
[i
].offset
, section_hdr
[i
].size
);
1145 text_sec_hdr
= find_mach_sec_hdr(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1146 i
= find_mach_sec_index(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1147 if (i
== -1 || !text_sec_hdr
)
1148 error("could not find __TEXT,__text section");
1151 /* Make sure dysym was loaded */
1152 if(!(int)dysymtabcmd
)
1153 error("could not find __DYSYMTAB segment");
1155 /* read the table of content of the indirect sym */
1156 tocdylib
= load_data( fd
, dysymtabcmd
->indirectsymoff
, dysymtabcmd
->nindirectsyms
* sizeof(uint32_t) );
1158 /* Make sure symtab was loaded */
1160 error("could not find __SYMTAB segment");
1161 nb_syms
= symtabcmd
->nsyms
;
1163 symtab_std
= load_data(fd
, symtabcmd
->symoff
, symtabcmd
->nsyms
* sizeof(struct nlist
));
1164 strtab
= load_data(fd
, symtabcmd
->stroff
, symtabcmd
->strsize
);
1166 symtab
= malloc(sizeof(EXE_SYM
) * nb_syms
);
1168 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1169 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< nb_syms
; i
++, sym
++, syment
++) {
1170 struct nlist
*sym_follow
, *sym_next
= 0;
1172 memset(sym
, 0, sizeof(*sym
));
1174 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
1177 memcpy(sym
, syment
, sizeof(*syment
));
1179 /* Find the following symbol in order to get the current symbol size */
1180 for(j
= 0, sym_follow
= symtab_std
; j
< nb_syms
; j
++, sym_follow
++) {
1181 if ( sym_follow
->n_sect
!= 1 || sym_follow
->n_type
& N_STAB
|| !(sym_follow
->n_value
> sym
->st_value
))
1184 sym_next
= sym_follow
;
1187 if(!(sym_next
->n_value
> sym_follow
->n_value
))
1189 sym_next
= sym_follow
;
1192 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
1194 sym
->st_size
= text_sec_hdr
->size
- sym
->st_value
;
1198 relocs
= load_data(fd
, text_sec_hdr
->reloff
, text_sec_hdr
->nreloc
* sizeof(struct relocation_info
));
1199 nb_relocs
= text_sec_hdr
->nreloc
;
1205 #endif /* CONFIG_FORMAT_MACH */
1207 void get_reloc_expr(char *name
, int name_size
, const char *sym_name
)
1211 if (strstart(sym_name
, "__op_param", &p
)) {
1212 snprintf(name
, name_size
, "param%s", p
);
1213 } else if (strstart(sym_name
, "__op_gen_label", &p
)) {
1214 snprintf(name
, name_size
, "gen_labels[param%s]", p
);
1217 if (sym_name
[0] == '.')
1218 snprintf(name
, name_size
,
1219 "(long)(&__dot_%s)",
1223 snprintf(name
, name_size
, "(long)(&%s)", sym_name
);
1229 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1232 struct plt_entry
*next
;
1234 unsigned long addend
;
1238 get_plt_index (const char *name
, unsigned long addend
)
1240 struct plt_entry
*plt
, *prev
= NULL
;
1243 /* see if we already have an entry for this target: */
1244 for (plt
= plt_list
; plt
; ++index
, prev
= plt
, plt
= plt
->next
)
1245 if (strcmp(plt
->name
, name
) == 0 && plt
->addend
== addend
)
1248 /* nope; create a new PLT entry: */
1250 plt
= malloc(sizeof(*plt
));
1255 memset(plt
, 0, sizeof(*plt
));
1256 plt
->name
= strdup(name
);
1257 plt
->addend
= addend
;
1259 /* append to plt-list: */
1271 int arm_emit_ldr_info(const char *name
, unsigned long start_offset
,
1272 FILE *outfile
, uint8_t *p_start
, uint8_t *p_end
,
1273 ELF_RELOC
*relocs
, int nb_relocs
)
1277 int offset
, min_offset
, pc_offset
, data_size
, spare
, max_pool
;
1278 uint8_t data_allocated
[1024];
1279 unsigned int data_index
;
1282 memset(data_allocated
, 0, sizeof(data_allocated
));
1285 min_offset
= p_end
- p_start
;
1287 while (p
< p_start
+ min_offset
) {
1288 insn
= get32((uint32_t *)p
);
1289 /* TODO: Armv5e ldrd. */
1290 /* TODO: VFP load. */
1291 if ((insn
& 0x0d5f0000) == 0x051f0000) {
1292 /* ldr reg, [pc, #im] */
1293 offset
= insn
& 0xfff;
1294 if (!(insn
& 0x00800000))
1298 } else if ((insn
& 0x0e5f0f00) == 0x0c1f0100) {
1300 offset
= (insn
& 0xff) << 2;
1301 if (!(insn
& 0x00800000))
1305 } else if ((insn
& 0x0fff0000) == 0x028f0000) {
1306 /* Some gcc load a doubleword immediate with
1308 ldmia regN, {regN, regM}
1309 Hope and pray the compiler never generates somethin like
1310 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1313 r
= (insn
& 0xf00) >> 7;
1314 offset
= ((insn
& 0xff) >> r
) | ((insn
& 0xff) << (32 - r
));
1322 /* PC-relative load needs fixing up. */
1323 if (spare
> max_pool
- offset
)
1324 spare
= max_pool
- offset
;
1325 if ((offset
& 3) !=0)
1326 error("%s:%04x: pc offset must be 32 bit aligned",
1327 name
, start_offset
+ p
- p_start
);
1329 error("%s:%04x: Embedded literal value",
1330 name
, start_offset
+ p
- p_start
);
1331 pc_offset
= p
- p_start
+ offset
+ 8;
1332 if (pc_offset
<= (p
- p_start
) ||
1333 pc_offset
>= (p_end
- p_start
))
1334 error("%s:%04x: pc offset must point inside the function code",
1335 name
, start_offset
+ p
- p_start
);
1336 if (pc_offset
< min_offset
)
1337 min_offset
= pc_offset
;
1339 /* The intruction position */
1340 fprintf(outfile
, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1342 /* The position of the constant pool data. */
1343 data_index
= ((p_end
- p_start
) - pc_offset
) >> 2;
1344 fprintf(outfile
, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1346 fprintf(outfile
, " arm_ldr_ptr->type = %d;\n", type
);
1347 fprintf(outfile
, " arm_ldr_ptr++;\n");
1353 /* Copy and relocate the constant pool data. */
1354 data_size
= (p_end
- p_start
) - min_offset
;
1355 if (data_size
> 0 && outfile
) {
1356 spare
+= min_offset
;
1357 fprintf(outfile
, " arm_data_ptr -= %d;\n", data_size
>> 2);
1358 fprintf(outfile
, " arm_pool_ptr -= %d;\n", data_size
);
1359 fprintf(outfile
, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1360 " arm_pool_ptr = gen_code_ptr + %d;\n",
1364 for (pc_offset
= min_offset
;
1365 pc_offset
< p_end
- p_start
;
1369 int i
, addend
, type
;
1370 const char *sym_name
;
1374 addend
= get32((uint32_t *)(p_start
+ pc_offset
));
1376 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1377 if (rel
->r_offset
== (pc_offset
+ start_offset
)) {
1378 sym_name
= get_rel_sym_name(rel
);
1379 /* the compiler leave some unnecessary references to the code */
1380 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1381 type
= ELF32_R_TYPE(rel
->r_info
);
1382 if (type
!= R_ARM_ABS32
)
1383 error("%s: unsupported data relocation", name
);
1387 fprintf(outfile
, " arm_data_ptr[%d] = 0x%x",
1388 data_index
, addend
);
1389 if (relname
[0] != '\0')
1390 fprintf(outfile
, " + %s", relname
);
1391 fprintf(outfile
, ";\n");
1400 insn
= get32((uint32_t *)p
);
1401 /* The last instruction must be an ldm instruction. There are several
1402 forms generated by gcc:
1403 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1405 ldmea fp, {..., pc} */
1406 if ((insn
& 0xffff8000) == 0xe99d8000) {
1409 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1413 } else if ((insn
& 0xffff8000) != 0xe89d8000
1414 && (insn
& 0xffff8000) != 0xe91b8000) {
1417 printf("%s: invalid epilog\n", name
);
1426 /* generate op code */
1427 void gen_code(const char *name
, host_ulong offset
, host_ulong size
,
1428 FILE *outfile
, int gen_switch
)
1431 uint8_t *p_start
, *p_end
;
1432 host_ulong start_offset
;
1434 uint8_t args_present
[MAX_ARGS
];
1435 const char *sym_name
, *p
;
1438 /* Compute exact size excluding prologue and epilogue instructions.
1439 * Increment start_offset to skip epilogue instructions, then compute
1440 * copy_size the indicate the size of the remaining instructions (in
1443 p_start
= text
+ offset
;
1444 p_end
= p_start
+ size
;
1445 start_offset
= offset
;
1446 #if defined(HOST_I386) || defined(HOST_X86_64)
1447 #ifdef CONFIG_FORMAT_COFF
1452 error("empty code for %s", name
);
1453 while (*p
!= 0xc3) {
1456 error("ret or jmp expected at the end of %s", name
);
1458 copy_size
= p
- p_start
;
1463 len
= p_end
- p_start
;
1465 error("empty code for %s", name
);
1466 if (p_end
[-1] == 0xc3) {
1469 error("ret or jmp expected at the end of %s", name
);
1474 #elif defined(HOST_PPC)
1477 p
= (void *)(p_end
- 4);
1479 error("empty code for %s", name
);
1480 if (get32((uint32_t *)p
) != 0x4e800020)
1481 error("blr expected at the end of %s", name
);
1482 copy_size
= p
- p_start
;
1484 #elif defined(HOST_S390)
1487 p
= (void *)(p_end
- 2);
1489 error("empty code for %s", name
);
1490 if (get16((uint16_t *)p
) != 0x07fe && get16((uint16_t *)p
) != 0x07f4)
1491 error("br %%r14 expected at the end of %s", name
);
1492 copy_size
= p
- p_start
;
1494 #elif defined(HOST_ALPHA)
1499 /* XXX: check why it occurs */
1501 error("empty code for %s", name
);
1503 if (get32((uint32_t *)p
) != 0x6bfa8001)
1504 error("ret expected at the end of %s", name
);
1505 copy_size
= p
- p_start
;
1507 #elif defined(HOST_IA64)
1510 p
= (void *)(p_end
- 4);
1512 error("empty code for %s", name
);
1513 /* br.ret.sptk.many b0;; */
1515 if (get32((uint32_t *)p
) != 0x00840008)
1516 error("br.ret.sptk.many b0;; expected at the end of %s", name
);
1517 copy_size
= p_end
- p_start
;
1519 #elif defined(HOST_SPARC)
1521 #define INSN_SAVE 0x9de3a000
1522 #define INSN_RET 0x81c7e008
1523 #define INSN_RETL 0x81c3e008
1524 #define INSN_RESTORE 0x81e80000
1525 #define INSN_RETURN 0x81cfe008
1526 #define INSN_NOP 0x01000000
1527 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1528 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1530 uint32_t start_insn
, end_insn1
, end_insn2
;
1532 p
= (void *)(p_end
- 8);
1534 error("empty code for %s", name
);
1535 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1536 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1537 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1538 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1539 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1541 start_offset
+= 0x4;
1542 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1543 /* SPARC v7: ret; restore; */ ;
1544 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1545 /* SPARC v9: return; nop; */ ;
1546 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1547 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1550 error("ret; restore; not found at end of %s", name
);
1551 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1554 error("No save at the beginning of %s", name
);
1557 /* Skip a preceeding nop, if present. */
1559 skip_insn
= get32((uint32_t *)(p
- 0x4));
1560 if (skip_insn
== INSN_NOP
)
1564 copy_size
= p
- p_start
;
1566 #elif defined(HOST_SPARC64)
1568 #define INSN_SAVE 0x9de3a000
1569 #define INSN_RET 0x81c7e008
1570 #define INSN_RETL 0x81c3e008
1571 #define INSN_RESTORE 0x81e80000
1572 #define INSN_RETURN 0x81cfe008
1573 #define INSN_NOP 0x01000000
1574 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1575 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1577 uint32_t start_insn
, end_insn1
, end_insn2
, skip_insn
;
1579 p
= (void *)(p_end
- 8);
1581 /* XXX: check why it occurs */
1583 error("empty code for %s", name
);
1585 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1586 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1587 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1588 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1589 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1591 start_offset
+= 0x4;
1592 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1593 /* SPARC v7: ret; restore; */ ;
1594 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1595 /* SPARC v9: return; nop; */ ;
1596 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1597 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1600 error("ret; restore; not found at end of %s", name
);
1601 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1604 error("No save at the beginning of %s", name
);
1607 /* Skip a preceeding nop, if present. */
1609 skip_insn
= get32((uint32_t *)(p
- 0x4));
1610 if (skip_insn
== 0x01000000)
1614 copy_size
= p
- p_start
;
1616 #elif defined(HOST_ARM)
1620 if ((p_end
- p_start
) <= 16)
1621 error("%s: function too small", name
);
1622 if (get32((uint32_t *)p_start
) != 0xe1a0c00d ||
1623 (get32((uint32_t *)(p_start
+ 4)) & 0xffff0000) != 0xe92d0000 ||
1624 get32((uint32_t *)(p_start
+ 8)) != 0xe24cb004)
1625 error("%s: invalid prolog", name
);
1628 insn
= get32((uint32_t *)p_start
);
1629 if ((insn
& 0xffffff00) == 0xe24dd000) {
1630 /* Stack adjustment. Assume op uses the frame pointer. */
1634 copy_size
= arm_emit_ldr_info(name
, start_offset
, NULL
, p_start
, p_end
,
1637 #elif defined(HOST_M68K)
1640 p
= (void *)(p_end
- 2);
1642 error("empty code for %s", name
);
1643 // remove NOP's, probably added for alignment
1644 while ((get16((uint16_t *)p
) == 0x4e71) &&
1647 if (get16((uint16_t *)p
) != 0x4e75)
1648 error("rts expected at the end of %s", name
);
1649 copy_size
= p
- p_start
;
1651 #elif defined(HOST_MIPS)
1653 #define INSN_RETURN 0x03e00008
1654 #define INSN_NOP 0x00000000
1658 if (p
< (p_start
+ 0x8)) {
1659 error("empty code for %s", name
);
1661 uint32_t end_insn1
, end_insn2
;
1664 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1665 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1666 if (end_insn1
!= INSN_RETURN
&& end_insn2
!= INSN_NOP
)
1667 error("jr ra not found at end of %s", name
);
1669 copy_size
= p
- p_start
;
1672 #error unsupported CPU
1675 /* compute the number of arguments by looking at the relocations */
1676 for(i
= 0;i
< MAX_ARGS
; i
++)
1677 args_present
[i
] = 0;
1679 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1680 host_ulong offset
= get_rel_offset(rel
);
1681 if (offset
>= start_offset
&&
1682 offset
< start_offset
+ (p_end
- p_start
)) {
1683 sym_name
= get_rel_sym_name(rel
);
1686 if (strstart(sym_name
, "__op_param", &p
) ||
1687 strstart(sym_name
, "__op_gen_label", &p
)) {
1688 n
= strtoul(p
, NULL
, 10);
1690 error("too many arguments in %s", name
);
1691 args_present
[n
- 1] = 1;
1697 while (nb_args
< MAX_ARGS
&& args_present
[nb_args
])
1699 for(i
= nb_args
; i
< MAX_ARGS
; i
++) {
1700 if (args_present
[i
])
1701 error("inconsistent argument numbering in %s", name
);
1704 if (gen_switch
== 2) {
1705 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, copy_size
);
1706 } else if (gen_switch
== 1) {
1709 fprintf(outfile
, "case INDEX_%s: {\n", name
);
1711 fprintf(outfile
, " long ");
1712 for(i
= 0; i
< nb_args
; i
++) {
1714 fprintf(outfile
, ", ");
1715 fprintf(outfile
, "param%d", i
+ 1);
1717 fprintf(outfile
, ";\n");
1719 #if defined(HOST_IA64)
1720 fprintf(outfile
, " extern char %s;\n", name
);
1722 fprintf(outfile
, " extern void %s();\n", name
);
1725 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1726 host_ulong offset
= get_rel_offset(rel
);
1727 if (offset
>= start_offset
&&
1728 offset
< start_offset
+ (p_end
- p_start
)) {
1729 sym_name
= get_rel_sym_name(rel
);
1733 !strstart(sym_name
, "__op_param", NULL
) &&
1734 !strstart(sym_name
, "__op_jmp", NULL
) &&
1735 !strstart(sym_name
, "__op_gen_label", NULL
)) {
1736 #if defined(HOST_SPARC)
1737 if (sym_name
[0] == '.') {
1739 "extern char __dot_%s __asm__(\"%s\");\n",
1740 sym_name
+1, sym_name
);
1744 #if defined(__APPLE__)
1745 /* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
1746 fprintf(outfile
, "extern char %s __attribute__((unused));\n", sym_name
);
1747 #elif defined(HOST_IA64)
1748 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
1750 * PCREL21 br.call targets generally
1751 * are out of range and need to go
1752 * through an "import stub".
1754 fprintf(outfile
, " extern char %s;\n",
1757 fprintf(outfile
, "extern char %s;\n", sym_name
);
1763 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1764 name
, (int)(start_offset
- offset
), copy_size
);
1766 /* emit code offset information */
1769 const char *sym_name
, *p
;
1773 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
1774 sym_name
= get_sym_name(sym
);
1775 if (strstart(sym_name
, "__op_label", &p
)) {
1777 unsigned long offset
;
1779 /* test if the variable refers to a label inside
1780 the code we are generating */
1781 #ifdef CONFIG_FORMAT_COFF
1782 if (sym
->st_shndx
== text_shndx
) {
1783 ptr
= sdata
[coff_text_shndx
];
1784 } else if (sym
->st_shndx
== data_shndx
) {
1785 ptr
= sdata
[coff_data_shndx
];
1789 #elif defined(CONFIG_FORMAT_MACH)
1792 ptr
= sdata
[sym
->n_sect
-1];
1794 ptr
= sdata
[sym
->st_shndx
];
1797 error("__op_labelN in invalid section");
1798 offset
= sym
->st_value
;
1799 #ifdef CONFIG_FORMAT_MACH
1800 offset
-= section_hdr
[sym
->n_sect
-1].addr
;
1802 val
= *(host_ulong
*)(ptr
+ offset
);
1803 #ifdef ELF_USES_RELOCA
1805 int reloc_shndx
, nb_relocs1
, j
;
1807 /* try to find a matching relocation */
1808 reloc_shndx
= find_reloc(sym
->st_shndx
);
1810 nb_relocs1
= shdr
[reloc_shndx
].sh_size
/
1811 shdr
[reloc_shndx
].sh_entsize
;
1812 rel
= (ELF_RELOC
*)sdata
[reloc_shndx
];
1813 for(j
= 0; j
< nb_relocs1
; j
++) {
1814 if (rel
->r_offset
== offset
) {
1815 val
= rel
->r_addend
;
1823 if (val
>= start_offset
&& val
<= start_offset
+ copy_size
) {
1824 n
= strtol(p
, NULL
, 10);
1825 fprintf(outfile
, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n
, (long)(val
- start_offset
));
1831 /* load parameres in variables */
1832 for(i
= 0; i
< nb_args
; i
++) {
1833 fprintf(outfile
, " param%d = *opparam_ptr++;\n", i
+ 1);
1836 /* patch relocations */
1837 #if defined(HOST_I386)
1843 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1844 if (rel
->r_offset
>= start_offset
&&
1845 rel
->r_offset
< start_offset
+ copy_size
) {
1846 sym_name
= get_rel_sym_name(rel
);
1849 reloc_offset
= rel
->r_offset
- start_offset
;
1850 if (strstart(sym_name
, "__op_jmp", &p
)) {
1852 n
= strtol(p
, NULL
, 10);
1853 /* __op_jmp relocations are done at
1854 runtime to do translated block
1855 chaining: the offset of the instruction
1856 needs to be stored */
1857 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1862 get_reloc_expr(name
, sizeof(name
), sym_name
);
1863 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
1864 #ifdef CONFIG_FORMAT_ELF
1865 type
= ELF32_R_TYPE(rel
->r_info
);
1868 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1869 reloc_offset
, name
, addend
);
1872 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1873 reloc_offset
, name
, reloc_offset
, addend
);
1876 error("unsupported i386 relocation (%d)", type
);
1878 #elif defined(CONFIG_FORMAT_COFF)
1883 temp_name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
1884 if (!strcmp(temp_name
, ".data")) {
1885 for (j
= 0, sym
= symtab
; j
< nb_syms
; j
++, sym
++) {
1886 if (strstart(sym
->st_name
, sym_name
, NULL
)) {
1887 addend
-= sym
->st_value
;
1895 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1896 reloc_offset
, name
, addend
);
1899 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1900 reloc_offset
, name
, reloc_offset
, addend
);
1903 error("unsupported i386 relocation (%d)", type
);
1906 #error unsupport object format
1911 #elif defined(HOST_X86_64)
1917 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1918 if (rel
->r_offset
>= start_offset
&&
1919 rel
->r_offset
< start_offset
+ copy_size
) {
1920 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1921 get_reloc_expr(name
, sizeof(name
), sym_name
);
1922 type
= ELF32_R_TYPE(rel
->r_info
);
1923 addend
= rel
->r_addend
;
1924 reloc_offset
= rel
->r_offset
- start_offset
;
1927 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1928 reloc_offset
, name
, addend
);
1931 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1932 reloc_offset
, name
, addend
);
1935 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1936 reloc_offset
, name
, reloc_offset
, addend
);
1939 error("unsupported X86_64 relocation (%d)", type
);
1944 #elif defined(HOST_PPC)
1946 #ifdef CONFIG_FORMAT_ELF
1951 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1952 if (rel
->r_offset
>= start_offset
&&
1953 rel
->r_offset
< start_offset
+ copy_size
) {
1954 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1955 reloc_offset
= rel
->r_offset
- start_offset
;
1956 if (strstart(sym_name
, "__op_jmp", &p
)) {
1958 n
= strtol(p
, NULL
, 10);
1959 /* __op_jmp relocations are done at
1960 runtime to do translated block
1961 chaining: the offset of the instruction
1962 needs to be stored */
1963 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1968 get_reloc_expr(name
, sizeof(name
), sym_name
);
1969 type
= ELF32_R_TYPE(rel
->r_info
);
1970 addend
= rel
->r_addend
;
1973 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1974 reloc_offset
, name
, addend
);
1976 case R_PPC_ADDR16_LO
:
1977 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1978 reloc_offset
, name
, addend
);
1980 case R_PPC_ADDR16_HI
:
1981 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1982 reloc_offset
, name
, addend
);
1984 case R_PPC_ADDR16_HA
:
1985 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1986 reloc_offset
, name
, addend
);
1989 /* warning: must be at 32 MB distancy */
1990 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
1991 reloc_offset
, reloc_offset
, name
, reloc_offset
, addend
);
1994 error("unsupported powerpc relocation (%d)", type
);
1998 #elif defined(CONFIG_FORMAT_MACH)
1999 struct scattered_relocation_info
*scarel
;
2000 struct relocation_info
* rel
;
2001 char final_sym_name
[256];
2002 const char *sym_name
;
2007 for(i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2008 unsigned int offset
, length
, value
= 0;
2009 unsigned int type
, pcrel
, isym
= 0;
2010 unsigned int usesym
= 0;
2012 if(R_SCATTERED
& rel
->r_address
) {
2013 scarel
= (struct scattered_relocation_info
*)rel
;
2014 offset
= (unsigned int)scarel
->r_address
;
2015 length
= scarel
->r_length
;
2016 pcrel
= scarel
->r_pcrel
;
2017 type
= scarel
->r_type
;
2018 value
= scarel
->r_value
;
2020 value
= isym
= rel
->r_symbolnum
;
2021 usesym
= (rel
->r_extern
);
2022 offset
= rel
->r_address
;
2023 length
= rel
->r_length
;
2024 pcrel
= rel
->r_pcrel
;
2028 slide
= offset
- start_offset
;
2030 if (!(offset
>= start_offset
&& offset
< start_offset
+ size
))
2031 continue; /* not in our range */
2033 sym_name
= get_reloc_name(rel
, &sslide
);
2035 if(usesym
&& symtab
[isym
].n_type
& N_STAB
)
2036 continue; /* don't handle STAB (debug sym) */
2038 if (sym_name
&& strstart(sym_name
, "__op_jmp", &p
)) {
2040 n
= strtol(p
, NULL
, 10);
2041 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2043 continue; /* Nothing more to do */
2048 fprintf(outfile
, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2049 name
, value
, usesym
? "use sym" : "don't use sym", offset
, length
, pcrel
? "pcrel":"", type
);
2050 continue; /* dunno how to handle without final_sym_name */
2053 get_reloc_expr(final_sym_name
, sizeof(final_sym_name
),
2056 case PPC_RELOC_BR24
:
2057 if (!strstart(sym_name
,"__op_gen_label",&p
)) {
2058 fprintf(outfile
, "{\n");
2059 fprintf(outfile
, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide
);
2060 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",
2061 slide
, slide
, name
, sslide
);
2062 fprintf(outfile
, "}\n");
2064 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2065 slide
, slide
, final_sym_name
, slide
);
2068 case PPC_RELOC_HI16
:
2069 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2070 slide
, final_sym_name
, sslide
);
2072 case PPC_RELOC_LO16
:
2073 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2074 slide
, final_sym_name
, sslide
);
2076 case PPC_RELOC_HA16
:
2077 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2078 slide
, final_sym_name
, sslide
);
2081 error("unsupported powerpc relocation (%d)", type
);
2085 #error unsupport object format
2088 #elif defined(HOST_S390)
2094 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2095 if (rel
->r_offset
>= start_offset
&&
2096 rel
->r_offset
< start_offset
+ copy_size
) {
2097 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2098 get_reloc_expr(name
, sizeof(name
), sym_name
);
2099 type
= ELF32_R_TYPE(rel
->r_info
);
2100 addend
= rel
->r_addend
;
2101 reloc_offset
= rel
->r_offset
- start_offset
;
2104 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2105 reloc_offset
, name
, addend
);
2108 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2109 reloc_offset
, name
, addend
);
2112 fprintf(outfile
, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2113 reloc_offset
, name
, addend
);
2116 error("unsupported s390 relocation (%d)", type
);
2121 #elif defined(HOST_ALPHA)
2123 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2124 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2128 type
= ELF64_R_TYPE(rel
->r_info
);
2129 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2130 reloc_offset
= rel
->r_offset
- start_offset
;
2132 case R_ALPHA_GPDISP
:
2133 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2134 as an immediate instead of constructing it from the pv or ra. */
2135 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2137 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2138 reloc_offset
+ (int)rel
->r_addend
);
2140 case R_ALPHA_LITUSE
:
2141 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2142 now, since some called functions (libc) need pv to be set up. */
2145 /* Branch target prediction hint. Ignore for now. Should be already
2146 correct for in-function jumps. */
2148 case R_ALPHA_LITERAL
:
2149 /* Load a literal from the GOT relative to the gp. Since there's only a
2150 single gp, nothing is to be done. */
2152 case R_ALPHA_GPRELHIGH
:
2153 /* Handle fake relocations against __op_param symbol. Need to emit the
2154 high part of the immediate value instead. Other symbols need no
2155 special treatment. */
2156 if (strstart(sym_name
, "__op_param", &p
))
2157 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2160 case R_ALPHA_GPRELLOW
:
2161 if (strstart(sym_name
, "__op_param", &p
))
2162 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2166 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2167 set up the gp from the pv. */
2168 fprintf(outfile
, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2169 reloc_offset
, sym_name
, reloc_offset
);
2172 error("unsupported Alpha relocation (%d)", type
);
2177 #elif defined(HOST_IA64)
2179 unsigned long sym_idx
;
2185 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2186 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2187 if (rel
->r_offset
< start_offset
2188 || rel
->r_offset
>= start_offset
+ copy_size
)
2190 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2191 code_offset
= rel
->r_offset
- start_offset
;
2192 if (strstart(sym_name
, "__op_jmp", &p
)) {
2194 n
= strtol(p
, NULL
, 10);
2195 /* __op_jmp relocations are done at
2196 runtime to do translated block
2197 chaining: the offset of the instruction
2198 needs to be stored */
2199 fprintf(outfile
, " jmp_offsets[%d] ="
2200 "%ld + (gen_code_ptr - gen_code_buf);\n",
2204 get_reloc_expr(name
, sizeof(name
), sym_name
);
2205 type
= ELF64_R_TYPE(rel
->r_info
);
2206 addend
= rel
->r_addend
;
2210 " ia64_imm64(gen_code_ptr + %ld, "
2212 code_offset
, name
, addend
);
2214 case R_IA64_LTOFF22X
:
2215 case R_IA64_LTOFF22
:
2216 fprintf(outfile
, " IA64_LTOFF(gen_code_ptr + %ld,"
2217 " %s + %ld, %d);\n",
2218 code_offset
, name
, addend
,
2219 (type
== R_IA64_LTOFF22X
));
2223 " ia64_ldxmov(gen_code_ptr + %ld,"
2224 " %s + %ld);\n", code_offset
, name
, addend
);
2227 case R_IA64_PCREL21B
:
2228 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2230 " ia64_imm21b(gen_code_ptr + %ld,"
2231 " (long) (%s + %ld -\n\t\t"
2232 "((long) gen_code_ptr + %ld)) >> 4);\n",
2233 code_offset
, name
, addend
,
2234 code_offset
& ~0xfUL
);
2237 " IA64_PLT(gen_code_ptr + %ld, "
2238 "%d);\t/* %s + %ld */\n",
2240 get_plt_index(sym_name
, addend
),
2245 error("unsupported ia64 relocation (0x%x)",
2249 fprintf(outfile
, " ia64_nop_b(gen_code_ptr + %d);\n",
2250 copy_size
- 16 + 2);
2252 #elif defined(HOST_SPARC)
2258 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2259 if (rel
->r_offset
>= start_offset
&&
2260 rel
->r_offset
< start_offset
+ copy_size
) {
2261 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2262 get_reloc_expr(name
, sizeof(name
), sym_name
);
2263 type
= ELF32_R_TYPE(rel
->r_info
);
2264 addend
= rel
->r_addend
;
2265 reloc_offset
= rel
->r_offset
- start_offset
;
2268 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2269 reloc_offset
, name
, addend
);
2273 " *(uint32_t *)(gen_code_ptr + %d) = "
2274 "((*(uint32_t *)(gen_code_ptr + %d)) "
2276 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2277 reloc_offset
, reloc_offset
, name
, addend
);
2281 " *(uint32_t *)(gen_code_ptr + %d) = "
2282 "((*(uint32_t *)(gen_code_ptr + %d)) "
2284 " | ((%s + %d) & 0x3ff);\n",
2285 reloc_offset
, reloc_offset
, name
, addend
);
2287 case R_SPARC_WDISP30
:
2289 " *(uint32_t *)(gen_code_ptr + %d) = "
2290 "((*(uint32_t *)(gen_code_ptr + %d)) "
2292 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2293 " & 0x3fffffff);\n",
2294 reloc_offset
, reloc_offset
, name
, addend
,
2297 case R_SPARC_WDISP22
:
2299 " *(uint32_t *)(gen_code_ptr + %d) = "
2300 "((*(uint32_t *)(gen_code_ptr + %d)) "
2302 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2304 rel
->r_offset
- start_offset
,
2305 rel
->r_offset
- start_offset
,
2307 rel
->r_offset
- start_offset
);
2310 error("unsupported sparc relocation (%d)", type
);
2315 #elif defined(HOST_SPARC64)
2321 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2322 if (rel
->r_offset
>= start_offset
&&
2323 rel
->r_offset
< start_offset
+ copy_size
) {
2324 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2325 get_reloc_expr(name
, sizeof(name
), sym_name
);
2326 type
= ELF32_R_TYPE(rel
->r_info
);
2327 addend
= rel
->r_addend
;
2328 reloc_offset
= rel
->r_offset
- start_offset
;
2331 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2332 reloc_offset
, name
, addend
);
2336 " *(uint32_t *)(gen_code_ptr + %d) = "
2337 "((*(uint32_t *)(gen_code_ptr + %d)) "
2339 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2340 reloc_offset
, reloc_offset
, name
, addend
);
2344 " *(uint32_t *)(gen_code_ptr + %d) = "
2345 "((*(uint32_t *)(gen_code_ptr + %d)) "
2347 " | ((%s + %d) & 0x3ff);\n",
2348 reloc_offset
, reloc_offset
, name
, addend
);
2351 addend
+= ELF64_R_TYPE_DATA (rel
->r_info
);
2353 " *(uint32_t *)(gen_code_ptr + %d) = "
2354 "((*(uint32_t *)(gen_code_ptr + %d)) "
2356 " | ((%s + %d) & 0x3ff);\n",
2357 reloc_offset
, reloc_offset
, name
, addend
);
2359 case R_SPARC_WDISP30
:
2361 " *(uint32_t *)(gen_code_ptr + %d) = "
2362 "((*(uint32_t *)(gen_code_ptr + %d)) "
2364 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2365 " & 0x3fffffff);\n",
2366 reloc_offset
, reloc_offset
, name
, addend
,
2369 case R_SPARC_WDISP22
:
2371 " *(uint32_t *)(gen_code_ptr + %d) = "
2372 "((*(uint32_t *)(gen_code_ptr + %d)) "
2374 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2376 reloc_offset
, reloc_offset
, name
, addend
,
2381 " *(uint32_t *)(gen_code_ptr + %d) = "
2382 "((*(uint32_t *)(gen_code_ptr + %d)) "
2384 " | (((%s + %d) >> 42) & 0x00000000);\n",
2385 reloc_offset
, reloc_offset
, name
, addend
);
2390 " *(uint32_t *)(gen_code_ptr + %d) = "
2391 "((*(uint32_t *)(gen_code_ptr + %d)) "
2393 " | (((%s + %d) >> 10) & 0x00000000);\n",
2394 reloc_offset
, reloc_offset
, name
, addend
);
2399 " *(uint32_t *)(gen_code_ptr + %d) = "
2400 "((*(uint32_t *)(gen_code_ptr + %d)) "
2402 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2403 reloc_offset
, reloc_offset
, name
, addend
);
2407 error("unsupported sparc64 relocation (%d) for symbol %s", type
, name
);
2412 #elif defined(HOST_ARM)
2420 insn
= get32((uint32_t *)(p_start
+ 4));
2421 /* If prologue ends in sub sp, sp, #const then assume
2422 op has a stack frame and needs the frame pointer. */
2423 if ((insn
& 0xffffff00) == 0xe24dd000) {
2426 opcode
= 0xe28db000; /* add fp, sp, #0. */
2428 /* ??? Need to undo the extra stack adjustment at the end of the op.
2429 For now just leave the stack misaligned and hope it doesn't break anything
2431 if ((insn
& 4) != 0) {
2432 /* Preserve doubleword stack alignment. */
2434 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2439 insn
= get32((uint32_t *)(p_start
- 4));
2440 /* Calculate the size of the saved registers,
2442 for (i
= 0; i
< 15; i
++) {
2443 if (insn
& (1 << i
))
2447 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode
);
2449 arm_emit_ldr_info(name
, start_offset
, outfile
, p_start
, p_end
,
2452 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2453 if (rel
->r_offset
>= start_offset
&&
2454 rel
->r_offset
< start_offset
+ copy_size
) {
2455 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2456 /* the compiler leave some unnecessary references to the code */
2457 if (sym_name
[0] == '\0')
2459 get_reloc_expr(name
, sizeof(name
), sym_name
);
2460 type
= ELF32_R_TYPE(rel
->r_info
);
2461 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2462 reloc_offset
= rel
->r_offset
- start_offset
;
2465 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2466 reloc_offset
, name
, addend
);
2471 fprintf(outfile
, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2472 reloc_offset
, addend
, name
);
2475 error("unsupported arm relocation (%d)", type
);
2480 #elif defined(HOST_M68K)
2487 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2488 if (rel
->r_offset
>= start_offset
&&
2489 rel
->r_offset
< start_offset
+ copy_size
) {
2490 sym
= &(symtab
[ELFW(R_SYM
)(rel
->r_info
)]);
2491 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2492 get_reloc_expr(name
, sizeof(name
), sym_name
);
2493 type
= ELF32_R_TYPE(rel
->r_info
);
2494 addend
= get32((uint32_t *)(text
+ rel
->r_offset
)) + rel
->r_addend
;
2495 reloc_offset
= rel
->r_offset
- start_offset
;
2498 fprintf(outfile
, " /* R_68K_32 RELOC, offset %x */\n", rel
->r_offset
) ;
2499 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2500 reloc_offset
, name
, addend
);
2503 fprintf(outfile
, " /* R_68K_PC32 RELOC, offset %x */\n", rel
->r_offset
);
2504 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2505 reloc_offset
, name
, reloc_offset
, /*sym->st_value+*/ addend
);
2508 error("unsupported m68k relocation (%d)", type
);
2513 #elif defined(HOST_MIPS)
2515 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2516 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2522 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2523 /* the compiler leave some unnecessary references to the code */
2524 if (sym_name
[0] == '\0')
2526 get_reloc_expr(name
, sizeof(name
), sym_name
);
2527 type
= ELF32_R_TYPE(rel
->r_info
);
2528 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2529 reloc_offset
= rel
->r_offset
- start_offset
;
2532 fprintf(outfile
, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2533 rel
->r_offset
, sym_name
);
2535 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2536 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2538 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2539 reloc_offset
, reloc_offset
, name
);
2542 fprintf(outfile
, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2543 rel
->r_offset
, sym_name
);
2545 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2546 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2548 " | (%s & 0xffff);\n",
2549 reloc_offset
, reloc_offset
, name
);
2552 fprintf(outfile
, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2553 rel
->r_offset
, sym_name
);
2555 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2557 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2559 reloc_offset
, addend
, addend
, name
, reloc_offset
);
2563 fprintf(outfile
, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2564 rel
->r_offset
, sym_name
);
2566 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2567 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2569 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2570 reloc_offset
, reloc_offset
, name
);
2573 error("unsupported MIPS relocation (%d)", type
);
2579 #error unsupported CPU
2581 fprintf(outfile
, " gen_code_ptr += %d;\n", copy_size
);
2582 fprintf(outfile
, "}\n");
2583 fprintf(outfile
, "break;\n\n");
2585 fprintf(outfile
, "static inline void gen_%s(", name
);
2587 fprintf(outfile
, "void");
2589 for(i
= 0; i
< nb_args
; i
++) {
2591 fprintf(outfile
, ", ");
2592 fprintf(outfile
, "long param%d", i
+ 1);
2595 fprintf(outfile
, ")\n");
2596 fprintf(outfile
, "{\n");
2597 for(i
= 0; i
< nb_args
; i
++) {
2598 fprintf(outfile
, " *gen_opparam_ptr++ = param%d;\n", i
+ 1);
2600 fprintf(outfile
, " *gen_opc_ptr++ = INDEX_%s;\n", name
);
2601 fprintf(outfile
, "}\n\n");
2605 int gen_file(FILE *outfile
, int out_type
)
2610 if (out_type
== OUT_INDEX_OP
) {
2611 fprintf(outfile
, "DEF(end, 0, 0)\n");
2612 fprintf(outfile
, "DEF(nop, 0, 0)\n");
2613 fprintf(outfile
, "DEF(nop1, 1, 0)\n");
2614 fprintf(outfile
, "DEF(nop2, 2, 0)\n");
2615 fprintf(outfile
, "DEF(nop3, 3, 0)\n");
2616 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2618 name
= get_sym_name(sym
);
2619 if (strstart(name
, OP_PREFIX
, NULL
)) {
2620 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 2);
2623 } else if (out_type
== OUT_GEN_OP
) {
2624 /* generate gen_xxx functions */
2625 fprintf(outfile
, "#include \"dyngen-op.h\"\n");
2626 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2628 name
= get_sym_name(sym
);
2629 if (strstart(name
, OP_PREFIX
, NULL
)) {
2630 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2631 if (sym
->st_shndx
!= text_shndx
)
2632 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2634 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 0);
2639 /* generate big code generation switch */
2642 /* We need to know the size of all the ops so we can figure out when
2643 to emit constant pools. This must be consistent with opc.h. */
2645 "static const uint32_t arm_opc_size[] = {\n"
2650 " 0,\n"); /* nop3 */
2651 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2653 name
= get_sym_name(sym
);
2654 if (strstart(name
, OP_PREFIX
, NULL
)) {
2655 fprintf(outfile
, " %d,\n", sym
->st_size
);
2663 "int dyngen_code(uint8_t *gen_code_buf,\n"
2664 " uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2665 " const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2667 " uint8_t *gen_code_ptr;\n"
2668 " const uint16_t *opc_ptr;\n"
2669 " const uint32_t *opparam_ptr;\n");
2672 /* Arm is tricky because it uses constant pools for loading immediate values.
2673 We assume (and require) each function is code followed by a constant pool.
2674 All the ops are small so this should be ok. For each op we figure
2675 out how much "spare" range we have in the load instructions. This allows
2676 us to insert subsequent ops in between the op and the constant pool,
2677 eliminating the neeed to jump around the pool.
2679 We currently generate:
2681 [ For this example we assume merging would move op1_pool out of range.
2682 In practice we should be able to combine many ops before the offset
2683 limits are reached. ]
2694 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2697 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2698 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2699 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2700 /* Initialise the parmissible pool offset to an arbitary large value. */
2701 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2705 long addend
, not_first
= 0;
2706 unsigned long sym_idx
;
2707 int index
, max_index
;
2708 const char *sym_name
;
2712 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2713 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2714 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2715 if (strstart(sym_name
, "__op_gen_label", NULL
))
2717 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2720 addend
= rel
->r_addend
;
2721 index
= get_plt_index(sym_name
, addend
);
2722 if (index
<= max_index
)
2725 fprintf(outfile
, " extern void %s(void);\n", sym_name
);
2729 " struct ia64_fixup *plt_fixes = NULL, "
2730 "*ltoff_fixes = NULL;\n"
2731 " static long plt_target[] = {\n\t");
2734 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2735 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2736 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2737 if (strstart(sym_name
, "__op_gen_label", NULL
))
2739 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2742 addend
= rel
->r_addend
;
2743 index
= get_plt_index(sym_name
, addend
);
2744 if (index
<= max_index
)
2749 fprintf(outfile
, ",\n\t");
2752 fprintf(outfile
, "(long) &%s + %ld", sym_name
, addend
);
2754 fprintf(outfile
, "(long) &%s", sym_name
);
2756 fprintf(outfile
, "\n };\n"
2757 " unsigned int plt_offset[%u] = { 0 };\n", max_index
+ 1);
2763 " gen_code_ptr = gen_code_buf;\n"
2764 " opc_ptr = opc_buf;\n"
2765 " opparam_ptr = opparam_buf;\n");
2767 /* Generate prologue, if needed. */
2773 /* Generate constant pool if needed */
2775 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2776 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2777 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2778 " last_gen_code_ptr = gen_code_ptr;\n"
2779 " arm_ldr_ptr = arm_ldr_table;\n"
2780 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2781 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2786 " switch(*opc_ptr++) {\n");
2788 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2790 name
= get_sym_name(sym
);
2791 if (strstart(name
, OP_PREFIX
, NULL
)) {
2793 printf("%4d: %s pos=0x%08x len=%d\n",
2794 i
, name
, sym
->st_value
, sym
->st_size
);
2796 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2797 if (sym
->st_shndx
!= text_shndx
)
2798 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2800 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 1);
2805 " case INDEX_op_nop:\n"
2807 " case INDEX_op_nop1:\n"
2810 " case INDEX_op_nop2:\n"
2811 " opparam_ptr += 2;\n"
2813 " case INDEX_op_nop3:\n"
2814 " opparam_ptr += 3;\n"
2828 " extern char code_gen_buffer[];\n"
2829 " ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2830 "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2831 "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2832 "plt_target, plt_offset);\n }\n");
2835 /* generate some code patching */
2838 "if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2839 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2840 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2842 /* flush instruction cache */
2843 fprintf(outfile
, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2845 fprintf(outfile
, "return gen_code_ptr - gen_code_buf;\n");
2846 fprintf(outfile
, "}\n\n");
2855 printf("dyngen (c) 2003 Fabrice Bellard\n"
2856 "usage: dyngen [-o outfile] [-c] objfile\n"
2857 "Generate a dynamic code generator from an object file\n"
2858 "-c output enum of operations\n"
2859 "-g output gen_op_xx() functions\n"
2864 int main(int argc
, char **argv
)
2867 const char *filename
, *outfilename
;
2870 outfilename
= "out.c";
2871 out_type
= OUT_CODE
;
2873 c
= getopt(argc
, argv
, "ho:cg");
2881 outfilename
= optarg
;
2884 out_type
= OUT_INDEX_OP
;
2887 out_type
= OUT_GEN_OP
;
2893 filename
= argv
[optind
];
2894 outfile
= fopen(outfilename
, "w");
2896 error("could not open '%s'", outfilename
);
2898 load_object(filename
);
2899 gen_file(outfile
, out_type
);