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
121 #error unsupported CPU - please update the code
126 #if ELF_CLASS == ELFCLASS32
127 typedef int32_t host_long
;
128 typedef uint32_t host_ulong
;
129 #define swabls(x) swab32s(x)
130 #define swablss(x) swab32ss(x)
132 typedef int64_t host_long
;
133 typedef uint64_t host_ulong
;
134 #define swabls(x) swab64s(x)
135 #define swablss(x) swab64ss(x)
138 #ifdef ELF_USES_RELOCA
139 #define SHT_RELOC SHT_RELA
141 #define SHT_RELOC SHT_REL
144 #define EXE_RELOC ELF_RELOC
145 #define EXE_SYM ElfW(Sym)
147 #endif /* CONFIG_FORMAT_ELF */
149 #ifdef CONFIG_FORMAT_COFF
153 typedef int32_t host_long
;
154 typedef uint32_t host_ulong
;
156 #define FILENAMELEN 256
158 typedef struct coff_sym
{
159 struct external_syment
*st_syment
;
160 char st_name
[FILENAMELEN
];
167 typedef struct coff_rel
{
168 struct external_reloc
*r_reloc
;
173 #define EXE_RELOC struct coff_rel
174 #define EXE_SYM struct coff_sym
176 #endif /* CONFIG_FORMAT_COFF */
178 #ifdef CONFIG_FORMAT_MACH
180 #include <mach-o/loader.h>
181 #include <mach-o/nlist.h>
182 #include <mach-o/reloc.h>
183 #include <mach-o/ppc/reloc.h>
185 # define check_mach_header(x) (x.magic == MH_MAGIC)
186 typedef int32_t host_long
;
187 typedef uint32_t host_ulong
;
189 struct nlist_extended
195 unsigned char n_type
;
196 unsigned char n_sect
;
198 unsigned long st_value
;
199 unsigned long st_size
;
202 #define EXE_RELOC struct relocation_info
203 #define EXE_SYM struct nlist_extended
205 #endif /* CONFIG_FORMAT_MACH */
215 /* all dynamically generated functions begin with this code */
216 #define OP_PREFIX "op_"
220 void __attribute__((noreturn
)) __attribute__((format (printf
, 1, 2))) error(const char *fmt
, ...)
224 fprintf(stderr
, "dyngen: ");
225 vfprintf(stderr
, fmt
, ap
);
226 fprintf(stderr
, "\n");
231 void *load_data(int fd
, long offset
, unsigned int size
)
238 lseek(fd
, offset
, SEEK_SET
);
239 if (read(fd
, data
, size
) != size
) {
246 int strstart(const char *str
, const char *val
, const char **ptr
)
262 void pstrcpy(char *buf
, int buf_size
, const char *str
)
272 if (c
== 0 || q
>= buf
+ buf_size
- 1)
279 void swab16s(uint16_t *p
)
284 void swab32s(uint32_t *p
)
289 void swab32ss(int32_t *p
)
294 void swab64s(uint64_t *p
)
299 void swab64ss(int64_t *p
)
304 uint16_t get16(uint16_t *p
)
313 uint32_t get32(uint32_t *p
)
322 void put16(uint16_t *p
, uint16_t val
)
329 void put32(uint32_t *p
, uint32_t val
)
336 /* executable information */
344 #ifdef CONFIG_FORMAT_ELF
347 struct elf_shdr
*shdr
;
352 int elf_must_swap(struct elfhdr
*h
)
360 return (h
->e_ident
[EI_DATA
] == ELFDATA2MSB
) !=
361 (swaptest
.b
[0] == 0);
364 void elf_swap_ehdr(struct elfhdr
*h
)
366 swab16s(&h
->e_type
); /* Object file type */
367 swab16s(&h
-> e_machine
); /* Architecture */
368 swab32s(&h
-> e_version
); /* Object file version */
369 swabls(&h
-> e_entry
); /* Entry point virtual address */
370 swabls(&h
-> e_phoff
); /* Program header table file offset */
371 swabls(&h
-> e_shoff
); /* Section header table file offset */
372 swab32s(&h
-> e_flags
); /* Processor-specific flags */
373 swab16s(&h
-> e_ehsize
); /* ELF header size in bytes */
374 swab16s(&h
-> e_phentsize
); /* Program header table entry size */
375 swab16s(&h
-> e_phnum
); /* Program header table entry count */
376 swab16s(&h
-> e_shentsize
); /* Section header table entry size */
377 swab16s(&h
-> e_shnum
); /* Section header table entry count */
378 swab16s(&h
-> e_shstrndx
); /* Section header string table index */
381 void elf_swap_shdr(struct elf_shdr
*h
)
383 swab32s(&h
-> sh_name
); /* Section name (string tbl index) */
384 swab32s(&h
-> sh_type
); /* Section type */
385 swabls(&h
-> sh_flags
); /* Section flags */
386 swabls(&h
-> sh_addr
); /* Section virtual addr at execution */
387 swabls(&h
-> sh_offset
); /* Section file offset */
388 swabls(&h
-> sh_size
); /* Section size in bytes */
389 swab32s(&h
-> sh_link
); /* Link to another section */
390 swab32s(&h
-> sh_info
); /* Additional section information */
391 swabls(&h
-> sh_addralign
); /* Section alignment */
392 swabls(&h
-> sh_entsize
); /* Entry size if section holds table */
395 void elf_swap_phdr(struct elf_phdr
*h
)
397 swab32s(&h
->p_type
); /* Segment type */
398 swabls(&h
->p_offset
); /* Segment file offset */
399 swabls(&h
->p_vaddr
); /* Segment virtual address */
400 swabls(&h
->p_paddr
); /* Segment physical address */
401 swabls(&h
->p_filesz
); /* Segment size in file */
402 swabls(&h
->p_memsz
); /* Segment size in memory */
403 swab32s(&h
->p_flags
); /* Segment flags */
404 swabls(&h
->p_align
); /* Segment alignment */
407 void elf_swap_rel(ELF_RELOC
*rel
)
409 swabls(&rel
->r_offset
);
410 swabls(&rel
->r_info
);
411 #ifdef ELF_USES_RELOCA
412 swablss(&rel
->r_addend
);
416 struct elf_shdr
*find_elf_section(struct elf_shdr
*shdr
, int shnum
, const char *shstr
,
421 struct elf_shdr
*sec
;
423 for(i
= 0; i
< shnum
; i
++) {
427 shname
= shstr
+ sec
->sh_name
;
428 if (!strcmp(shname
, name
))
434 int find_reloc(int sh_index
)
436 struct elf_shdr
*sec
;
439 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
441 if (sec
->sh_type
== SHT_RELOC
&& sec
->sh_info
== sh_index
)
447 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
449 return rel
->r_offset
;
452 static char *get_rel_sym_name(EXE_RELOC
*rel
)
454 return strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
457 static char *get_sym_name(EXE_SYM
*sym
)
459 return strtab
+ sym
->st_name
;
462 /* load an elf object file */
463 int load_object(const char *filename
)
466 struct elf_shdr
*sec
, *symtab_sec
, *strtab_sec
, *text_sec
;
472 fd
= open(filename
, O_RDONLY
);
474 error("can't open file '%s'", filename
);
476 /* Read ELF header. */
477 if (read(fd
, &ehdr
, sizeof (ehdr
)) != sizeof (ehdr
))
478 error("unable to read file header");
480 /* Check ELF identification. */
481 if (ehdr
.e_ident
[EI_MAG0
] != ELFMAG0
482 || ehdr
.e_ident
[EI_MAG1
] != ELFMAG1
483 || ehdr
.e_ident
[EI_MAG2
] != ELFMAG2
484 || ehdr
.e_ident
[EI_MAG3
] != ELFMAG3
485 || ehdr
.e_ident
[EI_VERSION
] != EV_CURRENT
) {
486 error("bad ELF header");
489 do_swap
= elf_must_swap(&ehdr
);
491 elf_swap_ehdr(&ehdr
);
492 if (ehdr
.e_ident
[EI_CLASS
] != ELF_CLASS
)
493 error("Unsupported ELF class");
494 if (ehdr
.e_type
!= ET_REL
)
495 error("ELF object file expected");
496 if (ehdr
.e_version
!= EV_CURRENT
)
497 error("Invalid ELF version");
498 if (!elf_check_arch(ehdr
.e_machine
))
499 error("Unsupported CPU (e_machine=%d)", ehdr
.e_machine
);
501 /* read section headers */
502 shdr
= load_data(fd
, ehdr
.e_shoff
, ehdr
.e_shnum
* sizeof(struct elf_shdr
));
504 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
505 elf_swap_shdr(&shdr
[i
]);
509 /* read all section data */
510 sdata
= malloc(sizeof(void *) * ehdr
.e_shnum
);
511 memset(sdata
, 0, sizeof(void *) * ehdr
.e_shnum
);
513 for(i
= 0;i
< ehdr
.e_shnum
; i
++) {
515 if (sec
->sh_type
!= SHT_NOBITS
)
516 sdata
[i
] = load_data(fd
, sec
->sh_offset
, sec
->sh_size
);
519 sec
= &shdr
[ehdr
.e_shstrndx
];
520 shstr
= (char *)sdata
[ehdr
.e_shstrndx
];
522 /* swap relocations */
523 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
525 if (sec
->sh_type
== SHT_RELOC
) {
526 nb_relocs
= sec
->sh_size
/ sec
->sh_entsize
;
528 for(j
= 0, rel
= (ELF_RELOC
*)sdata
[i
]; j
< nb_relocs
; j
++, rel
++)
535 text_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".text");
537 error("could not find .text section");
538 text_shndx
= text_sec
- shdr
;
539 text
= sdata
[text_shndx
];
541 /* find text relocations, if any */
544 i
= find_reloc(text_shndx
);
546 relocs
= (ELF_RELOC
*)sdata
[i
];
547 nb_relocs
= shdr
[i
].sh_size
/ shdr
[i
].sh_entsize
;
550 symtab_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".symtab");
552 error("could not find .symtab section");
553 strtab_sec
= &shdr
[symtab_sec
->sh_link
];
555 symtab
= (ElfW(Sym
) *)sdata
[symtab_sec
- shdr
];
556 strtab
= (char *)sdata
[symtab_sec
->sh_link
];
558 nb_syms
= symtab_sec
->sh_size
/ sizeof(ElfW(Sym
));
560 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
561 swab32s(&sym
->st_name
);
562 swabls(&sym
->st_value
);
563 swabls(&sym
->st_size
);
564 swab16s(&sym
->st_shndx
);
571 #endif /* CONFIG_FORMAT_ELF */
573 #ifdef CONFIG_FORMAT_COFF
576 struct external_scnhdr
*shdr
;
578 struct external_filehdr fhdr
;
579 struct external_syment
*coff_symtab
;
581 int coff_text_shndx
, coff_data_shndx
;
585 #define STRTAB_SIZE 4
590 #define T_FUNCTION 0x20
593 void sym_ent_name(struct external_syment
*ext_sym
, EXE_SYM
*sym
)
598 if (ext_sym
->e
.e
.e_zeroes
!= 0) {
600 for(i
= 0; i
< 8; i
++) {
601 c
= ext_sym
->e
.e_name
[i
];
608 pstrcpy(sym
->st_name
, sizeof(sym
->st_name
), strtab
+ ext_sym
->e
.e
.e_offset
);
611 /* now convert the name to a C name (suppress the leading '_') */
612 if (sym
->st_name
[0] == '_') {
613 len
= strlen(sym
->st_name
);
614 memmove(sym
->st_name
, sym
->st_name
+ 1, len
- 1);
615 sym
->st_name
[len
- 1] = '\0';
619 char *name_for_dotdata(struct coff_rel
*rel
)
622 struct coff_sym
*sym
;
625 text_data
= *(uint32_t *)(text
+ rel
->r_offset
);
627 for (i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
628 if (sym
->st_syment
->e_scnum
== data_shndx
&&
629 text_data
>= sym
->st_value
&&
630 text_data
< sym
->st_value
+ sym
->st_size
) {
639 static char *get_sym_name(EXE_SYM
*sym
)
644 static char *get_rel_sym_name(EXE_RELOC
*rel
)
647 name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
648 if (!strcmp(name
, ".data"))
649 name
= name_for_dotdata(rel
);
655 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
657 return rel
->r_offset
;
660 struct external_scnhdr
*find_coff_section(struct external_scnhdr
*shdr
, int shnum
, const char *name
)
664 struct external_scnhdr
*sec
;
666 for(i
= 0; i
< shnum
; i
++) {
670 shname
= sec
->s_name
;
671 if (!strcmp(shname
, name
))
677 /* load a coff object file */
678 int load_object(const char *filename
)
681 struct external_scnhdr
*sec
, *text_sec
, *data_sec
;
683 struct external_syment
*ext_sym
;
684 struct external_reloc
*coff_relocs
;
685 struct external_reloc
*ext_rel
;
690 fd
= open(filename
, O_RDONLY
696 error("can't open file '%s'", filename
);
698 /* Read COFF header. */
699 if (read(fd
, &fhdr
, sizeof (fhdr
)) != sizeof (fhdr
))
700 error("unable to read file header");
702 /* Check COFF identification. */
703 if (fhdr
.f_magic
!= I386MAGIC
) {
704 error("bad COFF header");
708 /* read section headers */
709 shdr
= load_data(fd
, sizeof(struct external_filehdr
) + fhdr
.f_opthdr
, fhdr
.f_nscns
* sizeof(struct external_scnhdr
));
711 /* read all section data */
712 sdata
= malloc(sizeof(void *) * fhdr
.f_nscns
);
713 memset(sdata
, 0, sizeof(void *) * fhdr
.f_nscns
);
716 for(i
= 0;i
< fhdr
.f_nscns
; i
++) {
718 if (!strstart(sec
->s_name
, ".bss", &p
))
719 sdata
[i
] = load_data(fd
, sec
->s_scnptr
, sec
->s_size
);
724 text_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".text");
726 error("could not find .text section");
727 coff_text_shndx
= text_sec
- shdr
;
728 text
= sdata
[coff_text_shndx
];
731 data_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".data");
733 error("could not find .data section");
734 coff_data_shndx
= data_sec
- shdr
;
736 coff_symtab
= load_data(fd
, fhdr
.f_symptr
, fhdr
.f_nsyms
*SYMESZ
);
737 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
739 printf(" %02x", ((uint8_t *)ext_sym
->e
.e_name
)[i
]);
744 n_strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), STRTAB_SIZE
);
745 strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), *n_strtab
);
747 nb_syms
= fhdr
.f_nsyms
;
749 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
750 if (strstart(ext_sym
->e
.e_name
, ".text", NULL
))
751 text_shndx
= ext_sym
->e_scnum
;
752 if (strstart(ext_sym
->e
.e_name
, ".data", NULL
))
753 data_shndx
= ext_sym
->e_scnum
;
756 /* set coff symbol */
757 symtab
= malloc(sizeof(struct coff_sym
) * nb_syms
);
760 for (i
= 0, ext_sym
= coff_symtab
, sym
= symtab
; i
< nb_syms
; i
++, ext_sym
++, sym
++) {
761 memset(sym
, 0, sizeof(*sym
));
762 sym
->st_syment
= ext_sym
;
763 sym_ent_name(ext_sym
, sym
);
764 sym
->st_value
= ext_sym
->e_value
;
766 aux_size
= *(int8_t *)ext_sym
->e_numaux
;
767 if (ext_sym
->e_scnum
== text_shndx
&& ext_sym
->e_type
== T_FUNCTION
) {
768 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
769 if ((ext_sym
+ j
)->e_scnum
== text_shndx
&&
770 (ext_sym
+ j
)->e_type
== T_FUNCTION
){
771 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
773 } else if (j
== nb_syms
- i
- 1) {
774 sec
= &shdr
[coff_text_shndx
];
775 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
779 } else if (ext_sym
->e_scnum
== data_shndx
&& *(uint8_t *)ext_sym
->e_sclass
== C_EXTERNAL
) {
780 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
781 if ((ext_sym
+ j
)->e_scnum
== data_shndx
) {
782 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
784 } else if (j
== nb_syms
- i
- 1) {
785 sec
= &shdr
[coff_data_shndx
];
786 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
794 sym
->st_type
= ext_sym
->e_type
;
795 sym
->st_shndx
= ext_sym
->e_scnum
;
799 /* find text relocations, if any */
800 sec
= &shdr
[coff_text_shndx
];
801 coff_relocs
= load_data(fd
, sec
->s_relptr
, sec
->s_nreloc
*RELSZ
);
802 nb_relocs
= sec
->s_nreloc
;
804 /* set coff relocation */
805 relocs
= malloc(sizeof(struct coff_rel
) * nb_relocs
);
806 for (i
= 0, ext_rel
= coff_relocs
, rel
= relocs
; i
< nb_relocs
;
807 i
++, ext_rel
++, rel
++) {
808 memset(rel
, 0, sizeof(*rel
));
809 rel
->r_reloc
= ext_rel
;
810 rel
->r_offset
= *(uint32_t *)ext_rel
->r_vaddr
;
811 rel
->r_type
= *(uint16_t *)ext_rel
->r_type
;
816 #endif /* CONFIG_FORMAT_COFF */
818 #ifdef CONFIG_FORMAT_MACH
821 struct mach_header mach_hdr
;
824 struct segment_command
*segment
= 0;
825 struct dysymtab_command
*dysymtabcmd
= 0;
826 struct symtab_command
*symtabcmd
= 0;
829 struct section
*section_hdr
;
830 struct section
*text_sec_hdr
;
834 struct relocation_info
*relocs
;
838 struct nlist
*symtab_std
;
841 /* indirect symbols */
844 /* Utility functions */
846 static inline char *find_str_by_index(int index
)
851 /* Used by dyngen common code */
852 static char *get_sym_name(EXE_SYM
*sym
)
854 char *name
= find_str_by_index(sym
->n_un
.n_strx
);
856 if ( sym
->n_type
& N_STAB
) /* Debug symbols are ignored */
867 /* find a section index given its segname, sectname */
868 static int find_mach_sec_index(struct section
*section_hdr
, int shnum
, const char *segname
,
869 const char *sectname
)
872 struct section
*sec
= section_hdr
;
874 for(i
= 0; i
< shnum
; i
++, sec
++) {
875 if (!sec
->segname
|| !sec
->sectname
)
877 if (!strcmp(sec
->sectname
, sectname
) && !strcmp(sec
->segname
, segname
))
883 /* find a section header given its segname, sectname */
884 struct section
*find_mach_sec_hdr(struct section
*section_hdr
, int shnum
, const char *segname
,
885 const char *sectname
)
887 int index
= find_mach_sec_index(section_hdr
, shnum
, segname
, sectname
);
890 return section_hdr
+index
;
894 static inline void fetch_next_pair_value(struct relocation_info
* rel
, unsigned int *value
)
896 struct scattered_relocation_info
* scarel
;
898 if(R_SCATTERED
& rel
->r_address
) {
899 scarel
= (struct scattered_relocation_info
*)rel
;
900 if(scarel
->r_type
!= PPC_RELOC_PAIR
)
901 error("fetch_next_pair_value: looking for a pair which was not found (1)");
902 *value
= scarel
->r_value
;
904 if(rel
->r_type
!= PPC_RELOC_PAIR
)
905 error("fetch_next_pair_value: looking for a pair which was not found (2)");
906 *value
= rel
->r_address
;
910 /* find a sym name given its value, in a section number */
911 static const char * find_sym_with_value_and_sec_number( int value
, int sectnum
, int * offset
)
915 for( i
= 0 ; i
< nb_syms
; i
++ )
917 if( !(symtab
[i
].n_type
& N_STAB
) && (symtab
[i
].n_type
& N_SECT
) &&
918 (symtab
[i
].n_sect
== sectnum
) && (symtab
[i
].st_value
<= value
) )
920 if( (ret
<0) || (symtab
[i
].st_value
>= symtab
[ret
].st_value
) )
928 *offset
= value
- symtab
[ret
].st_value
;
929 return get_sym_name(&symtab
[ret
]);
934 * Find symbol name given a (virtual) address, and a section which is of type
935 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
937 static const char * find_reloc_name_in_sec_ptr(int address
, struct section
* sec_hdr
)
939 unsigned int tocindex
, symindex
, size
;
940 const char *name
= 0;
943 if(!( address
>= sec_hdr
->addr
&& address
< (sec_hdr
->addr
+ sec_hdr
->size
) ) )
946 if( sec_hdr
->flags
& S_SYMBOL_STUBS
){
947 size
= sec_hdr
->reserved2
;
952 else if( sec_hdr
->flags
& S_LAZY_SYMBOL_POINTERS
||
953 sec_hdr
->flags
& S_NON_LAZY_SYMBOL_POINTERS
)
954 size
= sizeof(unsigned long);
958 /* Compute our index in toc */
959 tocindex
= (address
- sec_hdr
->addr
)/size
;
960 symindex
= tocdylib
[sec_hdr
->reserved1
+ tocindex
];
962 name
= get_sym_name(&symtab
[symindex
]);
967 static const char * find_reloc_name_given_its_address(int address
)
970 for(i
= 0; i
< segment
->nsects
; i
++)
972 const char * name
= find_reloc_name_in_sec_ptr(address
, §ion_hdr
[i
]);
979 static const char * get_reloc_name(EXE_RELOC
* rel
, int * sslide
)
982 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
983 int sectnum
= rel
->r_symbolnum
;
987 /* init the slide value */
990 if(R_SCATTERED
& rel
->r_address
)
991 return (char *)find_reloc_name_given_its_address(sca_rel
->r_value
);
995 /* ignore debug sym */
996 if ( symtab
[rel
->r_symbolnum
].n_type
& N_STAB
)
998 return get_sym_name(&symtab
[rel
->r_symbolnum
]);
1001 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1002 sectoffset
= *(uint32_t *)(text
+ rel
->r_address
) & 0xffff;
1004 if(sectnum
==0xffffff)
1008 if(sectnum
> segment
->nsects
)
1009 error("sectnum > segment->nsects");
1013 case PPC_RELOC_LO16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
|= (other_half
<< 16);
1015 case PPC_RELOC_HI16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) | (uint16_t)(other_half
& 0xffff);
1017 case PPC_RELOC_HA16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) + (int16_t)(other_half
& 0xffff);
1019 case PPC_RELOC_BR24
:
1020 sectoffset
= ( *(uint32_t *)(text
+ rel
->r_address
) & 0x03fffffc );
1021 if (sectoffset
& 0x02000000) sectoffset
|= 0xfc000000;
1024 error("switch(rel->type) not found");
1028 sectoffset
+= rel
->r_address
;
1030 if (rel
->r_type
== PPC_RELOC_BR24
)
1031 name
= (char *)find_reloc_name_in_sec_ptr((int)sectoffset
, §ion_hdr
[sectnum
-1]);
1033 /* search it in the full symbol list, if not found */
1035 name
= (char *)find_sym_with_value_and_sec_number(sectoffset
, sectnum
, sslide
);
1040 /* Used by dyngen common code */
1041 static const char * get_rel_sym_name(EXE_RELOC
* rel
)
1044 return get_reloc_name( rel
, &sslide
);
1047 /* Used by dyngen common code */
1048 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
1050 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
1051 if(R_SCATTERED
& rel
->r_address
)
1052 return sca_rel
->r_address
;
1054 return rel
->r_address
;
1057 /* load a mach-o object file */
1058 int load_object(const char *filename
)
1061 unsigned int offset_to_segment
= 0;
1062 unsigned int offset_to_dysymtab
= 0;
1063 unsigned int offset_to_symtab
= 0;
1064 struct load_command lc
;
1067 struct nlist
*syment
;
1069 fd
= open(filename
, O_RDONLY
);
1071 error("can't open file '%s'", filename
);
1073 /* Read Mach header. */
1074 if (read(fd
, &mach_hdr
, sizeof (mach_hdr
)) != sizeof (mach_hdr
))
1075 error("unable to read file header");
1077 /* Check Mach identification. */
1078 if (!check_mach_header(mach_hdr
)) {
1079 error("bad Mach header");
1082 if (mach_hdr
.cputype
!= CPU_TYPE_POWERPC
)
1083 error("Unsupported CPU");
1085 if (mach_hdr
.filetype
!= MH_OBJECT
)
1086 error("Unsupported Mach Object");
1088 /* read segment headers */
1089 for(i
=0, j
=sizeof(mach_hdr
); i
<mach_hdr
.ncmds
; i
++)
1091 if(read(fd
, &lc
, sizeof(struct load_command
)) != sizeof(struct load_command
))
1092 error("unable to read load_command");
1093 if(lc
.cmd
== LC_SEGMENT
)
1095 offset_to_segment
= j
;
1096 lseek(fd
, offset_to_segment
, SEEK_SET
);
1097 segment
= malloc(sizeof(struct segment_command
));
1098 if(read(fd
, segment
, sizeof(struct segment_command
)) != sizeof(struct segment_command
))
1099 error("unable to read LC_SEGMENT");
1101 if(lc
.cmd
== LC_DYSYMTAB
)
1103 offset_to_dysymtab
= j
;
1104 lseek(fd
, offset_to_dysymtab
, SEEK_SET
);
1105 dysymtabcmd
= malloc(sizeof(struct dysymtab_command
));
1106 if(read(fd
, dysymtabcmd
, sizeof(struct dysymtab_command
)) != sizeof(struct dysymtab_command
))
1107 error("unable to read LC_DYSYMTAB");
1109 if(lc
.cmd
== LC_SYMTAB
)
1111 offset_to_symtab
= j
;
1112 lseek(fd
, offset_to_symtab
, SEEK_SET
);
1113 symtabcmd
= malloc(sizeof(struct symtab_command
));
1114 if(read(fd
, symtabcmd
, sizeof(struct symtab_command
)) != sizeof(struct symtab_command
))
1115 error("unable to read LC_SYMTAB");
1119 lseek(fd
, j
, SEEK_SET
);
1123 error("unable to find LC_SEGMENT");
1125 /* read section headers */
1126 section_hdr
= load_data(fd
, offset_to_segment
+ sizeof(struct segment_command
), segment
->nsects
* sizeof(struct section
));
1128 /* read all section data */
1129 sdata
= (uint8_t **)malloc(sizeof(void *) * segment
->nsects
);
1130 memset(sdata
, 0, sizeof(void *) * segment
->nsects
);
1132 /* Load the data in section data */
1133 for(i
= 0; i
< segment
->nsects
; i
++) {
1134 sdata
[i
] = load_data(fd
, section_hdr
[i
].offset
, section_hdr
[i
].size
);
1138 text_sec_hdr
= find_mach_sec_hdr(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1139 i
= find_mach_sec_index(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1140 if (i
== -1 || !text_sec_hdr
)
1141 error("could not find __TEXT,__text section");
1144 /* Make sure dysym was loaded */
1145 if(!(int)dysymtabcmd
)
1146 error("could not find __DYSYMTAB segment");
1148 /* read the table of content of the indirect sym */
1149 tocdylib
= load_data( fd
, dysymtabcmd
->indirectsymoff
, dysymtabcmd
->nindirectsyms
* sizeof(uint32_t) );
1151 /* Make sure symtab was loaded */
1153 error("could not find __SYMTAB segment");
1154 nb_syms
= symtabcmd
->nsyms
;
1156 symtab_std
= load_data(fd
, symtabcmd
->symoff
, symtabcmd
->nsyms
* sizeof(struct nlist
));
1157 strtab
= load_data(fd
, symtabcmd
->stroff
, symtabcmd
->strsize
);
1159 symtab
= malloc(sizeof(EXE_SYM
) * nb_syms
);
1161 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1162 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< nb_syms
; i
++, sym
++, syment
++) {
1163 struct nlist
*sym_follow
, *sym_next
= 0;
1165 memset(sym
, 0, sizeof(*sym
));
1167 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
1170 memcpy(sym
, syment
, sizeof(*syment
));
1172 /* Find the following symbol in order to get the current symbol size */
1173 for(j
= 0, sym_follow
= symtab_std
; j
< nb_syms
; j
++, sym_follow
++) {
1174 if ( sym_follow
->n_sect
!= 1 || sym_follow
->n_type
& N_STAB
|| !(sym_follow
->n_value
> sym
->st_value
))
1177 sym_next
= sym_follow
;
1180 if(!(sym_next
->n_value
> sym_follow
->n_value
))
1182 sym_next
= sym_follow
;
1185 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
1187 sym
->st_size
= text_sec_hdr
->size
- sym
->st_value
;
1191 relocs
= load_data(fd
, text_sec_hdr
->reloff
, text_sec_hdr
->nreloc
* sizeof(struct relocation_info
));
1192 nb_relocs
= text_sec_hdr
->nreloc
;
1198 #endif /* CONFIG_FORMAT_MACH */
1200 void get_reloc_expr(char *name
, int name_size
, const char *sym_name
)
1204 if (strstart(sym_name
, "__op_param", &p
)) {
1205 snprintf(name
, name_size
, "param%s", p
);
1206 } else if (strstart(sym_name
, "__op_gen_label", &p
)) {
1207 snprintf(name
, name_size
, "gen_labels[param%s]", p
);
1210 if (sym_name
[0] == '.')
1211 snprintf(name
, name_size
,
1212 "(long)(&__dot_%s)",
1216 snprintf(name
, name_size
, "(long)(&%s)", sym_name
);
1222 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1225 struct plt_entry
*next
;
1227 unsigned long addend
;
1231 get_plt_index (const char *name
, unsigned long addend
)
1233 struct plt_entry
*plt
, *prev
= NULL
;
1236 /* see if we already have an entry for this target: */
1237 for (plt
= plt_list
; plt
; ++index
, prev
= plt
, plt
= plt
->next
)
1238 if (strcmp(plt
->name
, name
) == 0 && plt
->addend
== addend
)
1241 /* nope; create a new PLT entry: */
1243 plt
= malloc(sizeof(*plt
));
1248 memset(plt
, 0, sizeof(*plt
));
1249 plt
->name
= strdup(name
);
1250 plt
->addend
= addend
;
1252 /* append to plt-list: */
1264 int arm_emit_ldr_info(const char *name
, unsigned long start_offset
,
1265 FILE *outfile
, uint8_t *p_start
, uint8_t *p_end
,
1266 ELF_RELOC
*relocs
, int nb_relocs
)
1270 int offset
, min_offset
, pc_offset
, data_size
, spare
, max_pool
;
1271 uint8_t data_allocated
[1024];
1272 unsigned int data_index
;
1275 memset(data_allocated
, 0, sizeof(data_allocated
));
1278 min_offset
= p_end
- p_start
;
1280 while (p
< p_start
+ min_offset
) {
1281 insn
= get32((uint32_t *)p
);
1282 /* TODO: Armv5e ldrd. */
1283 /* TODO: VFP load. */
1284 if ((insn
& 0x0d5f0000) == 0x051f0000) {
1285 /* ldr reg, [pc, #im] */
1286 offset
= insn
& 0xfff;
1287 if (!(insn
& 0x00800000))
1291 } else if ((insn
& 0x0e5f0f00) == 0x0c1f0100) {
1293 offset
= (insn
& 0xff) << 2;
1294 if (!(insn
& 0x00800000))
1298 } else if ((insn
& 0x0fff0000) == 0x028f0000) {
1299 /* Some gcc load a doubleword immediate with
1301 ldmia regN, {regN, regM}
1302 Hope and pray the compiler never generates somethin like
1303 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1306 r
= (insn
& 0xf00) >> 7;
1307 offset
= ((insn
& 0xff) >> r
) | ((insn
& 0xff) << (32 - r
));
1315 /* PC-relative load needs fixing up. */
1316 if (spare
> max_pool
- offset
)
1317 spare
= max_pool
- offset
;
1318 if ((offset
& 3) !=0)
1319 error("%s:%04x: pc offset must be 32 bit aligned",
1320 name
, start_offset
+ p
- p_start
);
1322 error("%s:%04x: Embedded literal value",
1323 name
, start_offset
+ p
- p_start
);
1324 pc_offset
= p
- p_start
+ offset
+ 8;
1325 if (pc_offset
<= (p
- p_start
) ||
1326 pc_offset
>= (p_end
- p_start
))
1327 error("%s:%04x: pc offset must point inside the function code",
1328 name
, start_offset
+ p
- p_start
);
1329 if (pc_offset
< min_offset
)
1330 min_offset
= pc_offset
;
1332 /* The intruction position */
1333 fprintf(outfile
, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1335 /* The position of the constant pool data. */
1336 data_index
= ((p_end
- p_start
) - pc_offset
) >> 2;
1337 fprintf(outfile
, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1339 fprintf(outfile
, " arm_ldr_ptr->type = %d;\n", type
);
1340 fprintf(outfile
, " arm_ldr_ptr++;\n");
1346 /* Copy and relocate the constant pool data. */
1347 data_size
= (p_end
- p_start
) - min_offset
;
1348 if (data_size
> 0 && outfile
) {
1349 spare
+= min_offset
;
1350 fprintf(outfile
, " arm_data_ptr -= %d;\n", data_size
>> 2);
1351 fprintf(outfile
, " arm_pool_ptr -= %d;\n", data_size
);
1352 fprintf(outfile
, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1353 " arm_pool_ptr = gen_code_ptr + %d;\n",
1357 for (pc_offset
= min_offset
;
1358 pc_offset
< p_end
- p_start
;
1362 int i
, addend
, type
;
1363 const char *sym_name
;
1367 addend
= get32((uint32_t *)(p_start
+ pc_offset
));
1369 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1370 if (rel
->r_offset
== (pc_offset
+ start_offset
)) {
1371 sym_name
= get_rel_sym_name(rel
);
1372 /* the compiler leave some unnecessary references to the code */
1373 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1374 type
= ELF32_R_TYPE(rel
->r_info
);
1375 if (type
!= R_ARM_ABS32
)
1376 error("%s: unsupported data relocation", name
);
1380 fprintf(outfile
, " arm_data_ptr[%d] = 0x%x",
1381 data_index
, addend
);
1382 if (relname
[0] != '\0')
1383 fprintf(outfile
, " + %s", relname
);
1384 fprintf(outfile
, ";\n");
1393 insn
= get32((uint32_t *)p
);
1394 /* The last instruction must be an ldm instruction. There are several
1395 forms generated by gcc:
1396 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1398 ldmea fp, {..., pc} */
1399 if ((insn
& 0xffff8000) == 0xe99d8000) {
1402 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1406 } else if ((insn
& 0xffff8000) != 0xe89d8000
1407 && (insn
& 0xffff8000) != 0xe91b8000) {
1410 printf("%s: invalid epilog\n", name
);
1419 /* generate op code */
1420 void gen_code(const char *name
, host_ulong offset
, host_ulong size
,
1421 FILE *outfile
, int gen_switch
)
1424 uint8_t *p_start
, *p_end
;
1425 host_ulong start_offset
;
1427 uint8_t args_present
[MAX_ARGS
];
1428 const char *sym_name
, *p
;
1431 /* Compute exact size excluding prologue and epilogue instructions.
1432 * Increment start_offset to skip epilogue instructions, then compute
1433 * copy_size the indicate the size of the remaining instructions (in
1436 p_start
= text
+ offset
;
1437 p_end
= p_start
+ size
;
1438 start_offset
= offset
;
1439 #if defined(HOST_I386) || defined(HOST_X86_64)
1440 #ifdef CONFIG_FORMAT_COFF
1445 error("empty code for %s", name
);
1446 while (*p
!= 0xc3) {
1449 error("ret or jmp expected at the end of %s", name
);
1451 copy_size
= p
- p_start
;
1456 len
= p_end
- p_start
;
1458 error("empty code for %s", name
);
1459 if (p_end
[-1] == 0xc3) {
1462 error("ret or jmp expected at the end of %s", name
);
1467 #elif defined(HOST_PPC)
1470 p
= (void *)(p_end
- 4);
1472 error("empty code for %s", name
);
1473 if (get32((uint32_t *)p
) != 0x4e800020)
1474 error("blr expected at the end of %s", name
);
1475 copy_size
= p
- p_start
;
1477 #elif defined(HOST_S390)
1480 p
= (void *)(p_end
- 2);
1482 error("empty code for %s", name
);
1483 if (get16((uint16_t *)p
) != 0x07fe && get16((uint16_t *)p
) != 0x07f4)
1484 error("br %%r14 expected at the end of %s", name
);
1485 copy_size
= p
- p_start
;
1487 #elif defined(HOST_ALPHA)
1492 /* XXX: check why it occurs */
1494 error("empty code for %s", name
);
1496 if (get32((uint32_t *)p
) != 0x6bfa8001)
1497 error("ret expected at the end of %s", name
);
1498 copy_size
= p
- p_start
;
1500 #elif defined(HOST_IA64)
1503 p
= (void *)(p_end
- 4);
1505 error("empty code for %s", name
);
1506 /* br.ret.sptk.many b0;; */
1508 if (get32((uint32_t *)p
) != 0x00840008)
1509 error("br.ret.sptk.many b0;; expected at the end of %s", name
);
1510 copy_size
= p_end
- p_start
;
1512 #elif defined(HOST_SPARC)
1514 #define INSN_SAVE 0x9de3a000
1515 #define INSN_RET 0x81c7e008
1516 #define INSN_RETL 0x81c3e008
1517 #define INSN_RESTORE 0x81e80000
1518 #define INSN_RETURN 0x81cfe008
1519 #define INSN_NOP 0x01000000
1520 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1521 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1523 uint32_t start_insn
, end_insn1
, end_insn2
;
1525 p
= (void *)(p_end
- 8);
1527 error("empty code for %s", name
);
1528 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1529 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1530 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1531 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1532 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1534 start_offset
+= 0x4;
1535 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1536 /* SPARC v7: ret; restore; */ ;
1537 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1538 /* SPARC v9: return; nop; */ ;
1539 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1540 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1543 error("ret; restore; not found at end of %s", name
);
1544 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1547 error("No save at the beginning of %s", name
);
1550 /* Skip a preceeding nop, if present. */
1552 skip_insn
= get32((uint32_t *)(p
- 0x4));
1553 if (skip_insn
== INSN_NOP
)
1557 copy_size
= p
- p_start
;
1559 #elif defined(HOST_SPARC64)
1561 #define INSN_SAVE 0x9de3a000
1562 #define INSN_RET 0x81c7e008
1563 #define INSN_RETL 0x81c3e008
1564 #define INSN_RESTORE 0x81e80000
1565 #define INSN_RETURN 0x81cfe008
1566 #define INSN_NOP 0x01000000
1567 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1568 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1570 uint32_t start_insn
, end_insn1
, end_insn2
, skip_insn
;
1572 p
= (void *)(p_end
- 8);
1574 /* XXX: check why it occurs */
1576 error("empty code for %s", name
);
1578 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1579 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1580 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1581 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1582 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1584 start_offset
+= 0x4;
1585 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1586 /* SPARC v7: ret; restore; */ ;
1587 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1588 /* SPARC v9: return; nop; */ ;
1589 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1590 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1593 error("ret; restore; not found at end of %s", name
);
1594 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1597 error("No save at the beginning of %s", name
);
1600 /* Skip a preceeding nop, if present. */
1602 skip_insn
= get32((uint32_t *)(p
- 0x4));
1603 if (skip_insn
== 0x01000000)
1607 copy_size
= p
- p_start
;
1609 #elif defined(HOST_ARM)
1613 if ((p_end
- p_start
) <= 16)
1614 error("%s: function too small", name
);
1615 if (get32((uint32_t *)p_start
) != 0xe1a0c00d ||
1616 (get32((uint32_t *)(p_start
+ 4)) & 0xffff0000) != 0xe92d0000 ||
1617 get32((uint32_t *)(p_start
+ 8)) != 0xe24cb004)
1618 error("%s: invalid prolog", name
);
1621 insn
= get32((uint32_t *)p_start
);
1622 if ((insn
& 0xffffff00) == 0xe24dd000) {
1623 /* Stack adjustment. Assume op uses the frame pointer. */
1627 copy_size
= arm_emit_ldr_info(name
, start_offset
, NULL
, p_start
, p_end
,
1630 #elif defined(HOST_M68K)
1633 p
= (void *)(p_end
- 2);
1635 error("empty code for %s", name
);
1636 // remove NOP's, probably added for alignment
1637 while ((get16((uint16_t *)p
) == 0x4e71) &&
1640 if (get16((uint16_t *)p
) != 0x4e75)
1641 error("rts expected at the end of %s", name
);
1642 copy_size
= p
- p_start
;
1645 #error unsupported CPU
1648 /* compute the number of arguments by looking at the relocations */
1649 for(i
= 0;i
< MAX_ARGS
; i
++)
1650 args_present
[i
] = 0;
1652 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1653 host_ulong offset
= get_rel_offset(rel
);
1654 if (offset
>= start_offset
&&
1655 offset
< start_offset
+ (p_end
- p_start
)) {
1656 sym_name
= get_rel_sym_name(rel
);
1659 if (strstart(sym_name
, "__op_param", &p
) ||
1660 strstart(sym_name
, "__op_gen_label", &p
)) {
1661 n
= strtoul(p
, NULL
, 10);
1663 error("too many arguments in %s", name
);
1664 args_present
[n
- 1] = 1;
1670 while (nb_args
< MAX_ARGS
&& args_present
[nb_args
])
1672 for(i
= nb_args
; i
< MAX_ARGS
; i
++) {
1673 if (args_present
[i
])
1674 error("inconsistent argument numbering in %s", name
);
1677 if (gen_switch
== 2) {
1678 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, copy_size
);
1679 } else if (gen_switch
== 1) {
1682 fprintf(outfile
, "case INDEX_%s: {\n", name
);
1684 fprintf(outfile
, " long ");
1685 for(i
= 0; i
< nb_args
; i
++) {
1687 fprintf(outfile
, ", ");
1688 fprintf(outfile
, "param%d", i
+ 1);
1690 fprintf(outfile
, ";\n");
1692 #if defined(HOST_IA64)
1693 fprintf(outfile
, " extern char %s;\n", name
);
1695 fprintf(outfile
, " extern void %s();\n", name
);
1698 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1699 host_ulong offset
= get_rel_offset(rel
);
1700 if (offset
>= start_offset
&&
1701 offset
< start_offset
+ (p_end
- p_start
)) {
1702 sym_name
= get_rel_sym_name(rel
);
1706 !strstart(sym_name
, "__op_param", NULL
) &&
1707 !strstart(sym_name
, "__op_jmp", NULL
) &&
1708 !strstart(sym_name
, "__op_gen_label", NULL
)) {
1709 #if defined(HOST_SPARC)
1710 if (sym_name
[0] == '.') {
1712 "extern char __dot_%s __asm__(\"%s\");\n",
1713 sym_name
+1, sym_name
);
1717 #if defined(__APPLE__)
1718 /* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
1719 fprintf(outfile
, "extern char %s __attribute__((unused));\n", sym_name
);
1720 #elif defined(HOST_IA64)
1721 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
1723 * PCREL21 br.call targets generally
1724 * are out of range and need to go
1725 * through an "import stub".
1727 fprintf(outfile
, " extern char %s;\n",
1730 fprintf(outfile
, "extern char %s;\n", sym_name
);
1736 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1737 name
, (int)(start_offset
- offset
), copy_size
);
1739 /* emit code offset information */
1742 const char *sym_name
, *p
;
1746 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
1747 sym_name
= get_sym_name(sym
);
1748 if (strstart(sym_name
, "__op_label", &p
)) {
1750 unsigned long offset
;
1752 /* test if the variable refers to a label inside
1753 the code we are generating */
1754 #ifdef CONFIG_FORMAT_COFF
1755 if (sym
->st_shndx
== text_shndx
) {
1756 ptr
= sdata
[coff_text_shndx
];
1757 } else if (sym
->st_shndx
== data_shndx
) {
1758 ptr
= sdata
[coff_data_shndx
];
1762 #elif defined(CONFIG_FORMAT_MACH)
1765 ptr
= sdata
[sym
->n_sect
-1];
1767 ptr
= sdata
[sym
->st_shndx
];
1770 error("__op_labelN in invalid section");
1771 offset
= sym
->st_value
;
1772 #ifdef CONFIG_FORMAT_MACH
1773 offset
-= section_hdr
[sym
->n_sect
-1].addr
;
1775 val
= *(unsigned long *)(ptr
+ offset
);
1776 #ifdef ELF_USES_RELOCA
1778 int reloc_shndx
, nb_relocs1
, j
;
1780 /* try to find a matching relocation */
1781 reloc_shndx
= find_reloc(sym
->st_shndx
);
1783 nb_relocs1
= shdr
[reloc_shndx
].sh_size
/
1784 shdr
[reloc_shndx
].sh_entsize
;
1785 rel
= (ELF_RELOC
*)sdata
[reloc_shndx
];
1786 for(j
= 0; j
< nb_relocs1
; j
++) {
1787 if (rel
->r_offset
== offset
) {
1788 val
= rel
->r_addend
;
1796 if (val
>= start_offset
&& val
<= start_offset
+ copy_size
) {
1797 n
= strtol(p
, NULL
, 10);
1798 fprintf(outfile
, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n
, (long)(val
- start_offset
));
1804 /* load parameres in variables */
1805 for(i
= 0; i
< nb_args
; i
++) {
1806 fprintf(outfile
, " param%d = *opparam_ptr++;\n", i
+ 1);
1809 /* patch relocations */
1810 #if defined(HOST_I386)
1816 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1817 if (rel
->r_offset
>= start_offset
&&
1818 rel
->r_offset
< start_offset
+ copy_size
) {
1819 sym_name
= get_rel_sym_name(rel
);
1822 reloc_offset
= rel
->r_offset
- start_offset
;
1823 if (strstart(sym_name
, "__op_jmp", &p
)) {
1825 n
= strtol(p
, NULL
, 10);
1826 /* __op_jmp relocations are done at
1827 runtime to do translated block
1828 chaining: the offset of the instruction
1829 needs to be stored */
1830 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1835 get_reloc_expr(name
, sizeof(name
), sym_name
);
1836 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
1837 #ifdef CONFIG_FORMAT_ELF
1838 type
= ELF32_R_TYPE(rel
->r_info
);
1841 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1842 reloc_offset
, name
, addend
);
1845 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1846 reloc_offset
, name
, reloc_offset
, addend
);
1849 error("unsupported i386 relocation (%d)", type
);
1851 #elif defined(CONFIG_FORMAT_COFF)
1856 temp_name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
1857 if (!strcmp(temp_name
, ".data")) {
1858 for (j
= 0, sym
= symtab
; j
< nb_syms
; j
++, sym
++) {
1859 if (strstart(sym
->st_name
, sym_name
, NULL
)) {
1860 addend
-= sym
->st_value
;
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 -4;\n",
1873 reloc_offset
, name
, reloc_offset
, addend
);
1876 error("unsupported i386 relocation (%d)", type
);
1879 #error unsupport object format
1884 #elif defined(HOST_X86_64)
1890 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1891 if (rel
->r_offset
>= start_offset
&&
1892 rel
->r_offset
< start_offset
+ copy_size
) {
1893 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1894 get_reloc_expr(name
, sizeof(name
), sym_name
);
1895 type
= ELF32_R_TYPE(rel
->r_info
);
1896 addend
= rel
->r_addend
;
1897 reloc_offset
= rel
->r_offset
- start_offset
;
1900 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1901 reloc_offset
, name
, addend
);
1904 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1905 reloc_offset
, name
, addend
);
1908 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1909 reloc_offset
, name
, reloc_offset
, addend
);
1912 error("unsupported X86_64 relocation (%d)", type
);
1917 #elif defined(HOST_PPC)
1919 #ifdef CONFIG_FORMAT_ELF
1924 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1925 if (rel
->r_offset
>= start_offset
&&
1926 rel
->r_offset
< start_offset
+ copy_size
) {
1927 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1928 reloc_offset
= rel
->r_offset
- start_offset
;
1929 if (strstart(sym_name
, "__op_jmp", &p
)) {
1931 n
= strtol(p
, NULL
, 10);
1932 /* __op_jmp relocations are done at
1933 runtime to do translated block
1934 chaining: the offset of the instruction
1935 needs to be stored */
1936 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1941 get_reloc_expr(name
, sizeof(name
), sym_name
);
1942 type
= ELF32_R_TYPE(rel
->r_info
);
1943 addend
= rel
->r_addend
;
1946 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1947 reloc_offset
, name
, addend
);
1949 case R_PPC_ADDR16_LO
:
1950 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1951 reloc_offset
, name
, addend
);
1953 case R_PPC_ADDR16_HI
:
1954 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1955 reloc_offset
, name
, addend
);
1957 case R_PPC_ADDR16_HA
:
1958 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1959 reloc_offset
, name
, addend
);
1962 /* warning: must be at 32 MB distancy */
1963 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
1964 reloc_offset
, reloc_offset
, name
, reloc_offset
, addend
);
1967 error("unsupported powerpc relocation (%d)", type
);
1971 #elif defined(CONFIG_FORMAT_MACH)
1972 struct scattered_relocation_info
*scarel
;
1973 struct relocation_info
* rel
;
1974 char final_sym_name
[256];
1975 const char *sym_name
;
1980 for(i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
1981 unsigned int offset
, length
, value
= 0;
1982 unsigned int type
, pcrel
, isym
= 0;
1983 unsigned int usesym
= 0;
1985 if(R_SCATTERED
& rel
->r_address
) {
1986 scarel
= (struct scattered_relocation_info
*)rel
;
1987 offset
= (unsigned int)scarel
->r_address
;
1988 length
= scarel
->r_length
;
1989 pcrel
= scarel
->r_pcrel
;
1990 type
= scarel
->r_type
;
1991 value
= scarel
->r_value
;
1993 value
= isym
= rel
->r_symbolnum
;
1994 usesym
= (rel
->r_extern
);
1995 offset
= rel
->r_address
;
1996 length
= rel
->r_length
;
1997 pcrel
= rel
->r_pcrel
;
2001 slide
= offset
- start_offset
;
2003 if (!(offset
>= start_offset
&& offset
< start_offset
+ size
))
2004 continue; /* not in our range */
2006 sym_name
= get_reloc_name(rel
, &sslide
);
2008 if(usesym
&& symtab
[isym
].n_type
& N_STAB
)
2009 continue; /* don't handle STAB (debug sym) */
2011 if (sym_name
&& strstart(sym_name
, "__op_jmp", &p
)) {
2013 n
= strtol(p
, NULL
, 10);
2014 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2016 continue; /* Nothing more to do */
2021 fprintf(outfile
, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2022 name
, value
, usesym
? "use sym" : "don't use sym", offset
, length
, pcrel
? "pcrel":"", type
);
2023 continue; /* dunno how to handle without final_sym_name */
2026 get_reloc_expr(final_sym_name
, sizeof(final_sym_name
),
2029 case PPC_RELOC_BR24
:
2030 if (!strstart(sym_name
,"__op_gen_label",&p
)) {
2031 fprintf(outfile
, "{\n");
2032 fprintf(outfile
, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide
);
2033 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",
2034 slide
, slide
, name
, sslide
);
2035 fprintf(outfile
, "}\n");
2037 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2038 slide
, slide
, final_sym_name
, slide
);
2041 case PPC_RELOC_HI16
:
2042 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2043 slide
, final_sym_name
, sslide
);
2045 case PPC_RELOC_LO16
:
2046 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2047 slide
, final_sym_name
, sslide
);
2049 case PPC_RELOC_HA16
:
2050 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2051 slide
, final_sym_name
, sslide
);
2054 error("unsupported powerpc relocation (%d)", type
);
2058 #error unsupport object format
2061 #elif defined(HOST_S390)
2067 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2068 if (rel
->r_offset
>= start_offset
&&
2069 rel
->r_offset
< start_offset
+ copy_size
) {
2070 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2071 get_reloc_expr(name
, sizeof(name
), sym_name
);
2072 type
= ELF32_R_TYPE(rel
->r_info
);
2073 addend
= rel
->r_addend
;
2074 reloc_offset
= rel
->r_offset
- start_offset
;
2077 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2078 reloc_offset
, name
, addend
);
2081 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2082 reloc_offset
, name
, addend
);
2085 fprintf(outfile
, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2086 reloc_offset
, name
, addend
);
2089 error("unsupported s390 relocation (%d)", type
);
2094 #elif defined(HOST_ALPHA)
2096 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2097 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2101 type
= ELF64_R_TYPE(rel
->r_info
);
2102 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2103 reloc_offset
= rel
->r_offset
- start_offset
;
2105 case R_ALPHA_GPDISP
:
2106 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2107 as an immediate instead of constructing it from the pv or ra. */
2108 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2110 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2111 reloc_offset
+ (int)rel
->r_addend
);
2113 case R_ALPHA_LITUSE
:
2114 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2115 now, since some called functions (libc) need pv to be set up. */
2118 /* Branch target prediction hint. Ignore for now. Should be already
2119 correct for in-function jumps. */
2121 case R_ALPHA_LITERAL
:
2122 /* Load a literal from the GOT relative to the gp. Since there's only a
2123 single gp, nothing is to be done. */
2125 case R_ALPHA_GPRELHIGH
:
2126 /* Handle fake relocations against __op_param symbol. Need to emit the
2127 high part of the immediate value instead. Other symbols need no
2128 special treatment. */
2129 if (strstart(sym_name
, "__op_param", &p
))
2130 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2133 case R_ALPHA_GPRELLOW
:
2134 if (strstart(sym_name
, "__op_param", &p
))
2135 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2139 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2140 set up the gp from the pv. */
2141 fprintf(outfile
, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2142 reloc_offset
, sym_name
, reloc_offset
);
2145 error("unsupported Alpha relocation (%d)", type
);
2150 #elif defined(HOST_IA64)
2152 unsigned long sym_idx
;
2158 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2159 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2160 if (rel
->r_offset
< start_offset
2161 || rel
->r_offset
>= start_offset
+ copy_size
)
2163 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2164 code_offset
= rel
->r_offset
- start_offset
;
2165 if (strstart(sym_name
, "__op_jmp", &p
)) {
2167 n
= strtol(p
, NULL
, 10);
2168 /* __op_jmp relocations are done at
2169 runtime to do translated block
2170 chaining: the offset of the instruction
2171 needs to be stored */
2172 fprintf(outfile
, " jmp_offsets[%d] ="
2173 "%ld + (gen_code_ptr - gen_code_buf);\n",
2177 get_reloc_expr(name
, sizeof(name
), sym_name
);
2178 type
= ELF64_R_TYPE(rel
->r_info
);
2179 addend
= rel
->r_addend
;
2183 " ia64_imm64(gen_code_ptr + %ld, "
2185 code_offset
, name
, addend
);
2187 case R_IA64_LTOFF22X
:
2188 case R_IA64_LTOFF22
:
2189 fprintf(outfile
, " IA64_LTOFF(gen_code_ptr + %ld,"
2190 " %s + %ld, %d);\n",
2191 code_offset
, name
, addend
,
2192 (type
== R_IA64_LTOFF22X
));
2196 " ia64_ldxmov(gen_code_ptr + %ld,"
2197 " %s + %ld);\n", code_offset
, name
, addend
);
2200 case R_IA64_PCREL21B
:
2201 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2203 " ia64_imm21b(gen_code_ptr + %ld,"
2204 " (long) (%s + %ld -\n\t\t"
2205 "((long) gen_code_ptr + %ld)) >> 4);\n",
2206 code_offset
, name
, addend
,
2207 code_offset
& ~0xfUL
);
2210 " IA64_PLT(gen_code_ptr + %ld, "
2211 "%d);\t/* %s + %ld */\n",
2213 get_plt_index(sym_name
, addend
),
2218 error("unsupported ia64 relocation (0x%x)",
2222 fprintf(outfile
, " ia64_nop_b(gen_code_ptr + %d);\n",
2223 copy_size
- 16 + 2);
2225 #elif defined(HOST_SPARC)
2231 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2232 if (rel
->r_offset
>= start_offset
&&
2233 rel
->r_offset
< start_offset
+ copy_size
) {
2234 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2235 get_reloc_expr(name
, sizeof(name
), sym_name
);
2236 type
= ELF32_R_TYPE(rel
->r_info
);
2237 addend
= rel
->r_addend
;
2238 reloc_offset
= rel
->r_offset
- start_offset
;
2241 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2242 reloc_offset
, name
, addend
);
2246 " *(uint32_t *)(gen_code_ptr + %d) = "
2247 "((*(uint32_t *)(gen_code_ptr + %d)) "
2249 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2250 reloc_offset
, reloc_offset
, name
, addend
);
2254 " *(uint32_t *)(gen_code_ptr + %d) = "
2255 "((*(uint32_t *)(gen_code_ptr + %d)) "
2257 " | ((%s + %d) & 0x3ff);\n",
2258 reloc_offset
, reloc_offset
, name
, addend
);
2260 case R_SPARC_WDISP30
:
2262 " *(uint32_t *)(gen_code_ptr + %d) = "
2263 "((*(uint32_t *)(gen_code_ptr + %d)) "
2265 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2266 " & 0x3fffffff);\n",
2267 reloc_offset
, reloc_offset
, name
, addend
,
2270 case R_SPARC_WDISP22
:
2272 " *(uint32_t *)(gen_code_ptr + %d) = "
2273 "((*(uint32_t *)(gen_code_ptr + %d)) "
2275 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2277 rel
->r_offset
- start_offset
,
2278 rel
->r_offset
- start_offset
,
2280 rel
->r_offset
- start_offset
);
2283 error("unsupported sparc relocation (%d)", type
);
2288 #elif defined(HOST_SPARC64)
2294 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2295 if (rel
->r_offset
>= start_offset
&&
2296 rel
->r_offset
< start_offset
+ copy_size
) {
2297 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2298 get_reloc_expr(name
, sizeof(name
), sym_name
);
2299 type
= ELF32_R_TYPE(rel
->r_info
);
2300 addend
= rel
->r_addend
;
2301 reloc_offset
= rel
->r_offset
- start_offset
;
2304 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2305 reloc_offset
, name
, addend
);
2309 " *(uint32_t *)(gen_code_ptr + %d) = "
2310 "((*(uint32_t *)(gen_code_ptr + %d)) "
2312 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2313 reloc_offset
, reloc_offset
, name
, addend
);
2317 " *(uint32_t *)(gen_code_ptr + %d) = "
2318 "((*(uint32_t *)(gen_code_ptr + %d)) "
2320 " | ((%s + %d) & 0x3ff);\n",
2321 reloc_offset
, reloc_offset
, name
, addend
);
2324 addend
+= ELF64_R_TYPE_DATA (rel
->r_info
);
2326 " *(uint32_t *)(gen_code_ptr + %d) = "
2327 "((*(uint32_t *)(gen_code_ptr + %d)) "
2329 " | ((%s + %d) & 0x3ff);\n",
2330 reloc_offset
, reloc_offset
, name
, addend
);
2332 case R_SPARC_WDISP30
:
2334 " *(uint32_t *)(gen_code_ptr + %d) = "
2335 "((*(uint32_t *)(gen_code_ptr + %d)) "
2337 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2338 " & 0x3fffffff);\n",
2339 reloc_offset
, reloc_offset
, name
, addend
,
2342 case R_SPARC_WDISP22
:
2344 " *(uint32_t *)(gen_code_ptr + %d) = "
2345 "((*(uint32_t *)(gen_code_ptr + %d)) "
2347 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2349 reloc_offset
, reloc_offset
, name
, addend
,
2353 error("unsupported sparc64 relocation (%d) for symbol %s", type
, name
);
2358 #elif defined(HOST_ARM)
2366 insn
= get32((uint32_t *)(p_start
+ 4));
2367 /* If prologue ends in sub sp, sp, #const then assume
2368 op has a stack frame and needs the frame pointer. */
2369 if ((insn
& 0xffffff00) == 0xe24dd000) {
2372 opcode
= 0xe28db000; /* add fp, sp, #0. */
2374 /* ??? Need to undo the extra stack adjustment at the end of the op.
2375 For now just leave the stack misaligned and hope it doesn't break anything
2377 if ((insn
& 4) != 0) {
2378 /* Preserve doubleword stack alignment. */
2380 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2385 insn
= get32((uint32_t *)(p_start
- 4));
2386 /* Calculate the size of the saved registers,
2388 for (i
= 0; i
< 15; i
++) {
2389 if (insn
& (1 << i
))
2393 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode
);
2395 arm_emit_ldr_info(name
, start_offset
, outfile
, p_start
, p_end
,
2398 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2399 if (rel
->r_offset
>= start_offset
&&
2400 rel
->r_offset
< start_offset
+ copy_size
) {
2401 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2402 /* the compiler leave some unnecessary references to the code */
2403 if (sym_name
[0] == '\0')
2405 get_reloc_expr(name
, sizeof(name
), sym_name
);
2406 type
= ELF32_R_TYPE(rel
->r_info
);
2407 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2408 reloc_offset
= rel
->r_offset
- start_offset
;
2411 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2412 reloc_offset
, name
, addend
);
2417 fprintf(outfile
, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2418 reloc_offset
, addend
, name
);
2421 error("unsupported arm relocation (%d)", type
);
2426 #elif defined(HOST_M68K)
2433 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2434 if (rel
->r_offset
>= start_offset
&&
2435 rel
->r_offset
< start_offset
+ copy_size
) {
2436 sym
= &(symtab
[ELFW(R_SYM
)(rel
->r_info
)]);
2437 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2438 get_reloc_expr(name
, sizeof(name
), sym_name
);
2439 type
= ELF32_R_TYPE(rel
->r_info
);
2440 addend
= get32((uint32_t *)(text
+ rel
->r_offset
)) + rel
->r_addend
;
2441 reloc_offset
= rel
->r_offset
- start_offset
;
2444 fprintf(outfile
, " /* R_68K_32 RELOC, offset %x */\n", rel
->r_offset
) ;
2445 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2446 reloc_offset
, name
, addend
);
2449 fprintf(outfile
, " /* R_68K_PC32 RELOC, offset %x */\n", rel
->r_offset
);
2450 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2451 reloc_offset
, name
, reloc_offset
, /*sym->st_value+*/ addend
);
2454 error("unsupported m68k relocation (%d)", type
);
2460 #error unsupported CPU
2462 fprintf(outfile
, " gen_code_ptr += %d;\n", copy_size
);
2463 fprintf(outfile
, "}\n");
2464 fprintf(outfile
, "break;\n\n");
2466 fprintf(outfile
, "static inline void gen_%s(", name
);
2468 fprintf(outfile
, "void");
2470 for(i
= 0; i
< nb_args
; i
++) {
2472 fprintf(outfile
, ", ");
2473 fprintf(outfile
, "long param%d", i
+ 1);
2476 fprintf(outfile
, ")\n");
2477 fprintf(outfile
, "{\n");
2478 for(i
= 0; i
< nb_args
; i
++) {
2479 fprintf(outfile
, " *gen_opparam_ptr++ = param%d;\n", i
+ 1);
2481 fprintf(outfile
, " *gen_opc_ptr++ = INDEX_%s;\n", name
);
2482 fprintf(outfile
, "}\n\n");
2486 int gen_file(FILE *outfile
, int out_type
)
2491 if (out_type
== OUT_INDEX_OP
) {
2492 fprintf(outfile
, "DEF(end, 0, 0)\n");
2493 fprintf(outfile
, "DEF(nop, 0, 0)\n");
2494 fprintf(outfile
, "DEF(nop1, 1, 0)\n");
2495 fprintf(outfile
, "DEF(nop2, 2, 0)\n");
2496 fprintf(outfile
, "DEF(nop3, 3, 0)\n");
2497 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2499 name
= get_sym_name(sym
);
2500 if (strstart(name
, OP_PREFIX
, NULL
)) {
2501 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 2);
2504 } else if (out_type
== OUT_GEN_OP
) {
2505 /* generate gen_xxx functions */
2506 fprintf(outfile
, "#include \"dyngen-op.h\"\n");
2507 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2509 name
= get_sym_name(sym
);
2510 if (strstart(name
, OP_PREFIX
, NULL
)) {
2511 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2512 if (sym
->st_shndx
!= text_shndx
)
2513 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2515 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 0);
2520 /* generate big code generation switch */
2523 /* We need to know the size of all the ops so we can figure out when
2524 to emit constant pools. This must be consistent with opc.h. */
2526 "static const uint32_t arm_opc_size[] = {\n"
2531 " 0,\n"); /* nop3 */
2532 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2534 name
= get_sym_name(sym
);
2535 if (strstart(name
, OP_PREFIX
, NULL
)) {
2536 fprintf(outfile
, " %d,\n", sym
->st_size
);
2544 "int dyngen_code(uint8_t *gen_code_buf,\n"
2545 " uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2546 " const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2548 " uint8_t *gen_code_ptr;\n"
2549 " const uint16_t *opc_ptr;\n"
2550 " const uint32_t *opparam_ptr;\n");
2553 /* Arm is tricky because it uses constant pools for loading immediate values.
2554 We assume (and require) each function is code followed by a constant pool.
2555 All the ops are small so this should be ok. For each op we figure
2556 out how much "spare" range we have in the load instructions. This allows
2557 us to insert subsequent ops in between the op and the constant pool,
2558 eliminating the neeed to jump around the pool.
2560 We currently generate:
2562 [ For this example we assume merging would move op1_pool out of range.
2563 In practice we should be able to combine many ops before the offset
2564 limits are reached. ]
2575 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2578 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2579 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2580 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2581 /* Initialise the parmissible pool offset to an arbitary large value. */
2582 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2586 long addend
, not_first
= 0;
2587 unsigned long sym_idx
;
2588 int index
, max_index
;
2589 const char *sym_name
;
2593 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2594 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2595 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2596 if (strstart(sym_name
, "__op_gen_label", NULL
))
2598 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2601 addend
= rel
->r_addend
;
2602 index
= get_plt_index(sym_name
, addend
);
2603 if (index
<= max_index
)
2606 fprintf(outfile
, " extern void %s(void);\n", sym_name
);
2610 " struct ia64_fixup *plt_fixes = NULL, "
2611 "*ltoff_fixes = NULL;\n"
2612 " static long plt_target[] = {\n\t");
2615 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2616 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2617 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2618 if (strstart(sym_name
, "__op_gen_label", NULL
))
2620 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2623 addend
= rel
->r_addend
;
2624 index
= get_plt_index(sym_name
, addend
);
2625 if (index
<= max_index
)
2630 fprintf(outfile
, ",\n\t");
2633 fprintf(outfile
, "(long) &%s + %ld", sym_name
, addend
);
2635 fprintf(outfile
, "(long) &%s", sym_name
);
2637 fprintf(outfile
, "\n };\n"
2638 " unsigned int plt_offset[%u] = { 0 };\n", max_index
+ 1);
2644 " gen_code_ptr = gen_code_buf;\n"
2645 " opc_ptr = opc_buf;\n"
2646 " opparam_ptr = opparam_buf;\n");
2648 /* Generate prologue, if needed. */
2654 /* Generate constant pool if needed */
2656 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2657 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2658 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2659 " last_gen_code_ptr = gen_code_ptr;\n"
2660 " arm_ldr_ptr = arm_ldr_table;\n"
2661 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2662 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2667 " switch(*opc_ptr++) {\n");
2669 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2671 name
= get_sym_name(sym
);
2672 if (strstart(name
, OP_PREFIX
, NULL
)) {
2674 printf("%4d: %s pos=0x%08x len=%d\n",
2675 i
, name
, sym
->st_value
, sym
->st_size
);
2677 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2678 if (sym
->st_shndx
!= text_shndx
)
2679 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2681 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 1);
2686 " case INDEX_op_nop:\n"
2688 " case INDEX_op_nop1:\n"
2691 " case INDEX_op_nop2:\n"
2692 " opparam_ptr += 2;\n"
2694 " case INDEX_op_nop3:\n"
2695 " opparam_ptr += 3;\n"
2709 " extern char code_gen_buffer[];\n"
2710 " ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2711 "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2712 "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2713 "plt_target, plt_offset);\n }\n");
2716 /* generate some code patching */
2719 "if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2720 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2721 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2723 /* flush instruction cache */
2724 fprintf(outfile
, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2726 fprintf(outfile
, "return gen_code_ptr - gen_code_buf;\n");
2727 fprintf(outfile
, "}\n\n");
2736 printf("dyngen (c) 2003 Fabrice Bellard\n"
2737 "usage: dyngen [-o outfile] [-c] objfile\n"
2738 "Generate a dynamic code generator from an object file\n"
2739 "-c output enum of operations\n"
2740 "-g output gen_op_xx() functions\n"
2745 int main(int argc
, char **argv
)
2748 const char *filename
, *outfilename
;
2751 outfilename
= "out.c";
2752 out_type
= OUT_CODE
;
2754 c
= getopt(argc
, argv
, "ho:cg");
2762 outfilename
= optarg
;
2765 out_type
= OUT_INDEX_OP
;
2768 out_type
= OUT_GEN_OP
;
2774 filename
= argv
[optind
];
2775 outfile
= fopen(outfilename
, "w");
2777 error("could not open '%s'", outfilename
);
2779 load_object(filename
);
2780 gen_file(outfile
, out_type
);