2 * Generic Dynamic compiler generator
4 * Copyright (c) 2003 Fabrice Bellard
6 * The COFF object format support was extracted from Kazu's QEMU port
9 * Mach-O Support by Matt Reda and Pierre d'Herbemont
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 #include "config-host.h"
35 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
37 #if defined(CONFIG_WIN32)
38 #define CONFIG_FORMAT_COFF
39 #elif defined(CONFIG_DARWIN)
40 #define CONFIG_FORMAT_MACH
42 #define CONFIG_FORMAT_ELF
45 #ifdef CONFIG_FORMAT_ELF
47 /* elf format definitions. We use these macros to test the CPU to
48 allow cross compilation (this tool must be ran on the build
50 #if defined(HOST_I386)
52 #define ELF_CLASS ELFCLASS32
53 #define ELF_ARCH EM_386
54 #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
55 #undef ELF_USES_RELOCA
57 #elif defined(HOST_X86_64)
59 #define ELF_CLASS ELFCLASS64
60 #define ELF_ARCH EM_X86_64
61 #define elf_check_arch(x) ((x) == EM_X86_64)
62 #define ELF_USES_RELOCA
64 #elif defined(HOST_PPC)
66 #define ELF_CLASS ELFCLASS32
67 #define ELF_ARCH EM_PPC
68 #define elf_check_arch(x) ((x) == EM_PPC)
69 #define ELF_USES_RELOCA
71 #elif defined(HOST_S390)
73 #define ELF_CLASS ELFCLASS32
74 #define ELF_ARCH EM_S390
75 #define elf_check_arch(x) ((x) == EM_S390)
76 #define ELF_USES_RELOCA
78 #elif defined(HOST_ALPHA)
80 #define ELF_CLASS ELFCLASS64
81 #define ELF_ARCH EM_ALPHA
82 #define elf_check_arch(x) ((x) == EM_ALPHA)
83 #define ELF_USES_RELOCA
85 #elif defined(HOST_IA64)
87 #define ELF_CLASS ELFCLASS64
88 #define ELF_ARCH EM_IA_64
89 #define elf_check_arch(x) ((x) == EM_IA_64)
90 #define ELF_USES_RELOCA
92 #elif defined(HOST_SPARC)
94 #define ELF_CLASS ELFCLASS32
95 #define ELF_ARCH EM_SPARC
96 #define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
97 #define ELF_USES_RELOCA
99 #elif defined(HOST_SPARC64)
101 #define ELF_CLASS ELFCLASS64
102 #define ELF_ARCH EM_SPARCV9
103 #define elf_check_arch(x) ((x) == EM_SPARCV9)
104 #define ELF_USES_RELOCA
106 #elif defined(HOST_ARM)
108 #define ELF_CLASS ELFCLASS32
109 #define ELF_ARCH EM_ARM
110 #define elf_check_arch(x) ((x) == EM_ARM)
111 #define ELF_USES_RELOC
113 #elif defined(HOST_M68K)
115 #define ELF_CLASS ELFCLASS32
116 #define ELF_ARCH EM_68K
117 #define elf_check_arch(x) ((x) == EM_68K)
118 #define ELF_USES_RELOCA
121 #error unsupported CPU - please update the code
126 #if ELF_CLASS == ELFCLASS32
127 typedef int32_t host_long
;
128 typedef uint32_t host_ulong
;
129 #define swabls(x) swab32s(x)
131 typedef int64_t host_long
;
132 typedef uint64_t host_ulong
;
133 #define swabls(x) swab64s(x)
136 #ifdef ELF_USES_RELOCA
137 #define SHT_RELOC SHT_RELA
139 #define SHT_RELOC SHT_REL
142 #define EXE_RELOC ELF_RELOC
143 #define EXE_SYM ElfW(Sym)
145 #endif /* CONFIG_FORMAT_ELF */
147 #ifdef CONFIG_FORMAT_COFF
151 typedef int32_t host_long
;
152 typedef uint32_t host_ulong
;
154 #define FILENAMELEN 256
156 typedef struct coff_sym
{
157 struct external_syment
*st_syment
;
158 char st_name
[FILENAMELEN
];
165 typedef struct coff_rel
{
166 struct external_reloc
*r_reloc
;
171 #define EXE_RELOC struct coff_rel
172 #define EXE_SYM struct coff_sym
174 #endif /* CONFIG_FORMAT_COFF */
176 #ifdef CONFIG_FORMAT_MACH
178 #include <mach-o/loader.h>
179 #include <mach-o/nlist.h>
180 #include <mach-o/reloc.h>
181 #include <mach-o/ppc/reloc.h>
183 # define check_mach_header(x) (x.magic == MH_MAGIC)
184 typedef int32_t host_long
;
185 typedef uint32_t host_ulong
;
187 struct nlist_extended
193 unsigned char n_type
;
194 unsigned char n_sect
;
196 unsigned long st_value
;
197 unsigned long st_size
;
200 #define EXE_RELOC struct relocation_info
201 #define EXE_SYM struct nlist_extended
203 #endif /* CONFIG_FORMAT_MACH */
213 /* all dynamically generated functions begin with this code */
214 #define OP_PREFIX "op_"
218 void __attribute__((noreturn
)) __attribute__((format (printf
, 1, 2))) error(const char *fmt
, ...)
222 fprintf(stderr
, "dyngen: ");
223 vfprintf(stderr
, fmt
, ap
);
224 fprintf(stderr
, "\n");
229 void *load_data(int fd
, long offset
, unsigned int size
)
236 lseek(fd
, offset
, SEEK_SET
);
237 if (read(fd
, data
, size
) != size
) {
244 int strstart(const char *str
, const char *val
, const char **ptr
)
260 void pstrcpy(char *buf
, int buf_size
, const char *str
)
270 if (c
== 0 || q
>= buf
+ buf_size
- 1)
277 void swab16s(uint16_t *p
)
282 void swab32s(uint32_t *p
)
287 void swab64s(uint64_t *p
)
292 uint16_t get16(uint16_t *p
)
301 uint32_t get32(uint32_t *p
)
310 void put16(uint16_t *p
, uint16_t val
)
317 void put32(uint32_t *p
, uint32_t val
)
324 /* executable information */
332 #ifdef CONFIG_FORMAT_ELF
335 struct elf_shdr
*shdr
;
340 int elf_must_swap(struct elfhdr
*h
)
348 return (h
->e_ident
[EI_DATA
] == ELFDATA2MSB
) !=
349 (swaptest
.b
[0] == 0);
352 void elf_swap_ehdr(struct elfhdr
*h
)
354 swab16s(&h
->e_type
); /* Object file type */
355 swab16s(&h
-> e_machine
); /* Architecture */
356 swab32s(&h
-> e_version
); /* Object file version */
357 swabls(&h
-> e_entry
); /* Entry point virtual address */
358 swabls(&h
-> e_phoff
); /* Program header table file offset */
359 swabls(&h
-> e_shoff
); /* Section header table file offset */
360 swab32s(&h
-> e_flags
); /* Processor-specific flags */
361 swab16s(&h
-> e_ehsize
); /* ELF header size in bytes */
362 swab16s(&h
-> e_phentsize
); /* Program header table entry size */
363 swab16s(&h
-> e_phnum
); /* Program header table entry count */
364 swab16s(&h
-> e_shentsize
); /* Section header table entry size */
365 swab16s(&h
-> e_shnum
); /* Section header table entry count */
366 swab16s(&h
-> e_shstrndx
); /* Section header string table index */
369 void elf_swap_shdr(struct elf_shdr
*h
)
371 swab32s(&h
-> sh_name
); /* Section name (string tbl index) */
372 swab32s(&h
-> sh_type
); /* Section type */
373 swabls(&h
-> sh_flags
); /* Section flags */
374 swabls(&h
-> sh_addr
); /* Section virtual addr at execution */
375 swabls(&h
-> sh_offset
); /* Section file offset */
376 swabls(&h
-> sh_size
); /* Section size in bytes */
377 swab32s(&h
-> sh_link
); /* Link to another section */
378 swab32s(&h
-> sh_info
); /* Additional section information */
379 swabls(&h
-> sh_addralign
); /* Section alignment */
380 swabls(&h
-> sh_entsize
); /* Entry size if section holds table */
383 void elf_swap_phdr(struct elf_phdr
*h
)
385 swab32s(&h
->p_type
); /* Segment type */
386 swabls(&h
->p_offset
); /* Segment file offset */
387 swabls(&h
->p_vaddr
); /* Segment virtual address */
388 swabls(&h
->p_paddr
); /* Segment physical address */
389 swabls(&h
->p_filesz
); /* Segment size in file */
390 swabls(&h
->p_memsz
); /* Segment size in memory */
391 swab32s(&h
->p_flags
); /* Segment flags */
392 swabls(&h
->p_align
); /* Segment alignment */
395 void elf_swap_rel(ELF_RELOC
*rel
)
397 swabls(&rel
->r_offset
);
398 swabls(&rel
->r_info
);
399 #ifdef ELF_USES_RELOCA
400 swabls(&rel
->r_addend
);
404 struct elf_shdr
*find_elf_section(struct elf_shdr
*shdr
, int shnum
, const char *shstr
,
409 struct elf_shdr
*sec
;
411 for(i
= 0; i
< shnum
; i
++) {
415 shname
= shstr
+ sec
->sh_name
;
416 if (!strcmp(shname
, name
))
422 int find_reloc(int sh_index
)
424 struct elf_shdr
*sec
;
427 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
429 if (sec
->sh_type
== SHT_RELOC
&& sec
->sh_info
== sh_index
)
435 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
437 return rel
->r_offset
;
440 static char *get_rel_sym_name(EXE_RELOC
*rel
)
442 return strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
445 static char *get_sym_name(EXE_SYM
*sym
)
447 return strtab
+ sym
->st_name
;
450 /* load an elf object file */
451 int load_object(const char *filename
)
454 struct elf_shdr
*sec
, *symtab_sec
, *strtab_sec
, *text_sec
;
460 fd
= open(filename
, O_RDONLY
);
462 error("can't open file '%s'", filename
);
464 /* Read ELF header. */
465 if (read(fd
, &ehdr
, sizeof (ehdr
)) != sizeof (ehdr
))
466 error("unable to read file header");
468 /* Check ELF identification. */
469 if (ehdr
.e_ident
[EI_MAG0
] != ELFMAG0
470 || ehdr
.e_ident
[EI_MAG1
] != ELFMAG1
471 || ehdr
.e_ident
[EI_MAG2
] != ELFMAG2
472 || ehdr
.e_ident
[EI_MAG3
] != ELFMAG3
473 || ehdr
.e_ident
[EI_VERSION
] != EV_CURRENT
) {
474 error("bad ELF header");
477 do_swap
= elf_must_swap(&ehdr
);
479 elf_swap_ehdr(&ehdr
);
480 if (ehdr
.e_ident
[EI_CLASS
] != ELF_CLASS
)
481 error("Unsupported ELF class");
482 if (ehdr
.e_type
!= ET_REL
)
483 error("ELF object file expected");
484 if (ehdr
.e_version
!= EV_CURRENT
)
485 error("Invalid ELF version");
486 if (!elf_check_arch(ehdr
.e_machine
))
487 error("Unsupported CPU (e_machine=%d)", ehdr
.e_machine
);
489 /* read section headers */
490 shdr
= load_data(fd
, ehdr
.e_shoff
, ehdr
.e_shnum
* sizeof(struct elf_shdr
));
492 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
493 elf_swap_shdr(&shdr
[i
]);
497 /* read all section data */
498 sdata
= malloc(sizeof(void *) * ehdr
.e_shnum
);
499 memset(sdata
, 0, sizeof(void *) * ehdr
.e_shnum
);
501 for(i
= 0;i
< ehdr
.e_shnum
; i
++) {
503 if (sec
->sh_type
!= SHT_NOBITS
)
504 sdata
[i
] = load_data(fd
, sec
->sh_offset
, sec
->sh_size
);
507 sec
= &shdr
[ehdr
.e_shstrndx
];
508 shstr
= sdata
[ehdr
.e_shstrndx
];
510 /* swap relocations */
511 for(i
= 0; i
< ehdr
.e_shnum
; i
++) {
513 if (sec
->sh_type
== SHT_RELOC
) {
514 nb_relocs
= sec
->sh_size
/ sec
->sh_entsize
;
516 for(j
= 0, rel
= (ELF_RELOC
*)sdata
[i
]; j
< nb_relocs
; j
++, rel
++)
523 text_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".text");
525 error("could not find .text section");
526 text_shndx
= text_sec
- shdr
;
527 text
= sdata
[text_shndx
];
529 /* find text relocations, if any */
532 i
= find_reloc(text_shndx
);
534 relocs
= (ELF_RELOC
*)sdata
[i
];
535 nb_relocs
= shdr
[i
].sh_size
/ shdr
[i
].sh_entsize
;
538 symtab_sec
= find_elf_section(shdr
, ehdr
.e_shnum
, shstr
, ".symtab");
540 error("could not find .symtab section");
541 strtab_sec
= &shdr
[symtab_sec
->sh_link
];
543 symtab
= (ElfW(Sym
) *)sdata
[symtab_sec
- shdr
];
544 strtab
= sdata
[symtab_sec
->sh_link
];
546 nb_syms
= symtab_sec
->sh_size
/ sizeof(ElfW(Sym
));
548 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
549 swab32s(&sym
->st_name
);
550 swabls(&sym
->st_value
);
551 swabls(&sym
->st_size
);
552 swab16s(&sym
->st_shndx
);
559 #endif /* CONFIG_FORMAT_ELF */
561 #ifdef CONFIG_FORMAT_COFF
564 struct external_scnhdr
*shdr
;
566 struct external_filehdr fhdr
;
567 struct external_syment
*coff_symtab
;
569 int coff_text_shndx
, coff_data_shndx
;
573 #define STRTAB_SIZE 4
578 #define T_FUNCTION 0x20
581 void sym_ent_name(struct external_syment
*ext_sym
, EXE_SYM
*sym
)
586 if (ext_sym
->e
.e
.e_zeroes
!= 0) {
588 for(i
= 0; i
< 8; i
++) {
589 c
= ext_sym
->e
.e_name
[i
];
596 pstrcpy(sym
->st_name
, sizeof(sym
->st_name
), strtab
+ ext_sym
->e
.e
.e_offset
);
599 /* now convert the name to a C name (suppress the leading '_') */
600 if (sym
->st_name
[0] == '_') {
601 len
= strlen(sym
->st_name
);
602 memmove(sym
->st_name
, sym
->st_name
+ 1, len
- 1);
603 sym
->st_name
[len
- 1] = '\0';
607 char *name_for_dotdata(struct coff_rel
*rel
)
610 struct coff_sym
*sym
;
613 text_data
= *(uint32_t *)(text
+ rel
->r_offset
);
615 for (i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
616 if (sym
->st_syment
->e_scnum
== data_shndx
&&
617 text_data
>= sym
->st_value
&&
618 text_data
< sym
->st_value
+ sym
->st_size
) {
627 static char *get_sym_name(EXE_SYM
*sym
)
632 static char *get_rel_sym_name(EXE_RELOC
*rel
)
635 name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
636 if (!strcmp(name
, ".data"))
637 name
= name_for_dotdata(rel
);
643 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
645 return rel
->r_offset
;
648 struct external_scnhdr
*find_coff_section(struct external_scnhdr
*shdr
, int shnum
, const char *name
)
652 struct external_scnhdr
*sec
;
654 for(i
= 0; i
< shnum
; i
++) {
658 shname
= sec
->s_name
;
659 if (!strcmp(shname
, name
))
665 /* load a coff object file */
666 int load_object(const char *filename
)
669 struct external_scnhdr
*sec
, *text_sec
, *data_sec
;
671 struct external_syment
*ext_sym
;
672 struct external_reloc
*coff_relocs
;
673 struct external_reloc
*ext_rel
;
678 fd
= open(filename
, O_RDONLY
684 error("can't open file '%s'", filename
);
686 /* Read COFF header. */
687 if (read(fd
, &fhdr
, sizeof (fhdr
)) != sizeof (fhdr
))
688 error("unable to read file header");
690 /* Check COFF identification. */
691 if (fhdr
.f_magic
!= I386MAGIC
) {
692 error("bad COFF header");
696 /* read section headers */
697 shdr
= load_data(fd
, sizeof(struct external_filehdr
) + fhdr
.f_opthdr
, fhdr
.f_nscns
* sizeof(struct external_scnhdr
));
699 /* read all section data */
700 sdata
= malloc(sizeof(void *) * fhdr
.f_nscns
);
701 memset(sdata
, 0, sizeof(void *) * fhdr
.f_nscns
);
704 for(i
= 0;i
< fhdr
.f_nscns
; i
++) {
706 if (!strstart(sec
->s_name
, ".bss", &p
))
707 sdata
[i
] = load_data(fd
, sec
->s_scnptr
, sec
->s_size
);
712 text_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".text");
714 error("could not find .text section");
715 coff_text_shndx
= text_sec
- shdr
;
716 text
= sdata
[coff_text_shndx
];
719 data_sec
= find_coff_section(shdr
, fhdr
.f_nscns
, ".data");
721 error("could not find .data section");
722 coff_data_shndx
= data_sec
- shdr
;
724 coff_symtab
= load_data(fd
, fhdr
.f_symptr
, fhdr
.f_nsyms
*SYMESZ
);
725 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
727 printf(" %02x", ((uint8_t *)ext_sym
->e
.e_name
)[i
]);
732 n_strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), STRTAB_SIZE
);
733 strtab
= load_data(fd
, (fhdr
.f_symptr
+ fhdr
.f_nsyms
*SYMESZ
), *n_strtab
);
735 nb_syms
= fhdr
.f_nsyms
;
737 for (i
= 0, ext_sym
= coff_symtab
; i
< nb_syms
; i
++, ext_sym
++) {
738 if (strstart(ext_sym
->e
.e_name
, ".text", NULL
))
739 text_shndx
= ext_sym
->e_scnum
;
740 if (strstart(ext_sym
->e
.e_name
, ".data", NULL
))
741 data_shndx
= ext_sym
->e_scnum
;
744 /* set coff symbol */
745 symtab
= malloc(sizeof(struct coff_sym
) * nb_syms
);
748 for (i
= 0, ext_sym
= coff_symtab
, sym
= symtab
; i
< nb_syms
; i
++, ext_sym
++, sym
++) {
749 memset(sym
, 0, sizeof(*sym
));
750 sym
->st_syment
= ext_sym
;
751 sym_ent_name(ext_sym
, sym
);
752 sym
->st_value
= ext_sym
->e_value
;
754 aux_size
= *(int8_t *)ext_sym
->e_numaux
;
755 if (ext_sym
->e_scnum
== text_shndx
&& ext_sym
->e_type
== T_FUNCTION
) {
756 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
757 if ((ext_sym
+ j
)->e_scnum
== text_shndx
&&
758 (ext_sym
+ j
)->e_type
== T_FUNCTION
){
759 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
761 } else if (j
== nb_syms
- i
- 1) {
762 sec
= &shdr
[coff_text_shndx
];
763 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
767 } else if (ext_sym
->e_scnum
== data_shndx
&& *(uint8_t *)ext_sym
->e_sclass
== C_EXTERNAL
) {
768 for (j
= aux_size
+ 1; j
< nb_syms
- i
; j
++) {
769 if ((ext_sym
+ j
)->e_scnum
== data_shndx
) {
770 sym
->st_size
= (ext_sym
+ j
)->e_value
- ext_sym
->e_value
;
772 } else if (j
== nb_syms
- i
- 1) {
773 sec
= &shdr
[coff_data_shndx
];
774 sym
->st_size
= sec
->s_size
- ext_sym
->e_value
;
782 sym
->st_type
= ext_sym
->e_type
;
783 sym
->st_shndx
= ext_sym
->e_scnum
;
787 /* find text relocations, if any */
788 sec
= &shdr
[coff_text_shndx
];
789 coff_relocs
= load_data(fd
, sec
->s_relptr
, sec
->s_nreloc
*RELSZ
);
790 nb_relocs
= sec
->s_nreloc
;
792 /* set coff relocation */
793 relocs
= malloc(sizeof(struct coff_rel
) * nb_relocs
);
794 for (i
= 0, ext_rel
= coff_relocs
, rel
= relocs
; i
< nb_relocs
;
795 i
++, ext_rel
++, rel
++) {
796 memset(rel
, 0, sizeof(*rel
));
797 rel
->r_reloc
= ext_rel
;
798 rel
->r_offset
= *(uint32_t *)ext_rel
->r_vaddr
;
799 rel
->r_type
= *(uint16_t *)ext_rel
->r_type
;
804 #endif /* CONFIG_FORMAT_COFF */
806 #ifdef CONFIG_FORMAT_MACH
809 struct mach_header mach_hdr
;
812 struct segment_command
*segment
= 0;
813 struct dysymtab_command
*dysymtabcmd
= 0;
814 struct symtab_command
*symtabcmd
= 0;
817 struct section
*section_hdr
;
818 struct section
*text_sec_hdr
;
822 struct relocation_info
*relocs
;
826 struct nlist
*symtab_std
;
829 /* indirect symbols */
832 /* Utility functions */
834 static inline char *find_str_by_index(int index
)
839 /* Used by dyngen common code */
840 static char *get_sym_name(EXE_SYM
*sym
)
842 char *name
= find_str_by_index(sym
->n_un
.n_strx
);
844 if ( sym
->n_type
& N_STAB
) /* Debug symbols are ignored */
855 /* find a section index given its segname, sectname */
856 static int find_mach_sec_index(struct section
*section_hdr
, int shnum
, const char *segname
,
857 const char *sectname
)
860 struct section
*sec
= section_hdr
;
862 for(i
= 0; i
< shnum
; i
++, sec
++) {
863 if (!sec
->segname
|| !sec
->sectname
)
865 if (!strcmp(sec
->sectname
, sectname
) && !strcmp(sec
->segname
, segname
))
871 /* find a section header given its segname, sectname */
872 struct section
*find_mach_sec_hdr(struct section
*section_hdr
, int shnum
, const char *segname
,
873 const char *sectname
)
875 int index
= find_mach_sec_index(section_hdr
, shnum
, segname
, sectname
);
878 return section_hdr
+index
;
882 static inline void fetch_next_pair_value(struct relocation_info
* rel
, unsigned int *value
)
884 struct scattered_relocation_info
* scarel
;
886 if(R_SCATTERED
& rel
->r_address
) {
887 scarel
= (struct scattered_relocation_info
*)rel
;
888 if(scarel
->r_type
!= PPC_RELOC_PAIR
)
889 error("fetch_next_pair_value: looking for a pair which was not found (1)");
890 *value
= scarel
->r_value
;
892 if(rel
->r_type
!= PPC_RELOC_PAIR
)
893 error("fetch_next_pair_value: looking for a pair which was not found (2)");
894 *value
= rel
->r_address
;
898 /* find a sym name given its value, in a section number */
899 static const char * find_sym_with_value_and_sec_number( int value
, int sectnum
, int * offset
)
903 for( i
= 0 ; i
< nb_syms
; i
++ )
905 if( !(symtab
[i
].n_type
& N_STAB
) && (symtab
[i
].n_type
& N_SECT
) &&
906 (symtab
[i
].n_sect
== sectnum
) && (symtab
[i
].st_value
<= value
) )
908 if( (ret
<0) || (symtab
[i
].st_value
>= symtab
[ret
].st_value
) )
916 *offset
= value
- symtab
[ret
].st_value
;
917 return get_sym_name(&symtab
[ret
]);
922 * Find symbol name given a (virtual) address, and a section which is of type
923 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
925 static const char * find_reloc_name_in_sec_ptr(int address
, struct section
* sec_hdr
)
927 unsigned int tocindex
, symindex
, size
;
928 const char *name
= 0;
931 if(!( address
>= sec_hdr
->addr
&& address
< (sec_hdr
->addr
+ sec_hdr
->size
) ) )
934 if( sec_hdr
->flags
& S_SYMBOL_STUBS
){
935 size
= sec_hdr
->reserved2
;
940 else if( sec_hdr
->flags
& S_LAZY_SYMBOL_POINTERS
||
941 sec_hdr
->flags
& S_NON_LAZY_SYMBOL_POINTERS
)
942 size
= sizeof(unsigned long);
946 /* Compute our index in toc */
947 tocindex
= (address
- sec_hdr
->addr
)/size
;
948 symindex
= tocdylib
[sec_hdr
->reserved1
+ tocindex
];
950 name
= get_sym_name(&symtab
[symindex
]);
955 static const char * find_reloc_name_given_its_address(int address
)
958 for(i
= 0; i
< segment
->nsects
; i
++)
960 const char * name
= find_reloc_name_in_sec_ptr(address
, §ion_hdr
[i
]);
967 static const char * get_reloc_name(EXE_RELOC
* rel
, int * sslide
)
970 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
971 int sectnum
= rel
->r_symbolnum
;
975 /* init the slide value */
978 if(R_SCATTERED
& rel
->r_address
)
979 return (char *)find_reloc_name_given_its_address(sca_rel
->r_value
);
983 /* ignore debug sym */
984 if ( symtab
[rel
->r_symbolnum
].n_type
& N_STAB
)
986 return get_sym_name(&symtab
[rel
->r_symbolnum
]);
989 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
990 sectoffset
= *(uint32_t *)(text
+ rel
->r_address
) & 0xffff;
992 if(sectnum
==0xffffff)
996 if(sectnum
> segment
->nsects
)
997 error("sectnum > segment->nsects");
1001 case PPC_RELOC_LO16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
|= (other_half
<< 16);
1003 case PPC_RELOC_HI16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) | (uint16_t)(other_half
& 0xffff);
1005 case PPC_RELOC_HA16
: fetch_next_pair_value(rel
+1, &other_half
); sectoffset
= (sectoffset
<< 16) + (int16_t)(other_half
& 0xffff);
1007 case PPC_RELOC_BR24
:
1008 sectoffset
= ( *(uint32_t *)(text
+ rel
->r_address
) & 0x03fffffc );
1009 if (sectoffset
& 0x02000000) sectoffset
|= 0xfc000000;
1012 error("switch(rel->type) not found");
1016 sectoffset
+= rel
->r_address
;
1018 if (rel
->r_type
== PPC_RELOC_BR24
)
1019 name
= (char *)find_reloc_name_in_sec_ptr((int)sectoffset
, §ion_hdr
[sectnum
-1]);
1021 /* search it in the full symbol list, if not found */
1023 name
= (char *)find_sym_with_value_and_sec_number(sectoffset
, sectnum
, sslide
);
1028 /* Used by dyngen common code */
1029 static const char * get_rel_sym_name(EXE_RELOC
* rel
)
1032 return get_reloc_name( rel
, &sslide
);
1035 /* Used by dyngen common code */
1036 static host_ulong
get_rel_offset(EXE_RELOC
*rel
)
1038 struct scattered_relocation_info
* sca_rel
= (struct scattered_relocation_info
*)rel
;
1039 if(R_SCATTERED
& rel
->r_address
)
1040 return sca_rel
->r_address
;
1042 return rel
->r_address
;
1045 /* load a mach-o object file */
1046 int load_object(const char *filename
)
1049 unsigned int offset_to_segment
= 0;
1050 unsigned int offset_to_dysymtab
= 0;
1051 unsigned int offset_to_symtab
= 0;
1052 struct load_command lc
;
1055 struct nlist
*syment
;
1057 fd
= open(filename
, O_RDONLY
);
1059 error("can't open file '%s'", filename
);
1061 /* Read Mach header. */
1062 if (read(fd
, &mach_hdr
, sizeof (mach_hdr
)) != sizeof (mach_hdr
))
1063 error("unable to read file header");
1065 /* Check Mach identification. */
1066 if (!check_mach_header(mach_hdr
)) {
1067 error("bad Mach header");
1070 if (mach_hdr
.cputype
!= CPU_TYPE_POWERPC
)
1071 error("Unsupported CPU");
1073 if (mach_hdr
.filetype
!= MH_OBJECT
)
1074 error("Unsupported Mach Object");
1076 /* read segment headers */
1077 for(i
=0, j
=sizeof(mach_hdr
); i
<mach_hdr
.ncmds
; i
++)
1079 if(read(fd
, &lc
, sizeof(struct load_command
)) != sizeof(struct load_command
))
1080 error("unable to read load_command");
1081 if(lc
.cmd
== LC_SEGMENT
)
1083 offset_to_segment
= j
;
1084 lseek(fd
, offset_to_segment
, SEEK_SET
);
1085 segment
= malloc(sizeof(struct segment_command
));
1086 if(read(fd
, segment
, sizeof(struct segment_command
)) != sizeof(struct segment_command
))
1087 error("unable to read LC_SEGMENT");
1089 if(lc
.cmd
== LC_DYSYMTAB
)
1091 offset_to_dysymtab
= j
;
1092 lseek(fd
, offset_to_dysymtab
, SEEK_SET
);
1093 dysymtabcmd
= malloc(sizeof(struct dysymtab_command
));
1094 if(read(fd
, dysymtabcmd
, sizeof(struct dysymtab_command
)) != sizeof(struct dysymtab_command
))
1095 error("unable to read LC_DYSYMTAB");
1097 if(lc
.cmd
== LC_SYMTAB
)
1099 offset_to_symtab
= j
;
1100 lseek(fd
, offset_to_symtab
, SEEK_SET
);
1101 symtabcmd
= malloc(sizeof(struct symtab_command
));
1102 if(read(fd
, symtabcmd
, sizeof(struct symtab_command
)) != sizeof(struct symtab_command
))
1103 error("unable to read LC_SYMTAB");
1107 lseek(fd
, j
, SEEK_SET
);
1111 error("unable to find LC_SEGMENT");
1113 /* read section headers */
1114 section_hdr
= load_data(fd
, offset_to_segment
+ sizeof(struct segment_command
), segment
->nsects
* sizeof(struct section
));
1116 /* read all section data */
1117 sdata
= (uint8_t **)malloc(sizeof(void *) * segment
->nsects
);
1118 memset(sdata
, 0, sizeof(void *) * segment
->nsects
);
1120 /* Load the data in section data */
1121 for(i
= 0; i
< segment
->nsects
; i
++) {
1122 sdata
[i
] = load_data(fd
, section_hdr
[i
].offset
, section_hdr
[i
].size
);
1126 text_sec_hdr
= find_mach_sec_hdr(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1127 i
= find_mach_sec_index(section_hdr
, segment
->nsects
, SEG_TEXT
, SECT_TEXT
);
1128 if (i
== -1 || !text_sec_hdr
)
1129 error("could not find __TEXT,__text section");
1132 /* Make sure dysym was loaded */
1133 if(!(int)dysymtabcmd
)
1134 error("could not find __DYSYMTAB segment");
1136 /* read the table of content of the indirect sym */
1137 tocdylib
= load_data( fd
, dysymtabcmd
->indirectsymoff
, dysymtabcmd
->nindirectsyms
* sizeof(uint32_t) );
1139 /* Make sure symtab was loaded */
1141 error("could not find __SYMTAB segment");
1142 nb_syms
= symtabcmd
->nsyms
;
1144 symtab_std
= load_data(fd
, symtabcmd
->symoff
, symtabcmd
->nsyms
* sizeof(struct nlist
));
1145 strtab
= load_data(fd
, symtabcmd
->stroff
, symtabcmd
->strsize
);
1147 symtab
= malloc(sizeof(EXE_SYM
) * nb_syms
);
1149 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1150 for(i
= 0, sym
= symtab
, syment
= symtab_std
; i
< nb_syms
; i
++, sym
++, syment
++) {
1151 struct nlist
*sym_follow
, *sym_next
= 0;
1153 memset(sym
, 0, sizeof(*sym
));
1155 if ( syment
->n_type
& N_STAB
) /* Debug symbols are skipped */
1158 memcpy(sym
, syment
, sizeof(*syment
));
1160 /* Find the following symbol in order to get the current symbol size */
1161 for(j
= 0, sym_follow
= symtab_std
; j
< nb_syms
; j
++, sym_follow
++) {
1162 if ( sym_follow
->n_sect
!= 1 || sym_follow
->n_type
& N_STAB
|| !(sym_follow
->n_value
> sym
->st_value
))
1165 sym_next
= sym_follow
;
1168 if(!(sym_next
->n_value
> sym_follow
->n_value
))
1170 sym_next
= sym_follow
;
1173 sym
->st_size
= sym_next
->n_value
- sym
->st_value
;
1175 sym
->st_size
= text_sec_hdr
->size
- sym
->st_value
;
1179 relocs
= load_data(fd
, text_sec_hdr
->reloff
, text_sec_hdr
->nreloc
* sizeof(struct relocation_info
));
1180 nb_relocs
= text_sec_hdr
->nreloc
;
1186 #endif /* CONFIG_FORMAT_MACH */
1188 void get_reloc_expr(char *name
, int name_size
, const char *sym_name
)
1192 if (strstart(sym_name
, "__op_param", &p
)) {
1193 snprintf(name
, name_size
, "param%s", p
);
1194 } else if (strstart(sym_name
, "__op_gen_label", &p
)) {
1195 snprintf(name
, name_size
, "gen_labels[param%s]", p
);
1198 if (sym_name
[0] == '.')
1199 snprintf(name
, name_size
,
1200 "(long)(&__dot_%s)",
1204 snprintf(name
, name_size
, "(long)(&%s)", sym_name
);
1210 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1213 struct plt_entry
*next
;
1215 unsigned long addend
;
1219 get_plt_index (const char *name
, unsigned long addend
)
1221 struct plt_entry
*plt
, *prev
= NULL
;
1224 /* see if we already have an entry for this target: */
1225 for (plt
= plt_list
; plt
; ++index
, prev
= plt
, plt
= plt
->next
)
1226 if (strcmp(plt
->name
, name
) == 0 && plt
->addend
== addend
)
1229 /* nope; create a new PLT entry: */
1231 plt
= malloc(sizeof(*plt
));
1236 memset(plt
, 0, sizeof(*plt
));
1237 plt
->name
= strdup(name
);
1238 plt
->addend
= addend
;
1240 /* append to plt-list: */
1252 int arm_emit_ldr_info(const char *name
, unsigned long start_offset
,
1253 FILE *outfile
, uint8_t *p_start
, uint8_t *p_end
,
1254 ELF_RELOC
*relocs
, int nb_relocs
)
1258 int offset
, min_offset
, pc_offset
, data_size
, spare
, max_pool
;
1259 uint8_t data_allocated
[1024];
1260 unsigned int data_index
;
1263 memset(data_allocated
, 0, sizeof(data_allocated
));
1266 min_offset
= p_end
- p_start
;
1268 while (p
< p_start
+ min_offset
) {
1269 insn
= get32((uint32_t *)p
);
1270 /* TODO: Armv5e ldrd. */
1271 /* TODO: VFP load. */
1272 if ((insn
& 0x0d5f0000) == 0x051f0000) {
1273 /* ldr reg, [pc, #im] */
1274 offset
= insn
& 0xfff;
1275 if (!(insn
& 0x00800000))
1279 } else if ((insn
& 0x0e5f0f00) == 0x0c1f0100) {
1281 offset
= (insn
& 0xff) << 2;
1282 if (!(insn
& 0x00800000))
1286 } else if ((insn
& 0x0fff0000) == 0x028f0000) {
1287 /* Some gcc load a doubleword immediate with
1289 ldmia regN, {regN, regM}
1290 Hope and pray the compiler never generates somethin like
1291 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1294 r
= (insn
& 0xf00) >> 7;
1295 offset
= ((insn
& 0xff) >> r
) | ((insn
& 0xff) << (32 - r
));
1303 /* PC-relative load needs fixing up. */
1304 if (spare
> max_pool
- offset
)
1305 spare
= max_pool
- offset
;
1306 if ((offset
& 3) !=0)
1307 error("%s:%04x: pc offset must be 32 bit aligned",
1308 name
, start_offset
+ p
- p_start
);
1310 error("%s:%04x: Embedded literal value",
1311 name
, start_offset
+ p
- p_start
);
1312 pc_offset
= p
- p_start
+ offset
+ 8;
1313 if (pc_offset
<= (p
- p_start
) ||
1314 pc_offset
>= (p_end
- p_start
))
1315 error("%s:%04x: pc offset must point inside the function code",
1316 name
, start_offset
+ p
- p_start
);
1317 if (pc_offset
< min_offset
)
1318 min_offset
= pc_offset
;
1320 /* The intruction position */
1321 fprintf(outfile
, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1323 /* The position of the constant pool data. */
1324 data_index
= ((p_end
- p_start
) - pc_offset
) >> 2;
1325 fprintf(outfile
, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1327 fprintf(outfile
, " arm_ldr_ptr->type = %d;\n", type
);
1328 fprintf(outfile
, " arm_ldr_ptr++;\n");
1334 /* Copy and relocate the constant pool data. */
1335 data_size
= (p_end
- p_start
) - min_offset
;
1336 if (data_size
> 0 && outfile
) {
1337 spare
+= min_offset
;
1338 fprintf(outfile
, " arm_data_ptr -= %d;\n", data_size
>> 2);
1339 fprintf(outfile
, " arm_pool_ptr -= %d;\n", data_size
);
1340 fprintf(outfile
, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1341 " arm_pool_ptr = gen_code_ptr + %d;\n",
1345 for (pc_offset
= min_offset
;
1346 pc_offset
< p_end
- p_start
;
1350 int i
, addend
, type
;
1351 const char *sym_name
;
1355 addend
= get32((uint32_t *)(p_start
+ pc_offset
));
1357 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1358 if (rel
->r_offset
== (pc_offset
+ start_offset
)) {
1359 sym_name
= get_rel_sym_name(rel
);
1360 /* the compiler leave some unnecessary references to the code */
1361 get_reloc_expr(relname
, sizeof(relname
), sym_name
);
1362 type
= ELF32_R_TYPE(rel
->r_info
);
1363 if (type
!= R_ARM_ABS32
)
1364 error("%s: unsupported data relocation", name
);
1368 fprintf(outfile
, " arm_data_ptr[%d] = 0x%x",
1369 data_index
, addend
);
1370 if (relname
[0] != '\0')
1371 fprintf(outfile
, " + %s", relname
);
1372 fprintf(outfile
, ";\n");
1381 insn
= get32((uint32_t *)p
);
1382 /* The last instruction must be an ldm instruction. There are several
1383 forms generated by gcc:
1384 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1386 ldmea fp, {..., pc} */
1387 if ((insn
& 0xffff8000) == 0xe99d8000) {
1390 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1394 } else if ((insn
& 0xffff8000) != 0xe89d8000
1395 && (insn
& 0xffff8000) != 0xe91b8000) {
1398 printf("%s: invalid epilog\n", name
);
1407 /* generate op code */
1408 void gen_code(const char *name
, host_ulong offset
, host_ulong size
,
1409 FILE *outfile
, int gen_switch
)
1412 uint8_t *p_start
, *p_end
;
1413 host_ulong start_offset
;
1415 uint8_t args_present
[MAX_ARGS
];
1416 const char *sym_name
, *p
;
1419 /* Compute exact size excluding prologue and epilogue instructions.
1420 * Increment start_offset to skip epilogue instructions, then compute
1421 * copy_size the indicate the size of the remaining instructions (in
1424 p_start
= text
+ offset
;
1425 p_end
= p_start
+ size
;
1426 start_offset
= offset
;
1427 #if defined(HOST_I386) || defined(HOST_X86_64)
1428 #ifdef CONFIG_FORMAT_COFF
1433 error("empty code for %s", name
);
1434 while (*p
!= 0xc3) {
1437 error("ret or jmp expected at the end of %s", name
);
1439 copy_size
= p
- p_start
;
1444 len
= p_end
- p_start
;
1446 error("empty code for %s", name
);
1447 if (p_end
[-1] == 0xc3) {
1450 error("ret or jmp expected at the end of %s", name
);
1455 #elif defined(HOST_PPC)
1458 p
= (void *)(p_end
- 4);
1460 error("empty code for %s", name
);
1461 if (get32((uint32_t *)p
) != 0x4e800020)
1462 error("blr expected at the end of %s", name
);
1463 copy_size
= p
- p_start
;
1465 #elif defined(HOST_S390)
1468 p
= (void *)(p_end
- 2);
1470 error("empty code for %s", name
);
1471 if (get16((uint16_t *)p
) != 0x07fe && get16((uint16_t *)p
) != 0x07f4)
1472 error("br %%r14 expected at the end of %s", name
);
1473 copy_size
= p
- p_start
;
1475 #elif defined(HOST_ALPHA)
1480 /* XXX: check why it occurs */
1482 error("empty code for %s", name
);
1484 if (get32((uint32_t *)p
) != 0x6bfa8001)
1485 error("ret expected at the end of %s", name
);
1486 copy_size
= p
- p_start
;
1488 #elif defined(HOST_IA64)
1491 p
= (void *)(p_end
- 4);
1493 error("empty code for %s", name
);
1494 /* br.ret.sptk.many b0;; */
1496 if (get32((uint32_t *)p
) != 0x00840008)
1497 error("br.ret.sptk.many b0;; expected at the end of %s", name
);
1498 copy_size
= p_end
- p_start
;
1500 #elif defined(HOST_SPARC)
1502 #define INSN_SAVE 0x9de3a000
1503 #define INSN_RET 0x81c7e008
1504 #define INSN_RETL 0x81c3e008
1505 #define INSN_RESTORE 0x81e80000
1506 #define INSN_RETURN 0x81cfe008
1507 #define INSN_NOP 0x01000000
1508 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1509 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1511 uint32_t start_insn
, end_insn1
, end_insn2
;
1513 p
= (void *)(p_end
- 8);
1515 error("empty code for %s", name
);
1516 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1517 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1518 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1519 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1520 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1522 start_offset
+= 0x4;
1523 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1524 /* SPARC v7: ret; restore; */ ;
1525 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1526 /* SPARC v9: return; nop; */ ;
1527 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1528 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1531 error("ret; restore; not found at end of %s", name
);
1532 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1535 error("No save at the beginning of %s", name
);
1538 /* Skip a preceeding nop, if present. */
1540 skip_insn
= get32((uint32_t *)(p
- 0x4));
1541 if (skip_insn
== INSN_NOP
)
1545 copy_size
= p
- p_start
;
1547 #elif defined(HOST_SPARC64)
1549 #define INSN_SAVE 0x9de3a000
1550 #define INSN_RET 0x81c7e008
1551 #define INSN_RETL 0x81c3e008
1552 #define INSN_RESTORE 0x81e80000
1553 #define INSN_RETURN 0x81cfe008
1554 #define INSN_NOP 0x01000000
1555 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1556 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1558 uint32_t start_insn
, end_insn1
, end_insn2
, skip_insn
;
1560 p
= (void *)(p_end
- 8);
1562 /* XXX: check why it occurs */
1564 error("empty code for %s", name
);
1566 start_insn
= get32((uint32_t *)(p_start
+ 0x0));
1567 end_insn1
= get32((uint32_t *)(p
+ 0x0));
1568 end_insn2
= get32((uint32_t *)(p
+ 0x4));
1569 if (((start_insn
& ~0x1fff) == INSN_SAVE
) ||
1570 (start_insn
& ~0x1fff) == INSN_ADD_SP
) {
1572 start_offset
+= 0x4;
1573 if (end_insn1
== INSN_RET
&& end_insn2
== INSN_RESTORE
)
1574 /* SPARC v7: ret; restore; */ ;
1575 else if (end_insn1
== INSN_RETURN
&& end_insn2
== INSN_NOP
)
1576 /* SPARC v9: return; nop; */ ;
1577 else if (end_insn1
== INSN_RETL
&& (end_insn2
& ~0x1fff) == INSN_SUB_SP
)
1578 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1581 error("ret; restore; not found at end of %s", name
);
1582 } else if (end_insn1
== INSN_RETL
&& end_insn2
== INSN_NOP
) {
1585 error("No save at the beginning of %s", name
);
1588 /* Skip a preceeding nop, if present. */
1590 skip_insn
= get32((uint32_t *)(p
- 0x4));
1591 if (skip_insn
== 0x01000000)
1595 copy_size
= p
- p_start
;
1597 #elif defined(HOST_ARM)
1601 if ((p_end
- p_start
) <= 16)
1602 error("%s: function too small", name
);
1603 if (get32((uint32_t *)p_start
) != 0xe1a0c00d ||
1604 (get32((uint32_t *)(p_start
+ 4)) & 0xffff0000) != 0xe92d0000 ||
1605 get32((uint32_t *)(p_start
+ 8)) != 0xe24cb004)
1606 error("%s: invalid prolog", name
);
1609 insn
= get32((uint32_t *)p_start
);
1610 if ((insn
& 0xffffff00) == 0xe24dd000) {
1611 /* Stack adjustment. Assume op uses the frame pointer. */
1615 copy_size
= arm_emit_ldr_info(name
, start_offset
, NULL
, p_start
, p_end
,
1618 #elif defined(HOST_M68K)
1621 p
= (void *)(p_end
- 2);
1623 error("empty code for %s", name
);
1624 // remove NOP's, probably added for alignment
1625 while ((get16((uint16_t *)p
) == 0x4e71) &&
1628 if (get16((uint16_t *)p
) != 0x4e75)
1629 error("rts expected at the end of %s", name
);
1630 copy_size
= p
- p_start
;
1633 #error unsupported CPU
1636 /* compute the number of arguments by looking at the relocations */
1637 for(i
= 0;i
< MAX_ARGS
; i
++)
1638 args_present
[i
] = 0;
1640 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1641 host_ulong offset
= get_rel_offset(rel
);
1642 if (offset
>= start_offset
&&
1643 offset
< start_offset
+ (p_end
- p_start
)) {
1644 sym_name
= get_rel_sym_name(rel
);
1647 if (strstart(sym_name
, "__op_param", &p
) ||
1648 strstart(sym_name
, "__op_gen_label", &p
)) {
1649 n
= strtoul(p
, NULL
, 10);
1651 error("too many arguments in %s", name
);
1652 args_present
[n
- 1] = 1;
1658 while (nb_args
< MAX_ARGS
&& args_present
[nb_args
])
1660 for(i
= nb_args
; i
< MAX_ARGS
; i
++) {
1661 if (args_present
[i
])
1662 error("inconsistent argument numbering in %s", name
);
1665 if (gen_switch
== 2) {
1666 fprintf(outfile
, "DEF(%s, %d, %d)\n", name
+ 3, nb_args
, copy_size
);
1667 } else if (gen_switch
== 1) {
1670 fprintf(outfile
, "case INDEX_%s: {\n", name
);
1672 fprintf(outfile
, " long ");
1673 for(i
= 0; i
< nb_args
; i
++) {
1675 fprintf(outfile
, ", ");
1676 fprintf(outfile
, "param%d", i
+ 1);
1678 fprintf(outfile
, ";\n");
1680 #if defined(HOST_IA64)
1681 fprintf(outfile
, " extern char %s;\n", name
);
1683 fprintf(outfile
, " extern void %s();\n", name
);
1686 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1687 host_ulong offset
= get_rel_offset(rel
);
1688 if (offset
>= start_offset
&&
1689 offset
< start_offset
+ (p_end
- p_start
)) {
1690 sym_name
= get_rel_sym_name(rel
);
1694 !strstart(sym_name
, "__op_param", NULL
) &&
1695 !strstart(sym_name
, "__op_jmp", NULL
) &&
1696 !strstart(sym_name
, "__op_gen_label", NULL
)) {
1697 #if defined(HOST_SPARC)
1698 if (sym_name
[0] == '.') {
1700 "extern char __dot_%s __asm__(\"%s\");\n",
1701 sym_name
+1, sym_name
);
1705 #if defined(__APPLE__)
1706 /* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
1707 fprintf(outfile
, "extern char %s __attribute__((unused));\n", sym_name
);
1708 #elif defined(HOST_IA64)
1709 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
1711 * PCREL21 br.call targets generally
1712 * are out of range and need to go
1713 * through an "import stub".
1715 fprintf(outfile
, " extern char %s;\n",
1718 fprintf(outfile
, "extern char %s;\n", sym_name
);
1724 fprintf(outfile
, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1725 name
, (int)(start_offset
- offset
), copy_size
);
1727 /* emit code offset information */
1730 const char *sym_name
, *p
;
1734 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
1735 sym_name
= get_sym_name(sym
);
1736 if (strstart(sym_name
, "__op_label", &p
)) {
1738 unsigned long offset
;
1740 /* test if the variable refers to a label inside
1741 the code we are generating */
1742 #ifdef CONFIG_FORMAT_COFF
1743 if (sym
->st_shndx
== text_shndx
) {
1744 ptr
= sdata
[coff_text_shndx
];
1745 } else if (sym
->st_shndx
== data_shndx
) {
1746 ptr
= sdata
[coff_data_shndx
];
1750 #elif defined(CONFIG_FORMAT_MACH)
1753 ptr
= sdata
[sym
->n_sect
-1];
1755 ptr
= sdata
[sym
->st_shndx
];
1758 error("__op_labelN in invalid section");
1759 offset
= sym
->st_value
;
1760 #ifdef CONFIG_FORMAT_MACH
1761 offset
-= section_hdr
[sym
->n_sect
-1].addr
;
1763 val
= *(unsigned long *)(ptr
+ offset
);
1764 #ifdef ELF_USES_RELOCA
1766 int reloc_shndx
, nb_relocs1
, j
;
1768 /* try to find a matching relocation */
1769 reloc_shndx
= find_reloc(sym
->st_shndx
);
1771 nb_relocs1
= shdr
[reloc_shndx
].sh_size
/
1772 shdr
[reloc_shndx
].sh_entsize
;
1773 rel
= (ELF_RELOC
*)sdata
[reloc_shndx
];
1774 for(j
= 0; j
< nb_relocs1
; j
++) {
1775 if (rel
->r_offset
== offset
) {
1776 val
= rel
->r_addend
;
1784 if (val
>= start_offset
&& val
<= start_offset
+ copy_size
) {
1785 n
= strtol(p
, NULL
, 10);
1786 fprintf(outfile
, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n
, (long)(val
- start_offset
));
1792 /* load parameres in variables */
1793 for(i
= 0; i
< nb_args
; i
++) {
1794 fprintf(outfile
, " param%d = *opparam_ptr++;\n", i
+ 1);
1797 /* patch relocations */
1798 #if defined(HOST_I386)
1804 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1805 if (rel
->r_offset
>= start_offset
&&
1806 rel
->r_offset
< start_offset
+ copy_size
) {
1807 sym_name
= get_rel_sym_name(rel
);
1810 reloc_offset
= rel
->r_offset
- start_offset
;
1811 if (strstart(sym_name
, "__op_jmp", &p
)) {
1813 n
= strtol(p
, NULL
, 10);
1814 /* __op_jmp relocations are done at
1815 runtime to do translated block
1816 chaining: the offset of the instruction
1817 needs to be stored */
1818 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1823 get_reloc_expr(name
, sizeof(name
), sym_name
);
1824 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
1825 #ifdef CONFIG_FORMAT_ELF
1826 type
= ELF32_R_TYPE(rel
->r_info
);
1829 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1830 reloc_offset
, name
, addend
);
1833 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1834 reloc_offset
, name
, reloc_offset
, addend
);
1837 error("unsupported i386 relocation (%d)", type
);
1839 #elif defined(CONFIG_FORMAT_COFF)
1844 temp_name
= get_sym_name(symtab
+ *(uint32_t *)(rel
->r_reloc
->r_symndx
));
1845 if (!strcmp(temp_name
, ".data")) {
1846 for (j
= 0, sym
= symtab
; j
< nb_syms
; j
++, sym
++) {
1847 if (strstart(sym
->st_name
, sym_name
, NULL
)) {
1848 addend
-= sym
->st_value
;
1856 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1857 reloc_offset
, name
, addend
);
1860 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1861 reloc_offset
, name
, reloc_offset
, addend
);
1864 error("unsupported i386 relocation (%d)", type
);
1867 #error unsupport object format
1872 #elif defined(HOST_X86_64)
1878 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1879 if (rel
->r_offset
>= start_offset
&&
1880 rel
->r_offset
< start_offset
+ copy_size
) {
1881 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1882 get_reloc_expr(name
, sizeof(name
), sym_name
);
1883 type
= ELF32_R_TYPE(rel
->r_info
);
1884 addend
= rel
->r_addend
;
1885 reloc_offset
= rel
->r_offset
- start_offset
;
1888 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1889 reloc_offset
, name
, addend
);
1892 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1893 reloc_offset
, name
, addend
);
1896 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1897 reloc_offset
, name
, reloc_offset
, addend
);
1900 error("unsupported X86_64 relocation (%d)", type
);
1905 #elif defined(HOST_PPC)
1907 #ifdef CONFIG_FORMAT_ELF
1912 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
1913 if (rel
->r_offset
>= start_offset
&&
1914 rel
->r_offset
< start_offset
+ copy_size
) {
1915 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
1916 reloc_offset
= rel
->r_offset
- start_offset
;
1917 if (strstart(sym_name
, "__op_jmp", &p
)) {
1919 n
= strtol(p
, NULL
, 10);
1920 /* __op_jmp relocations are done at
1921 runtime to do translated block
1922 chaining: the offset of the instruction
1923 needs to be stored */
1924 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1929 get_reloc_expr(name
, sizeof(name
), sym_name
);
1930 type
= ELF32_R_TYPE(rel
->r_info
);
1931 addend
= rel
->r_addend
;
1934 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1935 reloc_offset
, name
, addend
);
1937 case R_PPC_ADDR16_LO
:
1938 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1939 reloc_offset
, name
, addend
);
1941 case R_PPC_ADDR16_HI
:
1942 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1943 reloc_offset
, name
, addend
);
1945 case R_PPC_ADDR16_HA
:
1946 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1947 reloc_offset
, name
, addend
);
1950 /* warning: must be at 32 MB distancy */
1951 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
1952 reloc_offset
, reloc_offset
, name
, reloc_offset
, addend
);
1955 error("unsupported powerpc relocation (%d)", type
);
1959 #elif defined(CONFIG_FORMAT_MACH)
1960 struct scattered_relocation_info
*scarel
;
1961 struct relocation_info
* rel
;
1962 char final_sym_name
[256];
1963 const char *sym_name
;
1968 for(i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
1969 unsigned int offset
, length
, value
= 0;
1970 unsigned int type
, pcrel
, isym
= 0;
1971 unsigned int usesym
= 0;
1973 if(R_SCATTERED
& rel
->r_address
) {
1974 scarel
= (struct scattered_relocation_info
*)rel
;
1975 offset
= (unsigned int)scarel
->r_address
;
1976 length
= scarel
->r_length
;
1977 pcrel
= scarel
->r_pcrel
;
1978 type
= scarel
->r_type
;
1979 value
= scarel
->r_value
;
1981 value
= isym
= rel
->r_symbolnum
;
1982 usesym
= (rel
->r_extern
);
1983 offset
= rel
->r_address
;
1984 length
= rel
->r_length
;
1985 pcrel
= rel
->r_pcrel
;
1989 slide
= offset
- start_offset
;
1991 if (!(offset
>= start_offset
&& offset
< start_offset
+ size
))
1992 continue; /* not in our range */
1994 sym_name
= get_reloc_name(rel
, &sslide
);
1996 if(usesym
&& symtab
[isym
].n_type
& N_STAB
)
1997 continue; /* don't handle STAB (debug sym) */
1999 if (sym_name
&& strstart(sym_name
, "__op_jmp", &p
)) {
2001 n
= strtol(p
, NULL
, 10);
2002 fprintf(outfile
, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2004 continue; /* Nothing more to do */
2009 fprintf(outfile
, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2010 name
, value
, usesym
? "use sym" : "don't use sym", offset
, length
, pcrel
? "pcrel":"", type
);
2011 continue; /* dunno how to handle without final_sym_name */
2014 get_reloc_expr(final_sym_name
, sizeof(final_sym_name
),
2017 case PPC_RELOC_BR24
:
2018 if (!strstart(sym_name
,"__op_gen_label",&p
)) {
2019 fprintf(outfile
, "{\n");
2020 fprintf(outfile
, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide
);
2021 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",
2022 slide
, slide
, name
, sslide
);
2023 fprintf(outfile
, "}\n");
2025 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2026 slide
, slide
, final_sym_name
, slide
);
2029 case PPC_RELOC_HI16
:
2030 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2031 slide
, final_sym_name
, sslide
);
2033 case PPC_RELOC_LO16
:
2034 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2035 slide
, final_sym_name
, sslide
);
2037 case PPC_RELOC_HA16
:
2038 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2039 slide
, final_sym_name
, sslide
);
2042 error("unsupported powerpc relocation (%d)", type
);
2046 #error unsupport object format
2049 #elif defined(HOST_S390)
2055 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2056 if (rel
->r_offset
>= start_offset
&&
2057 rel
->r_offset
< start_offset
+ copy_size
) {
2058 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2059 get_reloc_expr(name
, sizeof(name
), sym_name
);
2060 type
= ELF32_R_TYPE(rel
->r_info
);
2061 addend
= rel
->r_addend
;
2062 reloc_offset
= rel
->r_offset
- start_offset
;
2065 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2066 reloc_offset
, name
, addend
);
2069 fprintf(outfile
, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2070 reloc_offset
, name
, addend
);
2073 fprintf(outfile
, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2074 reloc_offset
, name
, addend
);
2077 error("unsupported s390 relocation (%d)", type
);
2082 #elif defined(HOST_ALPHA)
2084 for (i
= 0, rel
= relocs
; i
< nb_relocs
; i
++, rel
++) {
2085 if (rel
->r_offset
>= start_offset
&& rel
->r_offset
< start_offset
+ copy_size
) {
2089 type
= ELF64_R_TYPE(rel
->r_info
);
2090 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2091 reloc_offset
= rel
->r_offset
- start_offset
;
2093 case R_ALPHA_GPDISP
:
2094 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2095 as an immediate instead of constructing it from the pv or ra. */
2096 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2098 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2099 reloc_offset
+ (int)rel
->r_addend
);
2101 case R_ALPHA_LITUSE
:
2102 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2103 now, since some called functions (libc) need pv to be set up. */
2106 /* Branch target prediction hint. Ignore for now. Should be already
2107 correct for in-function jumps. */
2109 case R_ALPHA_LITERAL
:
2110 /* Load a literal from the GOT relative to the gp. Since there's only a
2111 single gp, nothing is to be done. */
2113 case R_ALPHA_GPRELHIGH
:
2114 /* Handle fake relocations against __op_param symbol. Need to emit the
2115 high part of the immediate value instead. Other symbols need no
2116 special treatment. */
2117 if (strstart(sym_name
, "__op_param", &p
))
2118 fprintf(outfile
, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2121 case R_ALPHA_GPRELLOW
:
2122 if (strstart(sym_name
, "__op_param", &p
))
2123 fprintf(outfile
, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2127 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2128 set up the gp from the pv. */
2129 fprintf(outfile
, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2130 reloc_offset
, sym_name
, reloc_offset
);
2133 error("unsupported Alpha relocation (%d)", type
);
2138 #elif defined(HOST_IA64)
2140 unsigned long sym_idx
;
2146 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2147 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2148 if (rel
->r_offset
< start_offset
2149 || rel
->r_offset
>= start_offset
+ copy_size
)
2151 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2152 code_offset
= rel
->r_offset
- start_offset
;
2153 if (strstart(sym_name
, "__op_jmp", &p
)) {
2155 n
= strtol(p
, NULL
, 10);
2156 /* __op_jmp relocations are done at
2157 runtime to do translated block
2158 chaining: the offset of the instruction
2159 needs to be stored */
2160 fprintf(outfile
, " jmp_offsets[%d] ="
2161 "%ld + (gen_code_ptr - gen_code_buf);\n",
2165 get_reloc_expr(name
, sizeof(name
), sym_name
);
2166 type
= ELF64_R_TYPE(rel
->r_info
);
2167 addend
= rel
->r_addend
;
2171 " ia64_imm64(gen_code_ptr + %ld, "
2173 code_offset
, name
, addend
);
2175 case R_IA64_LTOFF22X
:
2176 case R_IA64_LTOFF22
:
2177 fprintf(outfile
, " IA64_LTOFF(gen_code_ptr + %ld,"
2178 " %s + %ld, %d);\n",
2179 code_offset
, name
, addend
,
2180 (type
== R_IA64_LTOFF22X
));
2184 " ia64_ldxmov(gen_code_ptr + %ld,"
2185 " %s + %ld);\n", code_offset
, name
, addend
);
2188 case R_IA64_PCREL21B
:
2189 if (strstart(sym_name
, "__op_gen_label", NULL
)) {
2191 " ia64_imm21b(gen_code_ptr + %ld,"
2192 " (long) (%s + %ld -\n\t\t"
2193 "((long) gen_code_ptr + %ld)) >> 4);\n",
2194 code_offset
, name
, addend
,
2195 code_offset
& ~0xfUL
);
2198 " IA64_PLT(gen_code_ptr + %ld, "
2199 "%d);\t/* %s + %ld */\n",
2201 get_plt_index(sym_name
, addend
),
2206 error("unsupported ia64 relocation (0x%x)",
2210 fprintf(outfile
, " ia64_nop_b(gen_code_ptr + %d);\n",
2211 copy_size
- 16 + 2);
2213 #elif defined(HOST_SPARC)
2219 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2220 if (rel
->r_offset
>= start_offset
&&
2221 rel
->r_offset
< start_offset
+ copy_size
) {
2222 sym_name
= strtab
+ symtab
[ELF32_R_SYM(rel
->r_info
)].st_name
;
2223 get_reloc_expr(name
, sizeof(name
), sym_name
);
2224 type
= ELF32_R_TYPE(rel
->r_info
);
2225 addend
= rel
->r_addend
;
2226 reloc_offset
= rel
->r_offset
- start_offset
;
2229 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2230 reloc_offset
, name
, addend
);
2234 " *(uint32_t *)(gen_code_ptr + %d) = "
2235 "((*(uint32_t *)(gen_code_ptr + %d)) "
2237 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2238 reloc_offset
, reloc_offset
, name
, addend
);
2242 " *(uint32_t *)(gen_code_ptr + %d) = "
2243 "((*(uint32_t *)(gen_code_ptr + %d)) "
2245 " | ((%s + %d) & 0x3ff);\n",
2246 reloc_offset
, reloc_offset
, name
, addend
);
2248 case R_SPARC_WDISP30
:
2250 " *(uint32_t *)(gen_code_ptr + %d) = "
2251 "((*(uint32_t *)(gen_code_ptr + %d)) "
2253 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2254 " & 0x3fffffff);\n",
2255 reloc_offset
, reloc_offset
, name
, addend
,
2258 case R_SPARC_WDISP22
:
2260 " *(uint32_t *)(gen_code_ptr + %d) = "
2261 "((*(uint32_t *)(gen_code_ptr + %d)) "
2263 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2265 rel
->r_offset
- start_offset
,
2266 rel
->r_offset
- start_offset
,
2268 rel
->r_offset
- start_offset
);
2271 error("unsupported sparc relocation (%d)", type
);
2276 #elif defined(HOST_SPARC64)
2282 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2283 if (rel
->r_offset
>= start_offset
&&
2284 rel
->r_offset
< start_offset
+ copy_size
) {
2285 sym_name
= strtab
+ symtab
[ELF64_R_SYM(rel
->r_info
)].st_name
;
2286 get_reloc_expr(name
, sizeof(name
), sym_name
);
2287 type
= ELF32_R_TYPE(rel
->r_info
);
2288 addend
= rel
->r_addend
;
2289 reloc_offset
= rel
->r_offset
- start_offset
;
2292 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2293 reloc_offset
, name
, addend
);
2297 " *(uint32_t *)(gen_code_ptr + %d) = "
2298 "((*(uint32_t *)(gen_code_ptr + %d)) "
2300 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2301 reloc_offset
, reloc_offset
, name
, addend
);
2305 " *(uint32_t *)(gen_code_ptr + %d) = "
2306 "((*(uint32_t *)(gen_code_ptr + %d)) "
2308 " | ((%s + %d) & 0x3ff);\n",
2309 reloc_offset
, reloc_offset
, name
, addend
);
2312 addend
+= ELF64_R_TYPE_DATA (rel
->r_info
);
2314 " *(uint32_t *)(gen_code_ptr + %d) = "
2315 "((*(uint32_t *)(gen_code_ptr + %d)) "
2317 " | ((%s + %d) & 0x3ff);\n",
2318 reloc_offset
, reloc_offset
, name
, addend
);
2320 case R_SPARC_WDISP30
:
2322 " *(uint32_t *)(gen_code_ptr + %d) = "
2323 "((*(uint32_t *)(gen_code_ptr + %d)) "
2325 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2326 " & 0x3fffffff);\n",
2327 reloc_offset
, reloc_offset
, name
, addend
,
2330 case R_SPARC_WDISP22
:
2332 " *(uint32_t *)(gen_code_ptr + %d) = "
2333 "((*(uint32_t *)(gen_code_ptr + %d)) "
2335 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2337 reloc_offset
, reloc_offset
, name
, addend
,
2341 error("unsupported sparc64 relocation (%d) for symbol %s", type
, name
);
2346 #elif defined(HOST_ARM)
2354 insn
= get32((uint32_t *)(p_start
+ 4));
2355 /* If prologue ends in sub sp, sp, #const then assume
2356 op has a stack frame and needs the frame pointer. */
2357 if ((insn
& 0xffffff00) == 0xe24dd000) {
2360 opcode
= 0xe28db000; /* add fp, sp, #0. */
2362 /* ??? Need to undo the extra stack adjustment at the end of the op.
2363 For now just leave the stack misaligned and hope it doesn't break anything
2365 if ((insn
& 4) != 0) {
2366 /* Preserve doubleword stack alignment. */
2368 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2373 insn
= get32((uint32_t *)(p_start
- 4));
2374 /* Calculate the size of the saved registers,
2376 for (i
= 0; i
< 15; i
++) {
2377 if (insn
& (1 << i
))
2381 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode
);
2383 arm_emit_ldr_info(name
, start_offset
, outfile
, p_start
, p_end
,
2386 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2387 if (rel
->r_offset
>= start_offset
&&
2388 rel
->r_offset
< start_offset
+ copy_size
) {
2389 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2390 /* the compiler leave some unnecessary references to the code */
2391 if (sym_name
[0] == '\0')
2393 get_reloc_expr(name
, sizeof(name
), sym_name
);
2394 type
= ELF32_R_TYPE(rel
->r_info
);
2395 addend
= get32((uint32_t *)(text
+ rel
->r_offset
));
2396 reloc_offset
= rel
->r_offset
- start_offset
;
2399 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2400 reloc_offset
, name
, addend
);
2405 fprintf(outfile
, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2406 reloc_offset
, addend
, name
);
2409 error("unsupported arm relocation (%d)", type
);
2414 #elif defined(HOST_M68K)
2421 for(i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2422 if (rel
->r_offset
>= start_offset
&&
2423 rel
->r_offset
< start_offset
+ copy_size
) {
2424 sym
= &(symtab
[ELFW(R_SYM
)(rel
->r_info
)]);
2425 sym_name
= strtab
+ symtab
[ELFW(R_SYM
)(rel
->r_info
)].st_name
;
2426 get_reloc_expr(name
, sizeof(name
), sym_name
);
2427 type
= ELF32_R_TYPE(rel
->r_info
);
2428 addend
= get32((uint32_t *)(text
+ rel
->r_offset
)) + rel
->r_addend
;
2429 reloc_offset
= rel
->r_offset
- start_offset
;
2432 fprintf(outfile
, " /* R_68K_32 RELOC, offset %x */\n", rel
->r_offset
) ;
2433 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2434 reloc_offset
, name
, addend
);
2437 fprintf(outfile
, " /* R_68K_PC32 RELOC, offset %x */\n", rel
->r_offset
);
2438 fprintf(outfile
, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2439 reloc_offset
, name
, reloc_offset
, /*sym->st_value+*/ addend
);
2442 error("unsupported m68k relocation (%d)", type
);
2448 #error unsupported CPU
2450 fprintf(outfile
, " gen_code_ptr += %d;\n", copy_size
);
2451 fprintf(outfile
, "}\n");
2452 fprintf(outfile
, "break;\n\n");
2454 fprintf(outfile
, "static inline void gen_%s(", name
);
2456 fprintf(outfile
, "void");
2458 for(i
= 0; i
< nb_args
; i
++) {
2460 fprintf(outfile
, ", ");
2461 fprintf(outfile
, "long param%d", i
+ 1);
2464 fprintf(outfile
, ")\n");
2465 fprintf(outfile
, "{\n");
2466 for(i
= 0; i
< nb_args
; i
++) {
2467 fprintf(outfile
, " *gen_opparam_ptr++ = param%d;\n", i
+ 1);
2469 fprintf(outfile
, " *gen_opc_ptr++ = INDEX_%s;\n", name
);
2470 fprintf(outfile
, "}\n\n");
2474 int gen_file(FILE *outfile
, int out_type
)
2479 if (out_type
== OUT_INDEX_OP
) {
2480 fprintf(outfile
, "DEF(end, 0, 0)\n");
2481 fprintf(outfile
, "DEF(nop, 0, 0)\n");
2482 fprintf(outfile
, "DEF(nop1, 1, 0)\n");
2483 fprintf(outfile
, "DEF(nop2, 2, 0)\n");
2484 fprintf(outfile
, "DEF(nop3, 3, 0)\n");
2485 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2487 name
= get_sym_name(sym
);
2488 if (strstart(name
, OP_PREFIX
, NULL
)) {
2489 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 2);
2492 } else if (out_type
== OUT_GEN_OP
) {
2493 /* generate gen_xxx functions */
2494 fprintf(outfile
, "#include \"dyngen-op.h\"\n");
2495 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2497 name
= get_sym_name(sym
);
2498 if (strstart(name
, OP_PREFIX
, NULL
)) {
2499 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2500 if (sym
->st_shndx
!= text_shndx
)
2501 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2503 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 0);
2508 /* generate big code generation switch */
2511 /* We need to know the size of all the ops so we can figure out when
2512 to emit constant pools. This must be consistent with opc.h. */
2514 "static const uint32_t arm_opc_size[] = {\n"
2519 " 0,\n"); /* nop3 */
2520 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2522 name
= get_sym_name(sym
);
2523 if (strstart(name
, OP_PREFIX
, NULL
)) {
2524 fprintf(outfile
, " %d,\n", sym
->st_size
);
2532 "int dyngen_code(uint8_t *gen_code_buf,\n"
2533 " uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2534 " const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2536 " uint8_t *gen_code_ptr;\n"
2537 " const uint16_t *opc_ptr;\n"
2538 " const uint32_t *opparam_ptr;\n");
2541 /* Arm is tricky because it uses constant pools for loading immediate values.
2542 We assume (and require) each function is code followed by a constant pool.
2543 All the ops are small so this should be ok. For each op we figure
2544 out how much "spare" range we have in the load instructions. This allows
2545 us to insert subsequent ops in between the op and the constant pool,
2546 eliminating the neeed to jump around the pool.
2548 We currently generate:
2550 [ For this example we assume merging would move op1_pool out of range.
2551 In practice we should be able to combine many ops before the offset
2552 limits are reached. ]
2563 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2566 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2567 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2568 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2569 /* Initialise the parmissible pool offset to an arbitary large value. */
2570 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2574 long addend
, not_first
= 0;
2575 unsigned long sym_idx
;
2576 int index
, max_index
;
2577 const char *sym_name
;
2581 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2582 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2583 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2584 if (strstart(sym_name
, "__op_gen_label", NULL
))
2586 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2589 addend
= rel
->r_addend
;
2590 index
= get_plt_index(sym_name
, addend
);
2591 if (index
<= max_index
)
2594 fprintf(outfile
, " extern void %s(void);\n", sym_name
);
2598 " struct ia64_fixup *plt_fixes = NULL, "
2599 "*ltoff_fixes = NULL;\n"
2600 " static long plt_target[] = {\n\t");
2603 for (i
= 0, rel
= relocs
;i
< nb_relocs
; i
++, rel
++) {
2604 sym_idx
= ELF64_R_SYM(rel
->r_info
);
2605 sym_name
= (strtab
+ symtab
[sym_idx
].st_name
);
2606 if (strstart(sym_name
, "__op_gen_label", NULL
))
2608 if (ELF64_R_TYPE(rel
->r_info
) != R_IA64_PCREL21B
)
2611 addend
= rel
->r_addend
;
2612 index
= get_plt_index(sym_name
, addend
);
2613 if (index
<= max_index
)
2618 fprintf(outfile
, ",\n\t");
2621 fprintf(outfile
, "(long) &%s + %ld", sym_name
, addend
);
2623 fprintf(outfile
, "(long) &%s", sym_name
);
2625 fprintf(outfile
, "\n };\n"
2626 " unsigned int plt_offset[%u] = { 0 };\n", max_index
+ 1);
2632 " gen_code_ptr = gen_code_buf;\n"
2633 " opc_ptr = opc_buf;\n"
2634 " opparam_ptr = opparam_buf;\n");
2636 /* Generate prologue, if needed. */
2642 /* Generate constant pool if needed */
2644 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2645 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2646 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2647 " last_gen_code_ptr = gen_code_ptr;\n"
2648 " arm_ldr_ptr = arm_ldr_table;\n"
2649 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2650 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2655 " switch(*opc_ptr++) {\n");
2657 for(i
= 0, sym
= symtab
; i
< nb_syms
; i
++, sym
++) {
2659 name
= get_sym_name(sym
);
2660 if (strstart(name
, OP_PREFIX
, NULL
)) {
2662 printf("%4d: %s pos=0x%08x len=%d\n",
2663 i
, name
, sym
->st_value
, sym
->st_size
);
2665 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2666 if (sym
->st_shndx
!= text_shndx
)
2667 error("invalid section for opcode (0x%x)", sym
->st_shndx
);
2669 gen_code(name
, sym
->st_value
, sym
->st_size
, outfile
, 1);
2674 " case INDEX_op_nop:\n"
2676 " case INDEX_op_nop1:\n"
2679 " case INDEX_op_nop2:\n"
2680 " opparam_ptr += 2;\n"
2682 " case INDEX_op_nop3:\n"
2683 " opparam_ptr += 3;\n"
2697 " extern char code_gen_buffer[];\n"
2698 " ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2699 "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2700 "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2701 "plt_target, plt_offset);\n }\n");
2704 /* generate some code patching */
2707 "if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2708 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2709 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2711 /* flush instruction cache */
2712 fprintf(outfile
, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2714 fprintf(outfile
, "return gen_code_ptr - gen_code_buf;\n");
2715 fprintf(outfile
, "}\n\n");
2724 printf("dyngen (c) 2003 Fabrice Bellard\n"
2725 "usage: dyngen [-o outfile] [-c] objfile\n"
2726 "Generate a dynamic code generator from an object file\n"
2727 "-c output enum of operations\n"
2728 "-g output gen_op_xx() functions\n"
2733 int main(int argc
, char **argv
)
2736 const char *filename
, *outfilename
;
2739 outfilename
= "out.c";
2740 out_type
= OUT_CODE
;
2742 c
= getopt(argc
, argv
, "ho:cg");
2750 outfilename
= optarg
;
2753 out_type
= OUT_INDEX_OP
;
2756 out_type
= OUT_GEN_OP
;
2762 filename
= argv
[optind
];
2763 outfile
= fopen(outfilename
, "w");
2765 error("could not open '%s'", outfilename
);
2767 load_object(filename
);
2768 gen_file(outfile
, out_type
);