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_HPPA)
122 #define ELF_CLASS ELFCLASS32
123 #define ELF_ARCH EM_PARISC
124 #define elf_check_arch(x) ((x) == EM_PARISC)
125 #define ELF_USES_RELOCA
127 #elif defined(HOST_MIPS)
129 #define ELF_CLASS ELFCLASS32
130 #define ELF_ARCH EM_MIPS
131 #define elf_check_arch(x) ((x) == EM_MIPS)
132 #define ELF_USES_RELOC
134 #elif defined(HOST_MIPS64)
136 /* Assume n32 ABI here, which is ELF32. */
137 #define ELF_CLASS ELFCLASS32
138 #define ELF_ARCH EM_MIPS
139 #define elf_check_arch(x) ((x) == EM_MIPS)
140 #define ELF_USES_RELOCA
143 #error unsupported CPU - please update the code
148 #if ELF_CLASS == ELFCLASS32
149 typedef int32_t host_long
;
150 typedef uint32_t host_ulong
;
151 #define swabls(x) swab32s(x)
152 #define swablss(x) swab32ss(x)
154 typedef int64_t host_long
;
155 typedef uint64_t host_ulong
;
156 #define swabls(x) swab64s(x)
157 #define swablss(x) swab64ss(x)
160 #ifdef ELF_USES_RELOCA
161 #define SHT_RELOC SHT_RELA
163 #define SHT_RELOC SHT_REL
166 #define EXE_RELOC ELF_RELOC
167 #define EXE_SYM ElfW(Sym)
169 #endif /* CONFIG_FORMAT_ELF */
171 #ifdef CONFIG_FORMAT_COFF
173 typedef int32_t host_long
;
174 typedef uint32_t host_ulong
;
178 #define FILENAMELEN 256
180 typedef struct coff_sym
{
181 struct external_syment
*st_syment
;
182 char st_name
[FILENAMELEN
];
189 typedef struct coff_rel
{
190 struct external_reloc
*r_reloc
;
195 #define EXE_RELOC struct coff_rel
196 #define EXE_SYM struct coff_sym
198 #endif /* CONFIG_FORMAT_COFF */
200 #ifdef CONFIG_FORMAT_MACH
202 #include <mach-o/loader.h>
203 #include <mach-o/nlist.h>
204 #include <mach-o/reloc.h>
205 #include <mach-o/ppc/reloc.h>
207 # define check_mach_header(x) (x.magic == MH_MAGIC)
208 typedef int32_t host_long
;
209 typedef uint32_t host_ulong
;
211 struct nlist_extended
217 unsigned char n_type
;
218 unsigned char n_sect
;
220 unsigned long st_value
;
221 unsigned long st_size
;
224 #define EXE_RELOC struct relocation_info
225 #define EXE_SYM struct nlist_extended
227 #endif /* CONFIG_FORMAT_MACH */
237 /* all dynamically generated functions begin with this code */
238 #define OP_PREFIX "op_"
242 static void __attribute__((noreturn
)) __attribute__((format (printf
, 1, 2))) error(const char *fmt
, ...)
246 fprintf(stderr
, "dyngen: ");
247 vfprintf(stderr
, fmt
, ap
);
248 fprintf(stderr
, "\n");
253 static void *load_data(int fd
, long offset
, unsigned int size
)
260 lseek(fd
, offset
, SEEK_SET
);
261 if (read(fd
, data
, size
) != size
) {
268 int strstart(const char *str
, const char *val
, const char **ptr
)
284 void pstrcpy(char *buf
, int buf_size
, const char *str
)
294 if (c
== 0 || q
>= buf
+ buf_size
- 1)
301 void swab16s(uint16_t *p
)
306 void swab32s(uint32_t *p
)
311 void swab32ss(int32_t *p
)
316 void swab64s(uint64_t *p
)
321 void swab64ss(int64_t *p
)
326 uint16_t get16(uint16_t *p
)
335 uint32_t get32(uint32_t *p
)
344 void put16(uint16_t *p
, uint16_t val
)
351 void put32(uint32_t *p
, uint32_t val
)
358 /* executable information */
366 #ifdef CONFIG_FORMAT_ELF
369 struct elf_shdr
*shdr
;
374 int elf_must_swap(struct elfhdr
*h
)
382 return (h
->e_ident
[EI_DATA
] == ELFDATA2MSB
) !=
383 (swaptest
.b
[0] == 0);
386 void elf_swap_ehdr(struct elfhdr
*h
)
388 swab16s(&h
->e_type
); /* Object file type */
389 swab16s(&h
-> e_machine
); /* Architecture */
390 swab32s(&h
-> e_version
); /* Object file version */
391 swabls(&h
-> e_entry
); /* Entry point virtual address */
392 swabls(&h
-> e_phoff
); /* Program header table file offset */
393 swabls(&h
-> e_shoff
); /* Section header table file offset */
394 swab32s(&h
-> e_flags
); /* Processor-specific flags */
395 swab16s(&h
-> e_ehsize
); /* ELF header size in bytes */
396 swab16s(&h
-> e_phentsize
); /* Program header table entry size */
397 swab16s(&h
-> e_phnum
); /* Program header table entry count */
398 swab16s(&h
-> e_shentsize
); /* Section header table entry size */
399 swab16s(&h
-> e_shnum
); /* Section header table entry count */
400 swab16s(&h
-> e_shstrndx
); /* Section header string table index */
403 void elf_swap_shdr(struct elf_shdr
*h
)
405 swab32s(&h
-> sh_name
); /* Section name (string tbl index) */
406 swab32s(&h
-> sh_type
); /* Section type */
407 swabls(&h
-> sh_flags
); /* Section flags */
408 swabls(&h
-> sh_addr
); /* Section virtual addr at execution */
409 swabls(&h
-> sh_offset
); /* Section file offset */
410 swabls(&h
-> sh_size
); /* Section size in bytes */
411 swab32s(&h
-> sh_link
); /* Link to another section */
412 swab32s(&h
-> sh_info
); /* Additional section information */
413 swabls(&h
-> sh_addralign
); /* Section alignment */
414 swabls(&h
-> sh_entsize
); /* Entry size if section holds table */
417 void elf_swap_phdr(struct elf_phdr
*h
)
419 swab32s(&h
->p_type
); /* Segment type */
420 swabls(&h
->p_offset
); /* Segment file offset */
421 swabls(&h
->p_vaddr
); /* Segment virtual address */
422 swabls(&h
->p_paddr
); /* Segment physical address */
423 swabls(&h
->p_filesz
); /* Segment size in file */
424 swabls(&h
->p_memsz
); /* Segment size in memory */
425 swab32s(&h
->p_flags
); /* Segment flags */
426 swabls(&h
->p_align
); /* Segment alignment */
429 void elf_swap_rel(ELF_RELOC
*rel
)
431 swabls(&rel
->r_offset
);
432 swabls(&rel
->r_info
);
433 #ifdef ELF_USES_RELOCA
434 swablss(&rel
->r_addend
);
438 struct elf_shdr
*find_elf_section(struct elf_shdr
*shdr
, int shnum
, const char *shstr
,
443 struct elf_shdr
*sec
;
445 for(i
= 0; i
< shnum
; i
++) {
449 shname
= shstr
+ sec
->sh_name
;
450 if (!strcmp(shname
, name
))
456 int find_reloc(int sh_index
)
458 struct elf_shdr
*sec
;
461 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
463 if (sec
->sh_type
== SHT_RELOC
&& sec
->sh_info
== sh_index
)
469 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
471 return rel
->r_offset
;
474 static char *get_rel_sym_name(EXE_RELOC
*rel
)
476 return strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
479 static char *get_sym_name(EXE_SYM
*sym
)
481 return strtab
+ sym
->st_name
;
484 /* load an elf object file */
485 int load_object(const char *filename
)
488 struct elf_shdr
*sec
, *symtab_sec
, *strtab_sec
, *text_sec
;
494 fd
= open(filename
, O_RDONLY
);
496 error("can't open file '%s'", filename
);
498 /* Read ELF header. */
499 if (read(fd
, &ehdr
, sizeof (ehdr
)) != sizeof (ehdr
))
500 error("unable to read file header");
502 /* Check ELF identification. */
503 if (ehdr
.e_ident
[EI_MAG0
] != ELFMAG0
504 || ehdr
.e_ident
[EI_MAG1
] != ELFMAG1
505 || ehdr
.e_ident
[EI_MAG2
] != ELFMAG2
506 || ehdr
.e_ident
[EI_MAG3
] != ELFMAG3
507 || ehdr
.e_ident
[EI_VERSION
] != EV_CURRENT
) {
508 error("bad ELF header");
511 do_swap
= elf_must_swap(&ehdr
);
513 elf_swap_ehdr(&ehdr
);
514 if (ehdr
.e_ident
[EI_CLASS
] != ELF_CLASS
)
515 error("Unsupported ELF class");
516 if (ehdr
.e_type
!= ET_REL
)
517 error("ELF object file expected");
518 if (ehdr
.e_version
!= EV_CURRENT
)
519 error("Invalid ELF version");
520 if (!elf_check_arch(ehdr
.e_machine
))
521 error("Unsupported CPU (e_machine=%d)", ehdr
.e_machine
);
523 /* read section headers */
524 shdr
= load_data(fd
, ehdr
.e_shoff
, ehdr
.e_shnum
* sizeof(struct elf_shdr
));
526 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
527 elf_swap_shdr(&shdr
[i
]);
531 /* read all section data */
532 sdata
= malloc(sizeof(void *) * ehdr
.e_shnum
);
533 memset(sdata
, 0, sizeof(void *) * ehdr
.e_shnum
);
535 for(i
= 0;i
< ehdr
.e_shnum
; i
++) {
537 if (sec
->sh_type
!= SHT_NOBITS
)
538 sdata
[i
] = load_data(fd
, sec
->sh_offset
, sec
->sh_size
);
541 sec
= &shdr
[ehdr
.e_shstrndx
];
542 shstr
= (char *)sdata
[ehdr
.e_shstrndx
];
544 /* swap relocations */
545 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
547 if (sec
->sh_type
== SHT_RELOC
) {
548 nb_relocs
= sec
->sh_size
/ sec
->sh_entsize
;
550 for(j
= 0, rel
= (ELF_RELOC
*)sdata
[i
]; j
< nb_relocs
; j
++, rel
++)
557 text_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".text");
559 error("could not find .text section");
560 text_shndx
= text_sec
- shdr
;
561 text
= sdata
[text_shndx
];
563 /* find text relocations, if any */
566 i
= find_reloc(text_shndx
);
568 relocs
= (ELF_RELOC
*)sdata
[i
];
569 nb_relocs
= shdr
[i
].sh_size
/ shdr
[i
].sh_entsize
;
572 symtab_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".symtab");
574 error("could not find .symtab section");
575 strtab_sec
= &shdr
[symtab_sec
->sh_link
];
577 symtab
= (ElfW(Sym
) *)sdata
[symtab_sec
- shdr
];
578 strtab
= (char *)sdata
[symtab_sec
->sh_link
];
580 nb_syms
= symtab_sec
->sh_size
/ sizeof(ElfW(Sym
));
582 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
583 swab32s(&sym
->st_name
);
584 swabls(&sym
->st_value
);
585 swabls(&sym
->st_size
);
586 swab16s(&sym
->st_shndx
);
593 #endif /* CONFIG_FORMAT_ELF */
595 #ifdef CONFIG_FORMAT_COFF
598 struct external_scnhdr
*shdr
;
600 struct external_filehdr fhdr
;
601 struct external_syment
*coff_symtab
;
603 int coff_text_shndx
, coff_data_shndx
;
607 #define STRTAB_SIZE 4
612 #define T_FUNCTION 0x20
615 void sym_ent_name(struct external_syment
*ext_sym
, EXE_SYM
*sym
)
620 if (ext_sym
->e
.e
.e_zeroes
!= 0) {
622 for(i
= 0; i
< 8; i
++) {
623 c
= ext_sym
->e
.e_name
[i
];
630 pstrcpy(sym
->st_name
, sizeof(sym
->st_name
), strtab
+ ext_sym
->e
.e
.e_offset
);
633 /* now convert the name to a C name (suppress the leading '_') */
634 if (sym
->st_name
[0] == '_') {
635 len
= strlen(sym
->st_name
);
636 memmove(sym
->st_name
, sym
->st_name
+ 1, len
- 1);
637 sym
->st_name
[len
- 1] = '\0';
641 char *name_for_dotdata(struct coff_rel
*rel
)
644 struct coff_sym
*sym
;
647 text_data
= *(uint32_t *)(text
+ rel
->r_offset
);
649 for (i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
650 if (sym
->st_syment
->e_scnum
== data_shndx
&&
651 text_data
>= sym
->st_value
&&
652 text_data
< sym
->st_value
+ sym
->st_size
) {
661 static char *get_sym_name(EXE_SYM
*sym
)
666 static char *get_rel_sym_name(EXE_RELOC
*rel
)
669 name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
670 if (!strcmp(name
, ".data"))
671 name
= name_for_dotdata(rel
);
677 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
679 return rel
->r_offset
;
682 struct external_scnhdr
*find_coff_section(struct external_scnhdr
*shdr
, int shnum
, const char *name
)
686 struct external_scnhdr
*sec
;
688 for(i
= 0; i
< shnum
; i
++) {
692 shname
= sec
->s_name
;
693 if (!strcmp(shname
, name
))
699 /* load a coff object file */
700 int load_object(const char *filename
)
703 struct external_scnhdr
*sec
, *text_sec
, *data_sec
;
705 struct external_syment
*ext_sym
;
706 struct external_reloc
*coff_relocs
;
707 struct external_reloc
*ext_rel
;
714 fd
= open(filename
, O_RDONLY
720 error("can't open file '%s'", filename
);
722 /* Read COFF header. */
723 if (read(fd
, &fhdr
, sizeof (fhdr
)) != sizeof (fhdr
))
724 error("unable to read file header");
726 /* Check COFF identification. */
727 if (fhdr
.f_magic
!= I386MAGIC
) {
728 error("bad COFF header");
732 /* read section headers */
733 shdr
= load_data(fd
, sizeof(struct external_filehdr
) + fhdr
.f_opthdr
, fhdr
.f_nscns
* sizeof(struct external_scnhdr
));
735 /* read all section data */
736 sdata
= malloc(sizeof(void *) * fhdr
.f_nscns
);
737 memset(sdata
, 0, sizeof(void *) * fhdr
.f_nscns
);
739 for(i
= 0;i
< fhdr
.f_nscns
; i
++) {
741 if (!strstart(sec
->s_name
, ".bss", &p
))
742 sdata
[i
] = load_data(fd
, sec
->s_scnptr
, sec
->s_size
);
747 text_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".text");
749 error("could not find .text section");
750 coff_text_shndx
= text_sec
- shdr
;
751 text
= sdata
[coff_text_shndx
];
754 data_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".data");
756 error("could not find .data section");
757 coff_data_shndx
= data_sec
- shdr
;
759 coff_symtab
= load_data(fd
, fhdr
.f_symptr
, fhdr
.f_nsyms
*SYMESZ
);
760 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
762 printf(" %02x", ((uint8_t *)ext_sym
->e
.e_name
)[i
]);
767 n_strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), STRTAB_SIZE
);
768 strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), *n_strtab
);
770 nb_syms
= fhdr
.f_nsyms
;
772 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
773 if (strstart(ext_sym
->e
.e_name
, ".text", NULL
))
774 text_shndx
= ext_sym
->e_scnum
;
775 if (strstart(ext_sym
->e
.e_name
, ".data", NULL
))
776 data_shndx
= ext_sym
->e_scnum
;
779 /* set coff symbol */
780 symtab
= malloc(sizeof(struct coff_sym
) * nb_syms
);
782 for (i
= 0, ext_sym
= coff_symtab
, sym
= symtab
; i
< nb_syms
; i
++, ext_sym
++, sym
++) {
783 memset(sym
, 0, sizeof(*sym
));
784 sym
->st_syment
= ext_sym
;
785 sym_ent_name(ext_sym
, sym
);
786 sym
->st_value
= ext_sym
->e_value
;
788 aux_size
= *(int8_t *)ext_sym
->e_numaux
;
789 if (ext_sym
->e_scnum
== text_shndx
&& ext_sym
->e_type
== T_FUNCTION
) {
790 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
791 if ((ext_sym
+ j
)->e_scnum
== text_shndx
&&
792 (ext_sym
+ j
)->e_type
== T_FUNCTION
){
793 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
795 } else if (j
== nb_syms
- i
- 1) {
796 sec
= &shdr
[coff_text_shndx
];
797 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
801 } else if (ext_sym
->e_scnum
== data_shndx
&& *(uint8_t *)ext_sym
->e_sclass
== C_EXTERNAL
) {
802 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
803 if ((ext_sym
+ j
)->e_scnum
== data_shndx
) {
804 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
806 } else if (j
== nb_syms
- i
- 1) {
807 sec
= &shdr
[coff_data_shndx
];
808 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
816 sym
->st_type
= ext_sym
->e_type
;
817 sym
->st_shndx
= ext_sym
->e_scnum
;
821 /* find text relocations, if any */
822 sec
= &shdr
[coff_text_shndx
];
823 coff_relocs
= load_data(fd
, sec
->s_relptr
, sec
->s_nreloc
*RELSZ
);
824 nb_relocs
= sec
->s_nreloc
;
826 /* set coff relocation */
827 relocs
= malloc(sizeof(struct coff_rel
) * nb_relocs
);
828 for (i
= 0, ext_rel
= coff_relocs
, rel
= relocs
; i
< nb_relocs
;
829 i
++, ext_rel
++, rel
++) {
830 memset(rel
, 0, sizeof(*rel
));
831 rel
->r_reloc
= ext_rel
;
832 rel
->r_offset
= *(uint32_t *)ext_rel
->r_vaddr
;
833 rel
->r_type
= *(uint16_t *)ext_rel
->r_type
;
838 #endif /* CONFIG_FORMAT_COFF */
840 #ifdef CONFIG_FORMAT_MACH
843 struct mach_header mach_hdr
;
846 struct segment_command
*segment
= 0;
847 struct dysymtab_command
*dysymtabcmd
= 0;
848 struct symtab_command
*symtabcmd
= 0;
851 struct section
*section_hdr
;
852 struct section
*text_sec_hdr
;
856 struct relocation_info
*relocs
;
860 struct nlist
*symtab_std
;
863 /* indirect symbols */
866 /* Utility functions */
868 static inline char *find_str_by_index(int index
)
873 /* Used by dyngen common code */
874 static char *get_sym_name(EXE_SYM
*sym
)
876 char *name
= find_str_by_index(sym
->n_un
.n_strx
);
878 if ( sym
->n_type
& N_STAB
) /* Debug symbols are ignored */
889 /* find a section index given its segname, sectname */
890 static int find_mach_sec_index(struct section
*section_hdr
, int shnum
, const char *segname
,
891 const char *sectname
)
894 struct section
*sec
= section_hdr
;
896 for(i
= 0; i
< shnum
; i
++, sec
++) {
897 if (!sec
->segname
|| !sec
->sectname
)
899 if (!strcmp(sec
->sectname
, sectname
) && !strcmp(sec
->segname
, segname
))
905 /* find a section header given its segname, sectname */
906 struct section
*find_mach_sec_hdr(struct section
*section_hdr
, int shnum
, const char *segname
,
907 const char *sectname
)
909 int index
= find_mach_sec_index(section_hdr
, shnum
, segname
, sectname
);
912 return section_hdr
+index
;
916 static inline void fetch_next_pair_value(struct relocation_info
* rel
, unsigned int *value
)
918 struct scattered_relocation_info
* scarel
;
920 if(R_SCATTERED
& rel
->r_address
) {
921 scarel
= (struct scattered_relocation_info
*)rel
;
922 if(scarel
->r_type
!= PPC_RELOC_PAIR
)
923 error("fetch_next_pair_value: looking for a pair which was not found (1)");
924 *value
= scarel
->r_value
;
926 if(rel
->r_type
!= PPC_RELOC_PAIR
)
927 error("fetch_next_pair_value: looking for a pair which was not found (2)");
928 *value
= rel
->r_address
;
932 /* find a sym name given its value, in a section number */
933 static const char * find_sym_with_value_and_sec_number( int value
, int sectnum
, int * offset
)
937 for( i
= 0 ; i
< nb_syms
; i
++ )
939 if( !(symtab
[i
].n_type
& N_STAB
) && (symtab
[i
].n_type
& N_SECT
) &&
940 (symtab
[i
].n_sect
== sectnum
) && (symtab
[i
].st_value
<= value
) )
942 if( (ret
<0) || (symtab
[i
].st_value
>= symtab
[ret
].st_value
) )
950 *offset
= value
- symtab
[ret
].st_value
;
951 return get_sym_name(&symtab
[ret
]);
956 * Find symbol name given a (virtual) address, and a section which is of type
957 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
959 static const char * find_reloc_name_in_sec_ptr(int address
, struct section
* sec_hdr
)
961 unsigned int tocindex
, symindex
, size
;
962 const char *name
= 0;
965 if(!( address
>= sec_hdr
->addr
&& address
< (sec_hdr
->addr
+ sec_hdr
->size
) ) )
968 if( sec_hdr
->flags
& S_SYMBOL_STUBS
){
969 size
= sec_hdr
->reserved2
;
974 else if( sec_hdr
->flags
& S_LAZY_SYMBOL_POINTERS
||
975 sec_hdr
->flags
& S_NON_LAZY_SYMBOL_POINTERS
)
976 size
= sizeof(unsigned long);
980 /* Compute our index in toc */
981 tocindex
= (address
- sec_hdr
->addr
)/size
;
982 symindex
= tocdylib
[sec_hdr
->reserved1
+ tocindex
];
984 name
= get_sym_name(&symtab
[symindex
]);
989 static const char * find_reloc_name_given_its_address(int address
)
992 for(i
= 0; i
< segment
->nsects
; i
++)
994 const char * name
= find_reloc_name_in_sec_ptr(address
, §ion_hdr
[i
]);
1001 static const char * get_reloc_name(EXE_RELOC
* rel
, int * sslide
)
1004 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
1005 int sectnum
= rel
->r_symbolnum
;
1009 /* init the slide value */
1012 if(R_SCATTERED
& rel
->r_address
)
1013 return (char *)find_reloc_name_given_its_address(sca_rel
->r_value
);
1017 /* ignore debug sym */
1018 if ( symtab
[rel
->r_symbolnum
].n_type
& N_STAB
)
1020 return get_sym_name(&symtab
[rel
->r_symbolnum
]);
1023 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1024 sectoffset
= *(uint32_t *)(text
+ rel
->r_address
) & 0xffff;
1026 if(sectnum
==0xffffff)
1030 if(sectnum
> segment
->nsects
)
1031 error("sectnum > segment->nsects");
1035 case PPC_RELOC_LO16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
|= (other_half
<< 16);
1037 case PPC_RELOC_HI16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) | (uint16_t)(other_half
& 0xffff);
1039 case PPC_RELOC_HA16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) + (int16_t)(other_half
& 0xffff);
1041 case PPC_RELOC_BR24
:
1042 sectoffset
= ( *(uint32_t *)(text
+ rel
->r_address
) & 0x03fffffc );
1043 if (sectoffset
& 0x02000000) sectoffset
|= 0xfc000000;
1046 error("switch(rel->type) not found");
1050 sectoffset
+= rel
->r_address
;
1052 if (rel
->r_type
== PPC_RELOC_BR24
)
1053 name
= (char *)find_reloc_name_in_sec_ptr((int)sectoffset
, §ion_hdr
[sectnum
-1]);
1055 /* search it in the full symbol list, if not found */
1057 name
= (char *)find_sym_with_value_and_sec_number(sectoffset
, sectnum
, sslide
);
1062 /* Used by dyngen common code */
1063 static const char * get_rel_sym_name(EXE_RELOC
* rel
)
1066 return get_reloc_name( rel
, &sslide
);
1069 /* Used by dyngen common code */
1070 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
1072 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
1073 if(R_SCATTERED
& rel
->r_address
)
1074 return sca_rel
->r_address
;
1076 return rel
->r_address
;
1079 /* load a mach-o object file */
1080 int load_object(const char *filename
)
1083 unsigned int offset_to_segment
= 0;
1084 unsigned int offset_to_dysymtab
= 0;
1085 unsigned int offset_to_symtab
= 0;
1086 struct load_command lc
;
1089 struct nlist
*syment
;
1091 fd
= open(filename
, O_RDONLY
);
1093 error("can't open file '%s'", filename
);
1095 /* Read Mach header. */
1096 if (read(fd
, &mach_hdr
, sizeof (mach_hdr
)) != sizeof (mach_hdr
))
1097 error("unable to read file header");
1099 /* Check Mach identification. */
1100 if (!check_mach_header(mach_hdr
)) {
1101 error("bad Mach header");
1104 if (mach_hdr
.cputype
!= CPU_TYPE_POWERPC
)
1105 error("Unsupported CPU");
1107 if (mach_hdr
.filetype
!= MH_OBJECT
)
1108 error("Unsupported Mach Object");
1110 /* read segment headers */
1111 for(i
=0, j
=sizeof(mach_hdr
); i
<mach_hdr
.ncmds
; i
++)
1113 if(read(fd
, &lc
, sizeof(struct load_command
)) != sizeof(struct load_command
))
1114 error("unable to read load_command");
1115 if(lc
.cmd
== LC_SEGMENT
)
1117 offset_to_segment
= j
;
1118 lseek(fd
, offset_to_segment
, SEEK_SET
);
1119 segment
= malloc(sizeof(struct segment_command
));
1120 if(read(fd
, segment
, sizeof(struct segment_command
)) != sizeof(struct segment_command
))
1121 error("unable to read LC_SEGMENT");
1123 if(lc
.cmd
== LC_DYSYMTAB
)
1125 offset_to_dysymtab
= j
;
1126 lseek(fd
, offset_to_dysymtab
, SEEK_SET
);
1127 dysymtabcmd
= malloc(sizeof(struct dysymtab_command
));
1128 if(read(fd
, dysymtabcmd
, sizeof(struct dysymtab_command
)) != sizeof(struct dysymtab_command
))
1129 error("unable to read LC_DYSYMTAB");
1131 if(lc
.cmd
== LC_SYMTAB
)
1133 offset_to_symtab
= j
;
1134 lseek(fd
, offset_to_symtab
, SEEK_SET
);
1135 symtabcmd
= malloc(sizeof(struct symtab_command
));
1136 if(read(fd
, symtabcmd
, sizeof(struct symtab_command
)) != sizeof(struct symtab_command
))
1137 error("unable to read LC_SYMTAB");
1141 lseek(fd
, j
, SEEK_SET
);
1145 error("unable to find LC_SEGMENT");
1147 /* read section headers */
1148 section_hdr
= load_data(fd
, offset_to_segment
+ sizeof(struct segment_command
), segment
->nsects
* sizeof(struct section
));
1150 /* read all section data */
1151 sdata
= (uint8_t **)malloc(sizeof(void *) * segment
->nsects
);
1152 memset(sdata
, 0, sizeof(void *) * segment
->nsects
);
1154 /* Load the data in section data */
1155 for(i
= 0; i
< segment
->nsects
; i
++) {
1156 sdata
[i
] = load_data(fd
, section_hdr
[i
].offset
, section_hdr
[i
].size
);
1160 text_sec_hdr
= find_mach_sec_hdr(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1161 i
= find_mach_sec_index(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1162 if (i
== -1 || !text_sec_hdr
)
1163 error("could not find __TEXT,__text section");
1166 /* Make sure dysym was loaded */
1167 if(!(int)dysymtabcmd
)
1168 error("could not find __DYSYMTAB segment");
1170 /* read the table of content of the indirect sym */
1171 tocdylib
= load_data( fd
, dysymtabcmd
->indirectsymoff
, dysymtabcmd
->nindirectsyms
* sizeof(uint32_t) );
1173 /* Make sure symtab was loaded */
1175 error("could not find __SYMTAB segment");
1176 nb_syms
= symtabcmd
->nsyms
;
1178 symtab_std
= load_data(fd
, symtabcmd
->symoff
, symtabcmd
->nsyms
* sizeof(struct nlist
));
1179 strtab
= load_data(fd
, symtabcmd
->stroff
, symtabcmd
->strsize
);
1181 symtab
= malloc(sizeof(EXE_SYM
) * nb_syms
);
1183 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1184 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< nb_syms
; i
++, sym
++, syment
++) {
1185 struct nlist
*sym_follow
, *sym_next
= 0;
1187 memset(sym
, 0, sizeof(*sym
));
1189 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
1192 memcpy(sym
, syment
, sizeof(*syment
));
1194 /* Find the following symbol in order to get the current symbol size */
1195 for(j
= 0, sym_follow
= symtab_std
; j
< nb_syms
; j
++, sym_follow
++) {
1196 if ( sym_follow
->n_sect
!= 1 || sym_follow
->n_type
& N_STAB
|| !(sym_follow
->n_value
> sym
->st_value
))
1199 sym_next
= sym_follow
;
1202 if(!(sym_next
->n_value
> sym_follow
->n_value
))
1204 sym_next
= sym_follow
;
1207 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
1209 sym
->st_size
= text_sec_hdr
->size
- sym
->st_value
;
1213 relocs
= load_data(fd
, text_sec_hdr
->reloff
, text_sec_hdr
->nreloc
* sizeof(struct relocation_info
));
1214 nb_relocs
= text_sec_hdr
->nreloc
;
1220 #endif /* CONFIG_FORMAT_MACH */
1222 /* return true if the expression is a label reference */
1223 int get_reloc_expr(char *name
, int name_size
, const char *sym_name
)
1227 if (strstart(sym_name
, "__op_param", &p
)) {
1228 snprintf(name
, name_size
, "param%s", p
);
1229 } else if (strstart(sym_name
, "__op_gen_label", &p
)) {
1230 snprintf(name
, name_size
, "param%s", p
);
1233 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1234 if (sym_name
[0] == '.')
1235 snprintf(name
, name_size
,
1236 "(long)(&__dot_%s)",
1240 snprintf(name
, name_size
, "(long)(&%s)", sym_name
);
1247 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1250 struct plt_entry
*next
;
1252 unsigned long addend
;
1256 get_plt_index (const char *name
, unsigned long addend
)
1258 struct plt_entry
*plt
, *prev
= NULL
;
1261 /* see if we already have an entry for this target: */
1262 for (plt
= plt_list
; plt
; ++index
, prev
= plt
, plt
= plt
->next
)
1263 if (strcmp(plt
->name
, name
) == 0 && plt
->addend
== addend
)
1266 /* nope; create a new PLT entry: */
1268 plt
= malloc(sizeof(*plt
));
1273 memset(plt
, 0, sizeof(*plt
));
1274 plt
->name
= strdup(name
);
1275 plt
->addend
= addend
;
1277 /* append to plt-list: */
1289 int arm_emit_ldr_info(const char *name
, unsigned long start_offset
,
1290 FILE *outfile
, uint8_t *p_start
, uint8_t *p_end
,
1291 ELF_RELOC
*relocs
, int nb_relocs
)
1295 int offset
, min_offset
, pc_offset
, data_size
, spare
, max_pool
;
1296 uint8_t data_allocated
[1024];
1297 unsigned int data_index
;
1300 memset(data_allocated
, 0, sizeof(data_allocated
));
1303 min_offset
= p_end
- p_start
;
1305 while (p
< p_start
+ min_offset
) {
1306 insn
= get32((uint32_t *)p
);
1307 /* TODO: Armv5e ldrd. */
1308 /* TODO: VFP load. */
1309 if ((insn
& 0x0d5f0000) == 0x051f0000) {
1310 /* ldr reg, [pc, #im] */
1311 offset
= insn
& 0xfff;
1312 if (!(insn
& 0x00800000))
1316 } else if ((insn
& 0x0e5f0f00) == 0x0c1f0100) {
1318 offset
= (insn
& 0xff) << 2;
1319 if (!(insn
& 0x00800000))
1323 } else if ((insn
& 0x0fff0000) == 0x028f0000) {
1324 /* Some gcc load a doubleword immediate with
1326 ldmia regN, {regN, regM}
1327 Hope and pray the compiler never generates somethin like
1328 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1331 r
= (insn
& 0xf00) >> 7;
1332 offset
= ((insn
& 0xff) >> r
) | ((insn
& 0xff) << (32 - r
));
1340 /* PC-relative load needs fixing up. */
1341 if (spare
> max_pool
- offset
)
1342 spare
= max_pool
- offset
;
1343 if ((offset
& 3) !=0)
1344 error("%s:%04x: pc offset must be 32 bit aligned",
1345 name
, start_offset
+ p
- p_start
);
1347 error("%s:%04x: Embedded literal value",
1348 name
, start_offset
+ p
- p_start
);
1349 pc_offset
= p
- p_start
+ offset
+ 8;
1350 if (pc_offset
<= (p
- p_start
) ||
1351 pc_offset
>= (p_end
- p_start
))
1352 error("%s:%04x: pc offset must point inside the function code",
1353 name
, start_offset
+ p
- p_start
);
1354 if (pc_offset
< min_offset
)
1355 min_offset
= pc_offset
;
1357 /* The intruction position */
1358 fprintf(outfile
, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1360 /* The position of the constant pool data. */
1361 data_index
= ((p_end
- p_start
) - pc_offset
) >> 2;
1362 fprintf(outfile
, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1364 fprintf(outfile
, " arm_ldr_ptr->type = %d;\n", type
);
1365 fprintf(outfile
, " arm_ldr_ptr++;\n");
1371 /* Copy and relocate the constant pool data. */
1372 data_size
= (p_end
- p_start
) - min_offset
;
1373 if (data_size
> 0 && outfile
) {
1374 spare
+= min_offset
;
1375 fprintf(outfile
, " arm_data_ptr -= %d;\n", data_size
>> 2);
1376 fprintf(outfile
, " arm_pool_ptr -= %d;\n", data_size
);
1377 fprintf(outfile
, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1378 " arm_pool_ptr = gen_code_ptr + %d;\n",
1382 for (pc_offset
= min_offset
;
1383 pc_offset
< p_end
- p_start
;
1387 int i
, addend
, type
;
1388 const char *sym_name
;
1392 addend
= get32((uint32_t *)(p_start
+ pc_offset
));
1394 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1395 if (rel
->r_offset
== (pc_offset
+ start_offset
)) {
1396 sym_name
= get_rel_sym_name(rel
);
1397 /* the compiler leave some unnecessary references to the code */
1398 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1399 type
= ELF32_R_TYPE(rel
->r_info
);
1400 if (type
!= R_ARM_ABS32
)
1401 error("%s: unsupported data relocation", name
);
1405 fprintf(outfile
, " arm_data_ptr[%d] = 0x%x",
1406 data_index
, addend
);
1407 if (relname
[0] != '\0')
1408 fprintf(outfile
, " + %s", relname
);
1409 fprintf(outfile
, ";\n");
1418 insn
= get32((uint32_t *)p
);
1419 /* The last instruction must be an ldm instruction. There are several
1420 forms generated by gcc:
1421 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1423 ldmea fp, {..., pc} */
1424 if ((insn
& 0xffff8000) == 0xe99d8000) {
1427 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1431 } else if ((insn
& 0xffff8000) != 0xe89d8000
1432 && (insn
& 0xffff8000) != 0xe91b8000) {
1435 printf("%s: invalid epilog\n", name
);
1444 /* generate op code */
1445 void gen_code(const char *name
, host_ulong offset
, host_ulong size
,
1446 FILE *outfile
, int gen_switch
)
1449 uint8_t *p_start
, *p_end
;
1450 host_ulong start_offset
;
1452 uint8_t args_present
[MAX_ARGS
];
1453 const char *sym_name
, *p
;
1456 /* Compute exact size excluding prologue and epilogue instructions.
1457 * Increment start_offset to skip epilogue instructions, then compute
1458 * copy_size the indicate the size of the remaining instructions (in
1461 p_start
= text
+ offset
;
1462 p_end
= p_start
+ size
;
1463 start_offset
= offset
;
1464 #if defined(HOST_I386) || defined(HOST_X86_64)
1465 #ifdef CONFIG_FORMAT_COFF
1470 error("empty code for %s", name
);
1471 while (*p
!= 0xc3) {
1474 error("ret or jmp expected at the end of %s", name
);
1476 copy_size
= p
- p_start
;
1481 len
= p_end
- p_start
;
1483 error("empty code for %s", name
);
1484 if (p_end
[-1] == 0xc3) {
1487 error("ret or jmp expected at the end of %s", name
);
1492 #elif defined(HOST_PPC)
1495 p
= (void *)(p_end
- 4);
1497 error("empty code for %s", name
);
1498 if (get32((uint32_t *)p
) != 0x4e800020)
1499 error("blr expected at the end of %s", name
);
1500 copy_size
= p
- p_start
;
1502 #elif defined(HOST_S390)
1505 p
= (void *)(p_end
- 2);
1507 error("empty code for %s", name
);
1508 if ((get16((uint16_t *)p
) & 0xfff0) != 0x07f0)
1509 error("br expected at the end of %s", name
);
1510 copy_size
= p
- p_start
;
1512 #elif defined(HOST_ALPHA)
1517 /* XXX: check why it occurs */
1519 error("empty code for %s", name
);
1521 if (get32((uint32_t *)p
) != 0x6bfa8001)
1522 error("ret expected at the end of %s", name
);
1523 copy_size
= p
- p_start
;
1525 #elif defined(HOST_IA64)
1528 p
= (void *)(p_end
- 4);
1530 error("empty code for %s", name
);
1531 /* br.ret.sptk.many b0;; */
1533 if (get32((uint32_t *)p
) != 0x00840008)
1534 error("br.ret.sptk.many b0;; expected at the end of %s", name
);
1535 copy_size
= p_end
- p_start
;
1537 #elif defined(HOST_SPARC)
1539 #define INSN_SAVE 0x9de3a000
1540 #define INSN_RET 0x81c7e008
1541 #define INSN_RETL 0x81c3e008
1542 #define INSN_RESTORE 0x81e80000
1543 #define INSN_RETURN 0x81cfe008
1544 #define INSN_NOP 0x01000000
1545 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1546 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1548 uint32_t start_insn
, end_insn1
, end_insn2
;
1550 p
= (void *)(p_end
- 8);
1552 error("empty code for %s", name
);
1553 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1554 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1555 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1556 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1557 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1559 start_offset
+= 0x4;
1560 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1561 /* SPARC v7: ret; restore; */ ;
1562 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1563 /* SPARC v9: return; nop; */ ;
1564 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1565 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1568 error("ret; restore; not found at end of %s", name
);
1569 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1572 error("No save at the beginning of %s", name
);
1575 /* Skip a preceeding nop, if present. */
1577 skip_insn
= get32((uint32_t *)(p
- 0x4));
1578 if (skip_insn
== INSN_NOP
)
1582 copy_size
= p
- p_start
;
1584 #elif defined(HOST_SPARC64)
1586 #define INSN_SAVE 0x9de3a000
1587 #define INSN_RET 0x81c7e008
1588 #define INSN_RETL 0x81c3e008
1589 #define INSN_RESTORE 0x81e80000
1590 #define INSN_RETURN 0x81cfe008
1591 #define INSN_NOP 0x01000000
1592 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1593 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1595 uint32_t start_insn
, end_insn1
, end_insn2
, skip_insn
;
1597 p
= (void *)(p_end
- 8);
1599 /* XXX: check why it occurs */
1601 error("empty code for %s", name
);
1603 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1604 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1605 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1606 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1607 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1609 start_offset
+= 0x4;
1610 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1611 /* SPARC v7: ret; restore; */ ;
1612 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1613 /* SPARC v9: return; nop; */ ;
1614 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1615 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1618 error("ret; restore; not found at end of %s", name
);
1619 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1622 error("No save at the beginning of %s", name
);
1626 /* Skip a preceeding nop, if present. */
1628 skip_insn
= get32((uint32_t *)(p
- 0x4));
1629 if (skip_insn
== 0x01000000)
1634 copy_size
= p
- p_start
;
1636 #elif defined(HOST_ARM)
1640 if ((p_end
- p_start
) <= 16)
1641 error("%s: function too small", name
);
1642 if (get32((uint32_t *)p_start
) != 0xe1a0c00d ||
1643 (get32((uint32_t *)(p_start
+ 4)) & 0xffff0000) != 0xe92d0000 ||
1644 get32((uint32_t *)(p_start
+ 8)) != 0xe24cb004)
1645 error("%s: invalid prolog", name
);
1648 insn
= get32((uint32_t *)p_start
);
1649 if ((insn
& 0xffffff00) == 0xe24dd000) {
1650 /* Stack adjustment. Assume op uses the frame pointer. */
1654 copy_size
= arm_emit_ldr_info(name
, start_offset
, NULL
, p_start
, p_end
,
1657 #elif defined(HOST_M68K)
1660 p
= (void *)(p_end
- 2);
1662 error("empty code for %s", name
);
1663 // remove NOP's, probably added for alignment
1664 while ((get16((uint16_t *)p
) == 0x4e71) &&
1667 if (get16((uint16_t *)p
) != 0x4e75)
1668 error("rts expected at the end of %s", name
);
1669 copy_size
= p
- p_start
;
1671 #elif defined(HOST_HPPA)
1676 uint32_t insn
= get32((uint32_t *)p
);
1677 if (insn
== 0x6bc23fd9 || /* stw rp,-14(sp) */
1678 insn
== 0x08030241 || /* copy r3,r1 */
1679 insn
== 0x081e0243 || /* copy sp,r3 */
1680 (insn
& 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1681 (insn
& 0xffffc000) == 0x6fc10000) /* stwm r1,x(sp) */
1686 start_offset
+= p
- p_start
;
1690 while (p
> p_start
) {
1691 uint32_t insn
= get32((uint32_t *)p
);
1692 if ((insn
& 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */
1693 (insn
& 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */
1694 (insn
& 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1695 insn
== 0x48623fd9 || /* ldw -14(r3),rp */
1696 insn
== 0xe840c000 || /* bv r0(rp) */
1697 insn
== 0xe840c002) /* bv,n r0(rp) */
1704 error("empty code for %s", name
);
1706 copy_size
= p
- p_start
;
1708 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1710 #define INSN_RETURN 0x03e00008
1711 #define INSN_NOP 0x00000000
1715 if (p
< (p_start
+ 0x8)) {
1716 error("empty code for %s", name
);
1718 uint32_t end_insn1
, end_insn2
;
1721 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1722 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1723 if (end_insn1
!= INSN_RETURN
&& end_insn2
!= INSN_NOP
)
1724 error("jr ra not found at end of %s", name
);
1726 copy_size
= p
- p_start
;
1729 #error unsupported CPU
1732 /* compute the number of arguments by looking at the relocations */
1733 for(i
= 0;i
< MAX_ARGS
; i
++)
1734 args_present
[i
] = 0;
1736 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1737 host_ulong offset
= get_rel_offset(rel
);
1738 if (offset
>= start_offset
&&
1739 offset
< start_offset
+ (p_end
- p_start
)) {
1740 sym_name
= get_rel_sym_name(rel
);
1743 if (strstart(sym_name
, "__op_param", &p
) ||
1744 strstart(sym_name
, "__op_gen_label", &p
)) {
1745 n
= strtoul(p
, NULL
, 10);
1747 error("too many arguments in %s", name
);
1748 args_present
[n
- 1] = 1;
1754 while (nb_args
< MAX_ARGS
&& args_present
[nb_args
])
1756 for(i
= nb_args
; i
< MAX_ARGS
; i
++) {
1757 if (args_present
[i
])
1758 error("inconsistent argument numbering in %s", name
);
1761 if (gen_switch
== 2) {
1763 #if defined(HOST_HPPA)
1764 int op_size
= copy_size
;
1769 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
1770 if (rel
->r_offset
>= start_offset
&&
1771 rel
->r_offset
< start_offset
+ copy_size
) {
1772 sym_name
= get_rel_sym_name(rel
);
1773 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
1774 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1775 type
= ELF32_R_TYPE(rel
->r_info
);
1777 if (!is_label
&& type
== R_PARISC_PCREL17F
) {
1779 op_size
+= 8; /* ldil and be,n instructions */
1785 op_size
+= 4; /* b,l,n instruction, to skip past the stubs */
1787 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, op_size
);
1789 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, copy_size
);
1792 } else if (gen_switch
== 1) {
1795 fprintf(outfile
, "case INDEX_%s: {\n", name
);
1797 fprintf(outfile
, " long ");
1798 for(i
= 0; i
< nb_args
; i
++) {
1800 fprintf(outfile
, ", ");
1801 fprintf(outfile
, "param%d", i
+ 1);
1803 fprintf(outfile
, ";\n");
1805 #if defined(HOST_IA64)
1806 fprintf(outfile
, " extern char %s;\n", name
);
1808 fprintf(outfile
, " extern void %s();\n", name
);
1811 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1812 host_ulong offset
= get_rel_offset(rel
);
1813 if (offset
>= start_offset
&&
1814 offset
< start_offset
+ (p_end
- p_start
)) {
1815 sym_name
= get_rel_sym_name(rel
);
1819 !strstart(sym_name
, "__op_param", NULL
) &&
1820 !strstart(sym_name
, "__op_jmp", NULL
) &&
1821 !strstart(sym_name
, "__op_gen_label", NULL
)) {
1822 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1823 if (sym_name
[0] == '.') {
1825 "extern char __dot_%s __asm__(\"%s\");\n",
1826 sym_name
+1, sym_name
);
1830 #if defined(__APPLE__)
1831 /* Set __attribute((unused)) on darwin because we
1832 want to avoid warning when we don't use the symbol. */
1833 fprintf(outfile
, " extern char %s __attribute__((unused));\n", sym_name
);
1834 #elif defined(HOST_IA64)
1835 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
1837 * PCREL21 br.call targets generally
1838 * are out of range and need to go
1839 * through an "import stub".
1841 fprintf(outfile
, " extern char %s;\n",
1844 fprintf(outfile
, "extern char %s;\n", sym_name
);
1851 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1852 name
, (int)(start_offset
- offset
), copy_size
);
1854 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1855 name
, (int)(start_offset
- offset
), copy_size
);
1858 /* emit code offset information */
1861 const char *sym_name
, *p
;
1865 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
1866 sym_name
= get_sym_name(sym
);
1867 if (strstart(sym_name
, "__op_label", &p
)) {
1869 unsigned long offset
;
1871 /* test if the variable refers to a label inside
1872 the code we are generating */
1873 #ifdef CONFIG_FORMAT_COFF
1874 if (sym
->st_shndx
== text_shndx
) {
1875 ptr
= sdata
[coff_text_shndx
];
1876 } else if (sym
->st_shndx
== data_shndx
) {
1877 ptr
= sdata
[coff_data_shndx
];
1881 #elif defined(CONFIG_FORMAT_MACH)
1884 ptr
= sdata
[sym
->n_sect
-1];
1886 ptr
= sdata
[sym
->st_shndx
];
1889 error("__op_labelN in invalid section");
1890 offset
= sym
->st_value
;
1891 #ifdef CONFIG_FORMAT_MACH
1892 offset
-= section_hdr
[sym
->n_sect
-1].addr
;
1894 val
= *(host_ulong
*)(ptr
+ offset
);
1895 #ifdef ELF_USES_RELOCA
1897 int reloc_shndx
, nb_relocs1
, j
;
1899 /* try to find a matching relocation */
1900 reloc_shndx
= find_reloc(sym
->st_shndx
);
1902 nb_relocs1
= shdr
[reloc_shndx
].sh_size
/
1903 shdr
[reloc_shndx
].sh_entsize
;
1904 rel
= (ELF_RELOC
*)sdata
[reloc_shndx
];
1905 for(j
= 0; j
< nb_relocs1
; j
++) {
1906 if (rel
->r_offset
== offset
) {
1907 val
= rel
->r_addend
;
1915 if (val
>= start_offset
&& val
<= start_offset
+ copy_size
) {
1916 n
= strtol(p
, NULL
, 10);
1917 fprintf(outfile
, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n
, (long)(val
- start_offset
));
1923 /* load parameters in variables */
1924 for(i
= 0; i
< nb_args
; i
++) {
1925 fprintf(outfile
, " param%d = *opparam_ptr++;\n", i
+ 1);
1928 /* patch relocations */
1929 #if defined(HOST_I386)
1935 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1936 if (rel
->r_offset
>= start_offset
&&
1937 rel
->r_offset
< start_offset
+ copy_size
) {
1938 sym_name
= get_rel_sym_name(rel
);
1941 reloc_offset
= rel
->r_offset
- start_offset
;
1942 if (strstart(sym_name
, "__op_jmp", &p
)) {
1944 n
= strtol(p
, NULL
, 10);
1945 /* __op_jmp relocations are done at
1946 runtime to do translated block
1947 chaining: the offset of the instruction
1948 needs to be stored */
1949 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1954 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1955 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
1956 #ifdef CONFIG_FORMAT_ELF
1957 type
= ELF32_R_TYPE(rel
->r_info
);
1962 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1963 reloc_offset
, type
, relname
, addend
);
1966 error("unsupported i386 relocation (%d)", type
);
1971 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1972 reloc_offset
, relname
, addend
);
1975 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1976 reloc_offset
, relname
, reloc_offset
, addend
);
1979 error("unsupported i386 relocation (%d)", type
);
1982 #elif defined(CONFIG_FORMAT_COFF)
1987 temp_name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
1988 if (!strcmp(temp_name
, ".data")) {
1989 for (j
= 0, sym
= symtab
; j
< nb_syms
; j
++, sym
++) {
1990 if (strstart(sym
->st_name
, sym_name
, NULL
)) {
1991 addend
-= sym
->st_value
;
1998 /* TCG uses elf relocation constants */
2000 #define R_386_PC32 2
2009 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2010 reloc_offset
, type
, relname
, addend
);
2013 error("unsupported i386 relocation (%d)", type
);
2018 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2019 reloc_offset
, relname
, addend
);
2022 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
2023 reloc_offset
, relname
, reloc_offset
, addend
);
2026 error("unsupported i386 relocation (%d)", type
);
2030 #error unsupport object format
2035 #elif defined(HOST_X86_64)
2041 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2042 if (rel
->r_offset
>= start_offset
&&
2043 rel
->r_offset
< start_offset
+ copy_size
) {
2044 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2045 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2046 type
= ELF32_R_TYPE(rel
->r_info
);
2047 addend
= rel
->r_addend
;
2048 reloc_offset
= rel
->r_offset
- start_offset
;
2054 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2055 reloc_offset
, type
, relname
, addend
);
2058 error("unsupported X86_64 relocation (%d)", type
);
2063 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2064 reloc_offset
, relname
, addend
);
2067 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2068 reloc_offset
, relname
, addend
);
2071 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2072 reloc_offset
, relname
, reloc_offset
, addend
);
2075 error("unsupported X86_64 relocation (%d)", type
);
2081 #elif defined(HOST_PPC)
2083 #ifdef CONFIG_FORMAT_ELF
2088 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2089 if (rel
->r_offset
>= start_offset
&&
2090 rel
->r_offset
< start_offset
+ copy_size
) {
2091 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2092 reloc_offset
= rel
->r_offset
- start_offset
;
2093 if (strstart(sym_name
, "__op_jmp", &p
)) {
2095 n
= strtol(p
, NULL
, 10);
2096 /* __op_jmp relocations are done at
2097 runtime to do translated block
2098 chaining: the offset of the instruction
2099 needs to be stored */
2100 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2105 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2106 type
= ELF32_R_TYPE(rel
->r_info
);
2107 addend
= rel
->r_addend
;
2110 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2111 reloc_offset
, relname
, addend
);
2113 case R_PPC_ADDR16_LO
:
2114 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2115 reloc_offset
, relname
, addend
);
2117 case R_PPC_ADDR16_HI
:
2118 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2119 reloc_offset
, relname
, addend
);
2121 case R_PPC_ADDR16_HA
:
2122 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2123 reloc_offset
, relname
, addend
);
2126 /* warning: must be at 32 MB distancy */
2127 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2128 reloc_offset
, reloc_offset
, relname
, reloc_offset
, addend
);
2131 error("unsupported powerpc relocation (%d)", type
);
2135 #elif defined(CONFIG_FORMAT_MACH)
2136 struct scattered_relocation_info
*scarel
;
2137 struct relocation_info
* rel
;
2138 char final_sym_name
[256];
2139 const char *sym_name
;
2144 for(i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2145 unsigned int offset
, length
, value
= 0;
2146 unsigned int type
, pcrel
, isym
= 0;
2147 unsigned int usesym
= 0;
2149 if(R_SCATTERED
& rel
->r_address
) {
2150 scarel
= (struct scattered_relocation_info
*)rel
;
2151 offset
= (unsigned int)scarel
->r_address
;
2152 length
= scarel
->r_length
;
2153 pcrel
= scarel
->r_pcrel
;
2154 type
= scarel
->r_type
;
2155 value
= scarel
->r_value
;
2157 value
= isym
= rel
->r_symbolnum
;
2158 usesym
= (rel
->r_extern
);
2159 offset
= rel
->r_address
;
2160 length
= rel
->r_length
;
2161 pcrel
= rel
->r_pcrel
;
2165 slide
= offset
- start_offset
;
2167 if (!(offset
>= start_offset
&& offset
< start_offset
+ size
))
2168 continue; /* not in our range */
2170 sym_name
= get_reloc_name(rel
, &sslide
);
2172 if(usesym
&& symtab
[isym
].n_type
& N_STAB
)
2173 continue; /* don't handle STAB (debug sym) */
2175 if (sym_name
&& strstart(sym_name
, "__op_jmp", &p
)) {
2177 n
= strtol(p
, NULL
, 10);
2178 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2180 continue; /* Nothing more to do */
2184 fprintf(outfile
, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2185 name
, value
, usesym
? "use sym" : "don't use sym", offset
, length
, pcrel
? "pcrel":"", type
);
2186 continue; /* dunno how to handle without final_sym_name */
2189 get_reloc_expr(final_sym_name
, sizeof(final_sym_name
),
2192 case PPC_RELOC_BR24
:
2193 if (!strstart(sym_name
,"__op_gen_label",&p
)) {
2194 fprintf(outfile
, "{\n");
2195 fprintf(outfile
, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide
);
2196 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",
2197 slide
, slide
, name
, sslide
);
2198 fprintf(outfile
, "}\n");
2200 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2201 slide
, slide
, final_sym_name
, slide
);
2204 case PPC_RELOC_HI16
:
2205 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2206 slide
, final_sym_name
, sslide
);
2208 case PPC_RELOC_LO16
:
2209 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2210 slide
, final_sym_name
, sslide
);
2212 case PPC_RELOC_HA16
:
2213 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2214 slide
, final_sym_name
, sslide
);
2217 error("unsupported powerpc relocation (%d)", type
);
2221 #error unsupport object format
2224 #elif defined(HOST_S390)
2230 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2231 if (rel
->r_offset
>= start_offset
&&
2232 rel
->r_offset
< start_offset
+ copy_size
) {
2233 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2234 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2235 type
= ELF32_R_TYPE(rel
->r_info
);
2236 addend
= rel
->r_addend
;
2237 reloc_offset
= rel
->r_offset
- start_offset
;
2240 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2241 reloc_offset
, relname
, addend
);
2244 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2245 reloc_offset
, relname
, addend
);
2248 fprintf(outfile
, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2249 reloc_offset
, relname
, addend
);
2252 if (ELF32_ST_TYPE(symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_info
) == STT_SECTION
) {
2254 " *(uint32_t *)(gen_code_ptr + %d) += "
2255 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2256 reloc_offset
, name
);
2260 " *(uint32_t *)(gen_code_ptr + %d) = "
2261 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2262 reloc_offset
, relname
, addend
, reloc_offset
);
2265 error("unsupported s390 relocation (%d)", type
);
2270 #elif defined(HOST_ALPHA)
2272 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2273 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2277 type
= ELF64_R_TYPE(rel
->r_info
);
2278 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2279 reloc_offset
= rel
->r_offset
- start_offset
;
2281 case R_ALPHA_GPDISP
:
2282 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2283 as an immediate instead of constructing it from the pv or ra. */
2284 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2286 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2287 reloc_offset
+ (int)rel
->r_addend
);
2289 case R_ALPHA_LITUSE
:
2290 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2291 now, since some called functions (libc) need pv to be set up. */
2294 /* Branch target prediction hint. Ignore for now. Should be already
2295 correct for in-function jumps. */
2297 case R_ALPHA_LITERAL
:
2298 /* Load a literal from the GOT relative to the gp. Since there's only a
2299 single gp, nothing is to be done. */
2301 case R_ALPHA_GPRELHIGH
:
2302 /* Handle fake relocations against __op_param symbol. Need to emit the
2303 high part of the immediate value instead. Other symbols need no
2304 special treatment. */
2305 if (strstart(sym_name
, "__op_param", &p
))
2306 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2309 case R_ALPHA_GPRELLOW
:
2310 if (strstart(sym_name
, "__op_param", &p
))
2311 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2315 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2316 set up the gp from the pv. */
2317 fprintf(outfile
, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2318 reloc_offset
, sym_name
, reloc_offset
);
2321 error("unsupported Alpha relocation (%d)", type
);
2326 #elif defined(HOST_IA64)
2328 unsigned long sym_idx
;
2334 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2335 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2336 if (rel
->r_offset
< start_offset
2337 || rel
->r_offset
>= start_offset
+ copy_size
)
2339 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2340 code_offset
= rel
->r_offset
- start_offset
;
2341 if (strstart(sym_name
, "__op_jmp", &p
)) {
2343 n
= strtol(p
, NULL
, 10);
2344 /* __op_jmp relocations are done at
2345 runtime to do translated block
2346 chaining: the offset of the instruction
2347 needs to be stored */
2348 fprintf(outfile
, " jmp_offsets[%d] ="
2349 "%ld + (gen_code_ptr - gen_code_buf);\n",
2353 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2354 type
= ELF64_R_TYPE(rel
->r_info
);
2355 addend
= rel
->r_addend
;
2359 " ia64_imm64(gen_code_ptr + %ld, "
2361 code_offset
, relname
, addend
);
2363 case R_IA64_LTOFF22X
:
2364 case R_IA64_LTOFF22
:
2365 fprintf(outfile
, " IA64_LTOFF(gen_code_ptr + %ld,"
2366 " %s + %ld, %d);\n",
2367 code_offset
, relname
, addend
,
2368 (type
== R_IA64_LTOFF22X
));
2372 " ia64_ldxmov(gen_code_ptr + %ld,"
2373 " %s + %ld);\n", code_offset
, relname
, addend
);
2376 case R_IA64_PCREL21B
:
2377 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2379 " ia64_imm21b(gen_code_ptr + %ld,"
2380 " (long) (%s + %ld -\n\t\t"
2381 "((long) gen_code_ptr + %ld)) >> 4);\n",
2382 code_offset
, relname
, addend
,
2383 code_offset
& ~0xfUL
);
2386 " IA64_PLT(gen_code_ptr + %ld, "
2387 "%d);\t/* %s + %ld */\n",
2389 get_plt_index(sym_name
, addend
),
2394 error("unsupported ia64 relocation (0x%x)",
2398 fprintf(outfile
, " ia64_nop_b(gen_code_ptr + %d);\n",
2399 copy_size
- 16 + 2);
2401 #elif defined(HOST_SPARC)
2407 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2408 if (rel
->r_offset
>= start_offset
&&
2409 rel
->r_offset
< start_offset
+ copy_size
) {
2410 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2411 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2412 type
= ELF32_R_TYPE(rel
->r_info
);
2413 addend
= rel
->r_addend
;
2414 reloc_offset
= rel
->r_offset
- start_offset
;
2417 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2418 reloc_offset
, relname
, addend
);
2422 " *(uint32_t *)(gen_code_ptr + %d) = "
2423 "((*(uint32_t *)(gen_code_ptr + %d)) "
2425 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2426 reloc_offset
, reloc_offset
, relname
, addend
);
2430 " *(uint32_t *)(gen_code_ptr + %d) = "
2431 "((*(uint32_t *)(gen_code_ptr + %d)) "
2433 " | ((%s + %d) & 0x3ff);\n",
2434 reloc_offset
, reloc_offset
, relname
, addend
);
2436 case R_SPARC_WDISP30
:
2438 " *(uint32_t *)(gen_code_ptr + %d) = "
2439 "((*(uint32_t *)(gen_code_ptr + %d)) "
2441 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2442 " & 0x3fffffff);\n",
2443 reloc_offset
, reloc_offset
, relname
, addend
,
2446 case R_SPARC_WDISP22
:
2448 " *(uint32_t *)(gen_code_ptr + %d) = "
2449 "((*(uint32_t *)(gen_code_ptr + %d)) "
2451 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2453 rel
->r_offset
- start_offset
,
2454 rel
->r_offset
- start_offset
,
2456 rel
->r_offset
- start_offset
);
2459 error("unsupported sparc relocation (%d)", type
);
2464 #elif defined(HOST_SPARC64)
2470 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2471 if (rel
->r_offset
>= start_offset
&&
2472 rel
->r_offset
< start_offset
+ copy_size
) {
2473 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2474 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2475 type
= ELF32_R_TYPE(rel
->r_info
);
2476 addend
= rel
->r_addend
;
2477 reloc_offset
= rel
->r_offset
- start_offset
;
2480 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2481 reloc_offset
, relname
, addend
);
2485 " *(uint32_t *)(gen_code_ptr + %d) = "
2486 "((*(uint32_t *)(gen_code_ptr + %d)) "
2488 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2489 reloc_offset
, reloc_offset
, relname
, addend
);
2493 " *(uint32_t *)(gen_code_ptr + %d) = "
2494 "((*(uint32_t *)(gen_code_ptr + %d)) "
2496 " | ((%s + %d) & 0x3ff);\n",
2497 reloc_offset
, reloc_offset
, relname
, addend
);
2500 addend
+= ELF64_R_TYPE_DATA (rel
->r_info
);
2502 " *(uint32_t *)(gen_code_ptr + %d) = "
2503 "((*(uint32_t *)(gen_code_ptr + %d)) "
2505 " | ((%s + %d) & 0x3ff);\n",
2506 reloc_offset
, reloc_offset
, relname
, addend
);
2508 case R_SPARC_WDISP30
:
2510 " *(uint32_t *)(gen_code_ptr + %d) = "
2511 "((*(uint32_t *)(gen_code_ptr + %d)) "
2513 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2514 " & 0x3fffffff);\n",
2515 reloc_offset
, reloc_offset
, relname
, addend
,
2518 case R_SPARC_WDISP22
:
2520 " *(uint32_t *)(gen_code_ptr + %d) = "
2521 "((*(uint32_t *)(gen_code_ptr + %d)) "
2523 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2525 reloc_offset
, reloc_offset
, relname
, addend
,
2530 " *(uint32_t *)(gen_code_ptr + %d) = "
2531 "((*(uint32_t *)(gen_code_ptr + %d)) "
2533 " | (((%s + %d) >> 42) & 0x00000000);\n",
2534 reloc_offset
, reloc_offset
, relname
, addend
);
2539 " *(uint32_t *)(gen_code_ptr + %d) = "
2540 "((*(uint32_t *)(gen_code_ptr + %d)) "
2542 " | (((%s + %d) >> 10) & 0x00000000);\n",
2543 reloc_offset
, reloc_offset
, relname
, addend
);
2548 " *(uint32_t *)(gen_code_ptr + %d) = "
2549 "((*(uint32_t *)(gen_code_ptr + %d)) "
2551 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2552 reloc_offset
, reloc_offset
, relname
, addend
);
2556 error("unsupported sparc64 relocation (%d) for symbol %s", type
, relname
);
2561 #elif defined(HOST_ARM)
2569 insn
= get32((uint32_t *)(p_start
+ 4));
2570 /* If prologue ends in sub sp, sp, #const then assume
2571 op has a stack frame and needs the frame pointer. */
2572 if ((insn
& 0xffffff00) == 0xe24dd000) {
2575 opcode
= 0xe28db000; /* add fp, sp, #0. */
2577 /* ??? Need to undo the extra stack adjustment at the end of the op.
2578 For now just leave the stack misaligned and hope it doesn't break anything
2580 if ((insn
& 4) != 0) {
2581 /* Preserve doubleword stack alignment. */
2583 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2588 insn
= get32((uint32_t *)(p_start
- 4));
2589 /* Calculate the size of the saved registers,
2591 for (i
= 0; i
< 15; i
++) {
2592 if (insn
& (1 << i
))
2596 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode
);
2598 arm_emit_ldr_info(relname
, start_offset
, outfile
, p_start
, p_end
,
2601 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2602 if (rel
->r_offset
>= start_offset
&&
2603 rel
->r_offset
< start_offset
+ copy_size
) {
2604 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2605 /* the compiler leave some unnecessary references to the code */
2606 if (sym_name
[0] == '\0')
2608 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2609 type
= ELF32_R_TYPE(rel
->r_info
);
2610 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2611 reloc_offset
= rel
->r_offset
- start_offset
;
2614 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2615 reloc_offset
, relname
, addend
);
2620 fprintf(outfile
, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2621 reloc_offset
, addend
, relname
);
2624 error("unsupported arm relocation (%d)", type
);
2629 #elif defined(HOST_M68K)
2636 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2637 if (rel
->r_offset
>= start_offset
&&
2638 rel
->r_offset
< start_offset
+ copy_size
) {
2639 sym
= &(symtab
[ELFW(R_SYM
)(rel
->r_info
)]);
2640 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2641 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2642 type
= ELF32_R_TYPE(rel
->r_info
);
2643 addend
= get32((uint32_t *)(text
+ rel
->r_offset
)) + rel
->r_addend
;
2644 reloc_offset
= rel
->r_offset
- start_offset
;
2647 fprintf(outfile
, " /* R_68K_32 RELOC, offset %x */\n", rel
->r_offset
) ;
2648 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2649 reloc_offset
, relname
, addend
);
2652 fprintf(outfile
, " /* R_68K_PC32 RELOC, offset %x */\n", rel
->r_offset
);
2653 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2654 reloc_offset
, relname
, reloc_offset
, /*sym->st_value+*/ addend
);
2657 error("unsupported m68k relocation (%d)", type
);
2662 #elif defined(HOST_HPPA)
2668 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2669 if (rel
->r_offset
>= start_offset
&&
2670 rel
->r_offset
< start_offset
+ copy_size
) {
2671 sym_name
= get_rel_sym_name(rel
);
2672 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2673 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2674 type
= ELF32_R_TYPE(rel
->r_info
);
2675 addend
= rel
->r_addend
;
2676 reloc_offset
= rel
->r_offset
- start_offset
;
2680 case R_PARISC_PCREL17F
:
2682 " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2683 reloc_offset
, type
, relname
, addend
);
2686 error("unsupported hppa label relocation (%d)", type
);
2690 case R_PARISC_DIR21L
:
2692 " hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2693 reloc_offset
, relname
, addend
);
2695 case R_PARISC_DIR14R
:
2697 " hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2698 reloc_offset
, relname
, addend
);
2700 case R_PARISC_PCREL17F
:
2701 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2703 " hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2704 reloc_offset
, relname
, addend
);
2707 " HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2708 reloc_offset
, relname
);
2711 case R_PARISC_DPREL21L
:
2712 if (strstart(sym_name
, "__op_param", &p
))
2714 " hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2715 reloc_offset
, p
, addend
);
2718 " hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2719 reloc_offset
, relname
, addend
);
2721 case R_PARISC_DPREL14R
:
2722 if (strstart(sym_name
, "__op_param", &p
))
2724 " hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2725 reloc_offset
, p
, addend
);
2728 " hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2729 reloc_offset
, relname
, addend
);
2732 error("unsupported hppa relocation (%d)", type
);
2738 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2740 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2741 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2747 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2748 /* the compiler leave some unnecessary references to the code */
2749 if (sym_name
[0] == '\0')
2751 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2752 type
= ELF32_R_TYPE(rel
->r_info
);
2753 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2754 reloc_offset
= rel
->r_offset
- start_offset
;
2757 fprintf(outfile
, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2758 rel
->r_offset
, sym_name
);
2760 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2761 "(0x%x & ~0x3fffff) "
2762 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2764 reloc_offset
, addend
, addend
, relname
, reloc_offset
);
2767 fprintf(outfile
, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2768 rel
->r_offset
, sym_name
);
2770 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2771 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2773 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2774 reloc_offset
, reloc_offset
, relname
);
2777 fprintf(outfile
, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2778 rel
->r_offset
, sym_name
);
2780 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2781 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2783 " | (%s & 0xffff);\n",
2784 reloc_offset
, reloc_offset
, relname
);
2787 fprintf(outfile
, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2788 rel
->r_offset
, sym_name
);
2790 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2792 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2794 reloc_offset
, addend
, addend
, relname
, reloc_offset
);
2798 fprintf(outfile
, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2799 rel
->r_offset
, sym_name
);
2801 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2802 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2804 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2805 reloc_offset
, reloc_offset
, relname
);
2808 error("unsupported MIPS relocation (%d)", type
);
2814 #error unsupported CPU
2816 fprintf(outfile
, " gen_code_ptr += %d;\n", copy_size
);
2817 fprintf(outfile
, "}\n");
2818 fprintf(outfile
, "break;\n\n");
2820 fprintf(outfile
, "static inline void gen_%s(", name
);
2822 fprintf(outfile
, "void");
2824 for(i
= 0; i
< nb_args
; i
++) {
2826 fprintf(outfile
, ", ");
2827 fprintf(outfile
, "long param%d", i
+ 1);
2830 fprintf(outfile
, ")\n");
2831 fprintf(outfile
, "{\n");
2832 for(i
= 0; i
< nb_args
; i
++) {
2833 fprintf(outfile
, " *gen_opparam_ptr++ = param%d;\n", i
+ 1);
2835 fprintf(outfile
, " *gen_opc_ptr++ = INDEX_%s;\n", name
);
2836 fprintf(outfile
, "}\n\n");
2840 int gen_file(FILE *outfile
, int out_type
)
2845 if (out_type
== OUT_INDEX_OP
) {
2846 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2848 name
= get_sym_name(sym
);
2849 if (strstart(name
, OP_PREFIX
, NULL
)) {
2850 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 2);
2853 } else if (out_type
== OUT_GEN_OP
) {
2854 /* generate gen_xxx functions */
2855 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2857 name
= get_sym_name(sym
);
2858 if (strstart(name
, OP_PREFIX
, NULL
)) {
2859 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2860 if (sym
->st_shndx
!= text_shndx
)
2861 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2863 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 0);
2868 /* generate big code generation switch */
2872 /* We need to know the size of all the ops so we can figure out when
2873 to emit constant pools. This must be consistent with opc.h. */
2875 "static const uint32_t arm_opc_size[] = {\n"
2880 " 0,\n"); /* nop3 */
2881 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2883 name
= get_sym_name(sym
);
2884 if (strstart(name
, OP_PREFIX
, NULL
)) {
2885 fprintf(outfile
, " %d,\n", sym
->st_size
);
2894 /* Arm is tricky because it uses constant pools for loading immediate values.
2895 We assume (and require) each function is code followed by a constant pool.
2896 All the ops are small so this should be ok. For each op we figure
2897 out how much "spare" range we have in the load instructions. This allows
2898 us to insert subsequent ops in between the op and the constant pool,
2899 eliminating the neeed to jump around the pool.
2901 We currently generate:
2903 [ For this example we assume merging would move op1_pool out of range.
2904 In practice we should be able to combine many ops before the offset
2905 limits are reached. ]
2916 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2919 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2920 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2921 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2922 /* Initialise the parmissible pool offset to an arbitary large value. */
2923 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2928 long addend
, not_first
= 0;
2929 unsigned long sym_idx
;
2930 int index
, max_index
;
2931 const char *sym_name
;
2935 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2936 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2937 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2938 if (strstart(sym_name
, "__op_gen_label", NULL
))
2940 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2943 addend
= rel
->r_addend
;
2944 index
= get_plt_index(sym_name
, addend
);
2945 if (index
<= max_index
)
2948 fprintf(outfile
, " extern void %s(void);\n", sym_name
);
2952 " struct ia64_fixup *plt_fixes = NULL, "
2953 "*ltoff_fixes = NULL;\n"
2954 " static long plt_target[] = {\n\t");
2957 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2958 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2959 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2960 if (strstart(sym_name
, "__op_gen_label", NULL
))
2962 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2965 addend
= rel
->r_addend
;
2966 index
= get_plt_index(sym_name
, addend
);
2967 if (index
<= max_index
)
2972 fprintf(outfile
, ",\n\t");
2975 fprintf(outfile
, "(long) &%s + %ld", sym_name
, addend
);
2977 fprintf(outfile
, "(long) &%s", sym_name
);
2979 fprintf(outfile
, "\n };\n"
2980 " unsigned int plt_offset[%u] = { 0 };\n", max_index
+ 1);
2986 /* Generate constant pool if needed */
2988 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2989 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2990 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2991 " last_gen_code_ptr = gen_code_ptr;\n"
2992 " arm_ldr_ptr = arm_ldr_table;\n"
2993 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2994 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2998 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
3000 name
= get_sym_name(sym
);
3001 if (strstart(name
, OP_PREFIX
, NULL
)) {
3003 printf("%4d: %s pos=0x%08x len=%d\n",
3004 i
, name
, sym
->st_value
, sym
->st_size
);
3006 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
3007 if (sym
->st_shndx
!= text_shndx
)
3008 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
3010 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 1);
3020 printf("dyngen (c) 2003 Fabrice Bellard\n"
3021 "usage: dyngen [-o outfile] [-c] objfile\n"
3022 "Generate a dynamic code generator from an object file\n"
3023 "-c output enum of operations\n"
3024 "-g output gen_op_xx() functions\n"
3029 int main(int argc
, char **argv
)
3032 const char *filename
, *outfilename
;
3035 outfilename
= "out.c";
3036 out_type
= OUT_CODE
;
3038 c
= getopt(argc
, argv
, "ho:cg");
3046 outfilename
= optarg
;
3049 out_type
= OUT_INDEX_OP
;
3052 out_type
= OUT_GEN_OP
;
3058 filename
= argv
[optind
];
3059 outfile
= fopen(outfilename
, "w");
3061 error("could not open '%s'", outfilename
);
3063 load_object(filename
);
3064 gen_file(outfile
, out_type
);