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) {
1762 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, copy_size
);
1763 } else if (gen_switch
== 1) {
1766 fprintf(outfile
, "case INDEX_%s: {\n", name
);
1768 fprintf(outfile
, " long ");
1769 for(i
= 0; i
< nb_args
; i
++) {
1771 fprintf(outfile
, ", ");
1772 fprintf(outfile
, "param%d", i
+ 1);
1774 fprintf(outfile
, ";\n");
1776 #if defined(HOST_IA64)
1777 fprintf(outfile
, " extern char %s;\n", name
);
1779 fprintf(outfile
, " extern void %s();\n", name
);
1782 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1783 host_ulong offset
= get_rel_offset(rel
);
1784 if (offset
>= start_offset
&&
1785 offset
< start_offset
+ (p_end
- p_start
)) {
1786 sym_name
= get_rel_sym_name(rel
);
1790 !strstart(sym_name
, "__op_param", NULL
) &&
1791 !strstart(sym_name
, "__op_jmp", NULL
) &&
1792 !strstart(sym_name
, "__op_gen_label", NULL
)) {
1793 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1794 if (sym_name
[0] == '.') {
1796 "extern char __dot_%s __asm__(\"%s\");\n",
1797 sym_name
+1, sym_name
);
1801 #if defined(__APPLE__)
1802 /* Set __attribute((unused)) on darwin because we
1803 want to avoid warning when we don't use the symbol. */
1804 fprintf(outfile
, " extern char %s __attribute__((unused));\n", sym_name
);
1805 #elif defined(HOST_IA64)
1806 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
1808 * PCREL21 br.call targets generally
1809 * are out of range and need to go
1810 * through an "import stub".
1812 fprintf(outfile
, " extern char %s;\n",
1815 fprintf(outfile
, "extern char %s;\n", sym_name
);
1822 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1823 name
, (int)(start_offset
- offset
), copy_size
);
1825 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1826 name
, (int)(start_offset
- offset
), copy_size
);
1829 /* emit code offset information */
1832 const char *sym_name
, *p
;
1836 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
1837 sym_name
= get_sym_name(sym
);
1838 if (strstart(sym_name
, "__op_label", &p
)) {
1840 unsigned long offset
;
1842 /* test if the variable refers to a label inside
1843 the code we are generating */
1844 #ifdef CONFIG_FORMAT_COFF
1845 if (sym
->st_shndx
== text_shndx
) {
1846 ptr
= sdata
[coff_text_shndx
];
1847 } else if (sym
->st_shndx
== data_shndx
) {
1848 ptr
= sdata
[coff_data_shndx
];
1852 #elif defined(CONFIG_FORMAT_MACH)
1855 ptr
= sdata
[sym
->n_sect
-1];
1857 ptr
= sdata
[sym
->st_shndx
];
1860 error("__op_labelN in invalid section");
1861 offset
= sym
->st_value
;
1862 #ifdef CONFIG_FORMAT_MACH
1863 offset
-= section_hdr
[sym
->n_sect
-1].addr
;
1865 val
= *(host_ulong
*)(ptr
+ offset
);
1866 #ifdef ELF_USES_RELOCA
1868 int reloc_shndx
, nb_relocs1
, j
;
1870 /* try to find a matching relocation */
1871 reloc_shndx
= find_reloc(sym
->st_shndx
);
1873 nb_relocs1
= shdr
[reloc_shndx
].sh_size
/
1874 shdr
[reloc_shndx
].sh_entsize
;
1875 rel
= (ELF_RELOC
*)sdata
[reloc_shndx
];
1876 for(j
= 0; j
< nb_relocs1
; j
++) {
1877 if (rel
->r_offset
== offset
) {
1878 val
= rel
->r_addend
;
1886 if (val
>= start_offset
&& val
<= start_offset
+ copy_size
) {
1887 n
= strtol(p
, NULL
, 10);
1888 fprintf(outfile
, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n
, (long)(val
- start_offset
));
1894 /* load parameters in variables */
1895 for(i
= 0; i
< nb_args
; i
++) {
1896 fprintf(outfile
, " param%d = *opparam_ptr++;\n", i
+ 1);
1899 /* patch relocations */
1900 #if defined(HOST_I386)
1906 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1907 if (rel
->r_offset
>= start_offset
&&
1908 rel
->r_offset
< start_offset
+ copy_size
) {
1909 sym_name
= get_rel_sym_name(rel
);
1912 reloc_offset
= rel
->r_offset
- start_offset
;
1913 if (strstart(sym_name
, "__op_jmp", &p
)) {
1915 n
= strtol(p
, NULL
, 10);
1916 /* __op_jmp relocations are done at
1917 runtime to do translated block
1918 chaining: the offset of the instruction
1919 needs to be stored */
1920 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1925 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1926 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
1927 #ifdef CONFIG_FORMAT_ELF
1928 type
= ELF32_R_TYPE(rel
->r_info
);
1933 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1934 reloc_offset
, type
, relname
, addend
);
1937 error("unsupported i386 relocation (%d)", type
);
1942 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1943 reloc_offset
, relname
, addend
);
1946 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1947 reloc_offset
, relname
, reloc_offset
, addend
);
1950 error("unsupported i386 relocation (%d)", type
);
1953 #elif defined(CONFIG_FORMAT_COFF)
1958 temp_name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
1959 if (!strcmp(temp_name
, ".data")) {
1960 for (j
= 0, sym
= symtab
; j
< nb_syms
; j
++, sym
++) {
1961 if (strstart(sym
->st_name
, sym_name
, NULL
)) {
1962 addend
-= sym
->st_value
;
1969 /* TCG uses elf relocation constants */
1971 #define R_386_PC32 2
1980 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1981 reloc_offset
, type
, relname
, addend
);
1984 error("unsupported i386 relocation (%d)", type
);
1989 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1990 reloc_offset
, relname
, addend
);
1993 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1994 reloc_offset
, relname
, reloc_offset
, addend
);
1997 error("unsupported i386 relocation (%d)", type
);
2001 #error unsupport object format
2006 #elif defined(HOST_X86_64)
2012 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2013 if (rel
->r_offset
>= start_offset
&&
2014 rel
->r_offset
< start_offset
+ copy_size
) {
2015 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2016 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2017 type
= ELF32_R_TYPE(rel
->r_info
);
2018 addend
= rel
->r_addend
;
2019 reloc_offset
= rel
->r_offset
- start_offset
;
2025 fprintf(outfile
, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2026 reloc_offset
, type
, relname
, addend
);
2029 error("unsupported X86_64 relocation (%d)", type
);
2034 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2035 reloc_offset
, relname
, addend
);
2038 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2039 reloc_offset
, relname
, addend
);
2042 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2043 reloc_offset
, relname
, reloc_offset
, addend
);
2046 error("unsupported X86_64 relocation (%d)", type
);
2052 #elif defined(HOST_PPC)
2054 #ifdef CONFIG_FORMAT_ELF
2059 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2060 if (rel
->r_offset
>= start_offset
&&
2061 rel
->r_offset
< start_offset
+ copy_size
) {
2062 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2063 reloc_offset
= rel
->r_offset
- start_offset
;
2064 if (strstart(sym_name
, "__op_jmp", &p
)) {
2066 n
= strtol(p
, NULL
, 10);
2067 /* __op_jmp relocations are done at
2068 runtime to do translated block
2069 chaining: the offset of the instruction
2070 needs to be stored */
2071 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2076 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2077 type
= ELF32_R_TYPE(rel
->r_info
);
2078 addend
= rel
->r_addend
;
2081 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2082 reloc_offset
, relname
, addend
);
2084 case R_PPC_ADDR16_LO
:
2085 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2086 reloc_offset
, relname
, addend
);
2088 case R_PPC_ADDR16_HI
:
2089 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2090 reloc_offset
, relname
, addend
);
2092 case R_PPC_ADDR16_HA
:
2093 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2094 reloc_offset
, relname
, addend
);
2097 /* warning: must be at 32 MB distancy */
2098 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2099 reloc_offset
, reloc_offset
, relname
, reloc_offset
, addend
);
2102 error("unsupported powerpc relocation (%d)", type
);
2106 #elif defined(CONFIG_FORMAT_MACH)
2107 struct scattered_relocation_info
*scarel
;
2108 struct relocation_info
* rel
;
2109 char final_sym_name
[256];
2110 const char *sym_name
;
2115 for(i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2116 unsigned int offset
, length
, value
= 0;
2117 unsigned int type
, pcrel
, isym
= 0;
2118 unsigned int usesym
= 0;
2120 if(R_SCATTERED
& rel
->r_address
) {
2121 scarel
= (struct scattered_relocation_info
*)rel
;
2122 offset
= (unsigned int)scarel
->r_address
;
2123 length
= scarel
->r_length
;
2124 pcrel
= scarel
->r_pcrel
;
2125 type
= scarel
->r_type
;
2126 value
= scarel
->r_value
;
2128 value
= isym
= rel
->r_symbolnum
;
2129 usesym
= (rel
->r_extern
);
2130 offset
= rel
->r_address
;
2131 length
= rel
->r_length
;
2132 pcrel
= rel
->r_pcrel
;
2136 slide
= offset
- start_offset
;
2138 if (!(offset
>= start_offset
&& offset
< start_offset
+ size
))
2139 continue; /* not in our range */
2141 sym_name
= get_reloc_name(rel
, &sslide
);
2143 if(usesym
&& symtab
[isym
].n_type
& N_STAB
)
2144 continue; /* don't handle STAB (debug sym) */
2146 if (sym_name
&& strstart(sym_name
, "__op_jmp", &p
)) {
2148 n
= strtol(p
, NULL
, 10);
2149 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2151 continue; /* Nothing more to do */
2155 fprintf(outfile
, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2156 name
, value
, usesym
? "use sym" : "don't use sym", offset
, length
, pcrel
? "pcrel":"", type
);
2157 continue; /* dunno how to handle without final_sym_name */
2160 get_reloc_expr(final_sym_name
, sizeof(final_sym_name
),
2163 case PPC_RELOC_BR24
:
2164 if (!strstart(sym_name
,"__op_gen_label",&p
)) {
2165 fprintf(outfile
, "{\n");
2166 fprintf(outfile
, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide
);
2167 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",
2168 slide
, slide
, name
, sslide
);
2169 fprintf(outfile
, "}\n");
2171 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2172 slide
, slide
, final_sym_name
, slide
);
2175 case PPC_RELOC_HI16
:
2176 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2177 slide
, final_sym_name
, sslide
);
2179 case PPC_RELOC_LO16
:
2180 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2181 slide
, final_sym_name
, sslide
);
2183 case PPC_RELOC_HA16
:
2184 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2185 slide
, final_sym_name
, sslide
);
2188 error("unsupported powerpc relocation (%d)", type
);
2192 #error unsupport object format
2195 #elif defined(HOST_S390)
2201 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2202 if (rel
->r_offset
>= start_offset
&&
2203 rel
->r_offset
< start_offset
+ copy_size
) {
2204 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2205 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2206 type
= ELF32_R_TYPE(rel
->r_info
);
2207 addend
= rel
->r_addend
;
2208 reloc_offset
= rel
->r_offset
- start_offset
;
2211 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2212 reloc_offset
, relname
, addend
);
2215 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2216 reloc_offset
, relname
, addend
);
2219 fprintf(outfile
, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2220 reloc_offset
, relname
, addend
);
2223 if (ELF32_ST_TYPE(symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_info
) == STT_SECTION
) {
2225 " *(uint32_t *)(gen_code_ptr + %d) += "
2226 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2227 reloc_offset
, name
);
2231 " *(uint32_t *)(gen_code_ptr + %d) = "
2232 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2233 reloc_offset
, relname
, addend
, reloc_offset
);
2236 error("unsupported s390 relocation (%d)", type
);
2241 #elif defined(HOST_ALPHA)
2243 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2244 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2248 type
= ELF64_R_TYPE(rel
->r_info
);
2249 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2250 reloc_offset
= rel
->r_offset
- start_offset
;
2252 case R_ALPHA_GPDISP
:
2253 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2254 as an immediate instead of constructing it from the pv or ra. */
2255 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2257 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2258 reloc_offset
+ (int)rel
->r_addend
);
2260 case R_ALPHA_LITUSE
:
2261 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2262 now, since some called functions (libc) need pv to be set up. */
2265 /* Branch target prediction hint. Ignore for now. Should be already
2266 correct for in-function jumps. */
2268 case R_ALPHA_LITERAL
:
2269 /* Load a literal from the GOT relative to the gp. Since there's only a
2270 single gp, nothing is to be done. */
2272 case R_ALPHA_GPRELHIGH
:
2273 /* Handle fake relocations against __op_param symbol. Need to emit the
2274 high part of the immediate value instead. Other symbols need no
2275 special treatment. */
2276 if (strstart(sym_name
, "__op_param", &p
))
2277 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2280 case R_ALPHA_GPRELLOW
:
2281 if (strstart(sym_name
, "__op_param", &p
))
2282 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2286 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2287 set up the gp from the pv. */
2288 fprintf(outfile
, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2289 reloc_offset
, sym_name
, reloc_offset
);
2292 error("unsupported Alpha relocation (%d)", type
);
2297 #elif defined(HOST_IA64)
2299 unsigned long sym_idx
;
2305 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2306 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2307 if (rel
->r_offset
< start_offset
2308 || rel
->r_offset
>= start_offset
+ copy_size
)
2310 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2311 code_offset
= rel
->r_offset
- start_offset
;
2312 if (strstart(sym_name
, "__op_jmp", &p
)) {
2314 n
= strtol(p
, NULL
, 10);
2315 /* __op_jmp relocations are done at
2316 runtime to do translated block
2317 chaining: the offset of the instruction
2318 needs to be stored */
2319 fprintf(outfile
, " jmp_offsets[%d] ="
2320 "%ld + (gen_code_ptr - gen_code_buf);\n",
2324 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2325 type
= ELF64_R_TYPE(rel
->r_info
);
2326 addend
= rel
->r_addend
;
2330 " ia64_imm64(gen_code_ptr + %ld, "
2332 code_offset
, relname
, addend
);
2334 case R_IA64_LTOFF22X
:
2335 case R_IA64_LTOFF22
:
2336 fprintf(outfile
, " IA64_LTOFF(gen_code_ptr + %ld,"
2337 " %s + %ld, %d);\n",
2338 code_offset
, relname
, addend
,
2339 (type
== R_IA64_LTOFF22X
));
2343 " ia64_ldxmov(gen_code_ptr + %ld,"
2344 " %s + %ld);\n", code_offset
, relname
, addend
);
2347 case R_IA64_PCREL21B
:
2348 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2350 " ia64_imm21b(gen_code_ptr + %ld,"
2351 " (long) (%s + %ld -\n\t\t"
2352 "((long) gen_code_ptr + %ld)) >> 4);\n",
2353 code_offset
, relname
, addend
,
2354 code_offset
& ~0xfUL
);
2357 " IA64_PLT(gen_code_ptr + %ld, "
2358 "%d);\t/* %s + %ld */\n",
2360 get_plt_index(sym_name
, addend
),
2365 error("unsupported ia64 relocation (0x%x)",
2369 fprintf(outfile
, " ia64_nop_b(gen_code_ptr + %d);\n",
2370 copy_size
- 16 + 2);
2372 #elif defined(HOST_SPARC)
2378 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2379 if (rel
->r_offset
>= start_offset
&&
2380 rel
->r_offset
< start_offset
+ copy_size
) {
2381 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2382 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2383 type
= ELF32_R_TYPE(rel
->r_info
);
2384 addend
= rel
->r_addend
;
2385 reloc_offset
= rel
->r_offset
- start_offset
;
2388 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2389 reloc_offset
, relname
, addend
);
2393 " *(uint32_t *)(gen_code_ptr + %d) = "
2394 "((*(uint32_t *)(gen_code_ptr + %d)) "
2396 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2397 reloc_offset
, reloc_offset
, relname
, addend
);
2401 " *(uint32_t *)(gen_code_ptr + %d) = "
2402 "((*(uint32_t *)(gen_code_ptr + %d)) "
2404 " | ((%s + %d) & 0x3ff);\n",
2405 reloc_offset
, reloc_offset
, relname
, addend
);
2407 case R_SPARC_WDISP30
:
2409 " *(uint32_t *)(gen_code_ptr + %d) = "
2410 "((*(uint32_t *)(gen_code_ptr + %d)) "
2412 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2413 " & 0x3fffffff);\n",
2414 reloc_offset
, reloc_offset
, relname
, addend
,
2417 case R_SPARC_WDISP22
:
2419 " *(uint32_t *)(gen_code_ptr + %d) = "
2420 "((*(uint32_t *)(gen_code_ptr + %d)) "
2422 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2424 rel
->r_offset
- start_offset
,
2425 rel
->r_offset
- start_offset
,
2427 rel
->r_offset
- start_offset
);
2430 error("unsupported sparc relocation (%d)", type
);
2435 #elif defined(HOST_SPARC64)
2441 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2442 if (rel
->r_offset
>= start_offset
&&
2443 rel
->r_offset
< start_offset
+ copy_size
) {
2444 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2445 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2446 type
= ELF32_R_TYPE(rel
->r_info
);
2447 addend
= rel
->r_addend
;
2448 reloc_offset
= rel
->r_offset
- start_offset
;
2451 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2452 reloc_offset
, relname
, addend
);
2456 " *(uint32_t *)(gen_code_ptr + %d) = "
2457 "((*(uint32_t *)(gen_code_ptr + %d)) "
2459 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2460 reloc_offset
, reloc_offset
, relname
, addend
);
2464 " *(uint32_t *)(gen_code_ptr + %d) = "
2465 "((*(uint32_t *)(gen_code_ptr + %d)) "
2467 " | ((%s + %d) & 0x3ff);\n",
2468 reloc_offset
, reloc_offset
, relname
, addend
);
2471 addend
+= ELF64_R_TYPE_DATA (rel
->r_info
);
2473 " *(uint32_t *)(gen_code_ptr + %d) = "
2474 "((*(uint32_t *)(gen_code_ptr + %d)) "
2476 " | ((%s + %d) & 0x3ff);\n",
2477 reloc_offset
, reloc_offset
, relname
, addend
);
2479 case R_SPARC_WDISP30
:
2481 " *(uint32_t *)(gen_code_ptr + %d) = "
2482 "((*(uint32_t *)(gen_code_ptr + %d)) "
2484 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2485 " & 0x3fffffff);\n",
2486 reloc_offset
, reloc_offset
, relname
, addend
,
2489 case R_SPARC_WDISP22
:
2491 " *(uint32_t *)(gen_code_ptr + %d) = "
2492 "((*(uint32_t *)(gen_code_ptr + %d)) "
2494 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2496 reloc_offset
, reloc_offset
, relname
, addend
,
2501 " *(uint32_t *)(gen_code_ptr + %d) = "
2502 "((*(uint32_t *)(gen_code_ptr + %d)) "
2504 " | (((%s + %d) >> 42) & 0x00000000);\n",
2505 reloc_offset
, reloc_offset
, relname
, addend
);
2510 " *(uint32_t *)(gen_code_ptr + %d) = "
2511 "((*(uint32_t *)(gen_code_ptr + %d)) "
2513 " | (((%s + %d) >> 10) & 0x00000000);\n",
2514 reloc_offset
, reloc_offset
, relname
, addend
);
2519 " *(uint32_t *)(gen_code_ptr + %d) = "
2520 "((*(uint32_t *)(gen_code_ptr + %d)) "
2522 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2523 reloc_offset
, reloc_offset
, relname
, addend
);
2527 error("unsupported sparc64 relocation (%d) for symbol %s", type
, relname
);
2532 #elif defined(HOST_ARM)
2540 insn
= get32((uint32_t *)(p_start
+ 4));
2541 /* If prologue ends in sub sp, sp, #const then assume
2542 op has a stack frame and needs the frame pointer. */
2543 if ((insn
& 0xffffff00) == 0xe24dd000) {
2546 opcode
= 0xe28db000; /* add fp, sp, #0. */
2548 /* ??? Need to undo the extra stack adjustment at the end of the op.
2549 For now just leave the stack misaligned and hope it doesn't break anything
2551 if ((insn
& 4) != 0) {
2552 /* Preserve doubleword stack alignment. */
2554 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2559 insn
= get32((uint32_t *)(p_start
- 4));
2560 /* Calculate the size of the saved registers,
2562 for (i
= 0; i
< 15; i
++) {
2563 if (insn
& (1 << i
))
2567 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode
);
2569 arm_emit_ldr_info(relname
, start_offset
, outfile
, p_start
, p_end
,
2572 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2573 if (rel
->r_offset
>= start_offset
&&
2574 rel
->r_offset
< start_offset
+ copy_size
) {
2575 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2576 /* the compiler leave some unnecessary references to the code */
2577 if (sym_name
[0] == '\0')
2579 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2580 type
= ELF32_R_TYPE(rel
->r_info
);
2581 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2582 reloc_offset
= rel
->r_offset
- start_offset
;
2585 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2586 reloc_offset
, relname
, addend
);
2591 fprintf(outfile
, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2592 reloc_offset
, addend
, relname
);
2595 error("unsupported arm relocation (%d)", type
);
2600 #elif defined(HOST_M68K)
2607 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2608 if (rel
->r_offset
>= start_offset
&&
2609 rel
->r_offset
< start_offset
+ copy_size
) {
2610 sym
= &(symtab
[ELFW(R_SYM
)(rel
->r_info
)]);
2611 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2612 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2613 type
= ELF32_R_TYPE(rel
->r_info
);
2614 addend
= get32((uint32_t *)(text
+ rel
->r_offset
)) + rel
->r_addend
;
2615 reloc_offset
= rel
->r_offset
- start_offset
;
2618 fprintf(outfile
, " /* R_68K_32 RELOC, offset %x */\n", rel
->r_offset
) ;
2619 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2620 reloc_offset
, relname
, addend
);
2623 fprintf(outfile
, " /* R_68K_PC32 RELOC, offset %x */\n", rel
->r_offset
);
2624 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2625 reloc_offset
, relname
, reloc_offset
, /*sym->st_value+*/ addend
);
2628 error("unsupported m68k relocation (%d)", type
);
2633 #elif defined(HOST_HPPA)
2639 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2640 if (rel
->r_offset
>= start_offset
&&
2641 rel
->r_offset
< start_offset
+ copy_size
) {
2642 sym_name
= get_rel_sym_name(rel
);
2643 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2644 is_label
= get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2645 type
= ELF32_R_TYPE(rel
->r_info
);
2646 addend
= rel
->r_addend
;
2647 reloc_offset
= rel
->r_offset
- start_offset
;
2651 case R_PARISC_PCREL17F
:
2653 " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2654 reloc_offset
, type
, relname
, addend
);
2657 error("unsupported hppa label relocation (%d)", type
);
2661 case R_PARISC_DIR21L
:
2663 " hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2664 reloc_offset
, relname
, addend
);
2666 case R_PARISC_DIR14R
:
2668 " hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2669 reloc_offset
, relname
, addend
);
2671 case R_PARISC_PCREL17F
:
2672 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2674 " hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2675 reloc_offset
, relname
, addend
);
2678 " HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2679 reloc_offset
, relname
);
2682 case R_PARISC_DPREL21L
:
2683 if (strstart(sym_name
, "__op_param", &p
))
2685 " hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2686 reloc_offset
, p
, addend
);
2689 " hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2690 reloc_offset
, relname
, addend
);
2692 case R_PARISC_DPREL14R
:
2693 if (strstart(sym_name
, "__op_param", &p
))
2695 " hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2696 reloc_offset
, p
, addend
);
2699 " hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2700 reloc_offset
, relname
, addend
);
2703 error("unsupported hppa relocation (%d)", type
);
2709 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2711 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2712 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2718 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2719 /* the compiler leave some unnecessary references to the code */
2720 if (sym_name
[0] == '\0')
2722 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
2723 type
= ELF32_R_TYPE(rel
->r_info
);
2724 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2725 reloc_offset
= rel
->r_offset
- start_offset
;
2728 fprintf(outfile
, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2729 rel
->r_offset
, sym_name
);
2731 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2732 "(0x%x & ~0x3fffff) "
2733 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2735 reloc_offset
, addend
, addend
, relname
, reloc_offset
);
2738 fprintf(outfile
, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2739 rel
->r_offset
, sym_name
);
2741 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2742 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2744 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2745 reloc_offset
, reloc_offset
, relname
);
2748 fprintf(outfile
, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2749 rel
->r_offset
, sym_name
);
2751 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2752 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2754 " | (%s & 0xffff);\n",
2755 reloc_offset
, reloc_offset
, relname
);
2758 fprintf(outfile
, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2759 rel
->r_offset
, sym_name
);
2761 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2763 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2765 reloc_offset
, addend
, addend
, relname
, reloc_offset
);
2769 fprintf(outfile
, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2770 rel
->r_offset
, sym_name
);
2772 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2773 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2775 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2776 reloc_offset
, reloc_offset
, relname
);
2779 error("unsupported MIPS relocation (%d)", type
);
2785 #error unsupported CPU
2787 fprintf(outfile
, " gen_code_ptr += %d;\n", copy_size
);
2788 fprintf(outfile
, "}\n");
2789 fprintf(outfile
, "break;\n\n");
2791 fprintf(outfile
, "static inline void gen_%s(", name
);
2793 fprintf(outfile
, "void");
2795 for(i
= 0; i
< nb_args
; i
++) {
2797 fprintf(outfile
, ", ");
2798 fprintf(outfile
, "long param%d", i
+ 1);
2801 fprintf(outfile
, ")\n");
2802 fprintf(outfile
, "{\n");
2803 for(i
= 0; i
< nb_args
; i
++) {
2804 fprintf(outfile
, " *gen_opparam_ptr++ = param%d;\n", i
+ 1);
2806 fprintf(outfile
, " *gen_opc_ptr++ = INDEX_%s;\n", name
);
2807 fprintf(outfile
, "}\n\n");
2811 int gen_file(FILE *outfile
, int out_type
)
2816 if (out_type
== OUT_INDEX_OP
) {
2817 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2819 name
= get_sym_name(sym
);
2820 if (strstart(name
, OP_PREFIX
, NULL
)) {
2821 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 2);
2824 } else if (out_type
== OUT_GEN_OP
) {
2825 /* generate gen_xxx functions */
2826 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2828 name
= get_sym_name(sym
);
2829 if (strstart(name
, OP_PREFIX
, NULL
)) {
2830 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2831 if (sym
->st_shndx
!= text_shndx
)
2832 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2834 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 0);
2839 /* generate big code generation switch */
2843 /* We need to know the size of all the ops so we can figure out when
2844 to emit constant pools. This must be consistent with opc.h. */
2846 "static const uint32_t arm_opc_size[] = {\n"
2851 " 0,\n"); /* nop3 */
2852 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2854 name
= get_sym_name(sym
);
2855 if (strstart(name
, OP_PREFIX
, NULL
)) {
2856 fprintf(outfile
, " %d,\n", sym
->st_size
);
2865 /* Arm is tricky because it uses constant pools for loading immediate values.
2866 We assume (and require) each function is code followed by a constant pool.
2867 All the ops are small so this should be ok. For each op we figure
2868 out how much "spare" range we have in the load instructions. This allows
2869 us to insert subsequent ops in between the op and the constant pool,
2870 eliminating the neeed to jump around the pool.
2872 We currently generate:
2874 [ For this example we assume merging would move op1_pool out of range.
2875 In practice we should be able to combine many ops before the offset
2876 limits are reached. ]
2887 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2890 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2891 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2892 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2893 /* Initialise the parmissible pool offset to an arbitary large value. */
2894 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2898 long addend
, not_first
= 0;
2899 unsigned long sym_idx
;
2900 int index
, max_index
;
2901 const char *sym_name
;
2905 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2906 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2907 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2908 if (strstart(sym_name
, "__op_gen_label", NULL
))
2910 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2913 addend
= rel
->r_addend
;
2914 index
= get_plt_index(sym_name
, addend
);
2915 if (index
<= max_index
)
2918 fprintf(outfile
, " extern void %s(void);\n", sym_name
);
2922 " struct ia64_fixup *plt_fixes = NULL, "
2923 "*ltoff_fixes = NULL;\n"
2924 " static long plt_target[] = {\n\t");
2927 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2928 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2929 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2930 if (strstart(sym_name
, "__op_gen_label", NULL
))
2932 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2935 addend
= rel
->r_addend
;
2936 index
= get_plt_index(sym_name
, addend
);
2937 if (index
<= max_index
)
2942 fprintf(outfile
, ",\n\t");
2945 fprintf(outfile
, "(long) &%s + %ld", sym_name
, addend
);
2947 fprintf(outfile
, "(long) &%s", sym_name
);
2949 fprintf(outfile
, "\n };\n"
2950 " unsigned int plt_offset[%u] = { 0 };\n", max_index
+ 1);
2956 /* Generate constant pool if needed */
2958 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2959 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2960 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2961 " last_gen_code_ptr = gen_code_ptr;\n"
2962 " arm_ldr_ptr = arm_ldr_table;\n"
2963 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2964 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2968 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2970 name
= get_sym_name(sym
);
2971 if (strstart(name
, OP_PREFIX
, NULL
)) {
2973 printf("%4d: %s pos=0x%08x len=%d\n",
2974 i
, name
, sym
->st_value
, sym
->st_size
);
2976 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2977 if (sym
->st_shndx
!= text_shndx
)
2978 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2980 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 1);
2990 printf("dyngen (c) 2003 Fabrice Bellard\n"
2991 "usage: dyngen [-o outfile] [-c] objfile\n"
2992 "Generate a dynamic code generator from an object file\n"
2993 "-c output enum of operations\n"
2994 "-g output gen_op_xx() functions\n"
2999 int main(int argc
, char **argv
)
3002 const char *filename
, *outfilename
;
3005 outfilename
= "out.c";
3006 out_type
= OUT_CODE
;
3008 c
= getopt(argc
, argv
, "ho:cg");
3016 outfilename
= optarg
;
3019 out_type
= OUT_INDEX_OP
;
3022 out_type
= OUT_GEN_OP
;
3028 filename
= argv
[optind
];
3029 outfile
= fopen(outfilename
, "w");
3031 error("could not open '%s'", outfilename
);
3033 load_object(filename
);
3034 gen_file(outfile
, out_type
);