Treat DNS a special case among special addresses in slirp (Jason Wessel).
[qemu/mini2440/sniper_sniper_test.git] / dyngen.c
blob369d819a9d29df8043f7daf9ef9fd7b3d8ff530c
1 /*
2 * Generic Dynamic compiler generator
4 * Copyright (c) 2003 Fabrice Bellard
6 * The COFF object format support was extracted from Kazu's QEMU port
7 * to Win32.
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.
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <inttypes.h>
30 #include <unistd.h>
31 #include <fcntl.h>
33 #include "config-host.h"
35 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
36 compilation */
37 #if defined(CONFIG_WIN32)
38 #define CONFIG_FORMAT_COFF
39 #elif defined(CONFIG_DARWIN)
40 #define CONFIG_FORMAT_MACH
41 #else
42 #define CONFIG_FORMAT_ELF
43 #endif
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
49 platform) */
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
142 #else
143 #error unsupported CPU - please update the code
144 #endif
146 #include "elf.h"
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)
153 #else
154 typedef int64_t host_long;
155 typedef uint64_t host_ulong;
156 #define swabls(x) swab64s(x)
157 #define swablss(x) swab64ss(x)
158 #endif
160 #ifdef ELF_USES_RELOCA
161 #define SHT_RELOC SHT_RELA
162 #else
163 #define SHT_RELOC SHT_REL
164 #endif
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;
176 #include "a.out.h"
178 #define FILENAMELEN 256
180 typedef struct coff_sym {
181 struct external_syment *st_syment;
182 char st_name[FILENAMELEN];
183 uint32_t st_value;
184 int st_size;
185 uint8_t st_type;
186 uint8_t st_shndx;
187 } coff_Sym;
189 typedef struct coff_rel {
190 struct external_reloc *r_reloc;
191 int r_offset;
192 uint8_t r_type;
193 } coff_Rel;
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
213 union {
214 char *n_name;
215 long n_strx;
216 } n_un;
217 unsigned char n_type;
218 unsigned char n_sect;
219 short st_desc;
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 */
229 #include "bswap.h"
231 enum {
232 OUT_GEN_OP,
233 OUT_CODE,
234 OUT_INDEX_OP,
237 /* all dynamically generated functions begin with this code */
238 #define OP_PREFIX "op_"
240 int do_swap;
242 static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
244 va_list ap;
245 va_start(ap, fmt);
246 fprintf(stderr, "dyngen: ");
247 vfprintf(stderr, fmt, ap);
248 fprintf(stderr, "\n");
249 va_end(ap);
250 exit(1);
253 static void *load_data(int fd, long offset, unsigned int size)
255 char *data;
257 data = malloc(size);
258 if (!data)
259 return NULL;
260 lseek(fd, offset, SEEK_SET);
261 if (read(fd, data, size) != size) {
262 free(data);
263 return NULL;
265 return data;
268 int strstart(const char *str, const char *val, const char **ptr)
270 const char *p, *q;
271 p = str;
272 q = val;
273 while (*q != '\0') {
274 if (*p != *q)
275 return 0;
276 p++;
277 q++;
279 if (ptr)
280 *ptr = p;
281 return 1;
284 void pstrcpy(char *buf, int buf_size, const char *str)
286 int c;
287 char *q = buf;
289 if (buf_size <= 0)
290 return;
292 for(;;) {
293 c = *str++;
294 if (c == 0 || q >= buf + buf_size - 1)
295 break;
296 *q++ = c;
298 *q = '\0';
301 void swab16s(uint16_t *p)
303 *p = bswap16(*p);
306 void swab32s(uint32_t *p)
308 *p = bswap32(*p);
311 void swab32ss(int32_t *p)
313 *p = bswap32(*p);
316 void swab64s(uint64_t *p)
318 *p = bswap64(*p);
321 void swab64ss(int64_t *p)
323 *p = bswap64(*p);
326 uint16_t get16(uint16_t *p)
328 uint16_t val;
329 val = *p;
330 if (do_swap)
331 val = bswap16(val);
332 return val;
335 uint32_t get32(uint32_t *p)
337 uint32_t val;
338 val = *p;
339 if (do_swap)
340 val = bswap32(val);
341 return val;
344 void put16(uint16_t *p, uint16_t val)
346 if (do_swap)
347 val = bswap16(val);
348 *p = val;
351 void put32(uint32_t *p, uint32_t val)
353 if (do_swap)
354 val = bswap32(val);
355 *p = val;
358 /* executable information */
359 EXE_SYM *symtab;
360 int nb_syms;
361 int text_shndx;
362 uint8_t *text;
363 EXE_RELOC *relocs;
364 int nb_relocs;
366 #ifdef CONFIG_FORMAT_ELF
368 /* ELF file info */
369 struct elf_shdr *shdr;
370 uint8_t **sdata;
371 struct elfhdr ehdr;
372 char *strtab;
374 int elf_must_swap(struct elfhdr *h)
376 union {
377 uint32_t i;
378 uint8_t b[4];
379 } swaptest;
381 swaptest.i = 1;
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);
435 #endif
438 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
439 const char *name)
441 int i;
442 const char *shname;
443 struct elf_shdr *sec;
445 for(i = 0; i < shnum; i++) {
446 sec = &shdr[i];
447 if (!sec->sh_name)
448 continue;
449 shname = shstr + sec->sh_name;
450 if (!strcmp(shname, name))
451 return sec;
453 return NULL;
456 int find_reloc(int sh_index)
458 struct elf_shdr *sec;
459 int i;
461 for(i = 0; i < ehdr.e_shnum; i++) {
462 sec = &shdr[i];
463 if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
464 return i;
466 return 0;
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)
487 int fd;
488 struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
489 int i, j;
490 ElfW(Sym) *sym;
491 char *shstr;
492 ELF_RELOC *rel;
494 fd = open(filename, O_RDONLY);
495 if (fd < 0)
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);
512 if (do_swap)
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));
525 if (do_swap) {
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++) {
536 sec = &shdr[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++) {
546 sec = &shdr[i];
547 if (sec->sh_type == SHT_RELOC) {
548 nb_relocs = sec->sh_size / sec->sh_entsize;
549 if (do_swap) {
550 for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
551 elf_swap_rel(rel);
555 /* text section */
557 text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
558 if (!text_sec)
559 error("could not find .text section");
560 text_shndx = text_sec - shdr;
561 text = sdata[text_shndx];
563 /* find text relocations, if any */
564 relocs = NULL;
565 nb_relocs = 0;
566 i = find_reloc(text_shndx);
567 if (i != 0) {
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");
573 if (!symtab_sec)
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));
581 if (do_swap) {
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);
589 close(fd);
590 return 0;
593 #endif /* CONFIG_FORMAT_ELF */
595 #ifdef CONFIG_FORMAT_COFF
597 /* COFF file info */
598 struct external_scnhdr *shdr;
599 uint8_t **sdata;
600 struct external_filehdr fhdr;
601 struct external_syment *coff_symtab;
602 char *strtab;
603 int coff_text_shndx, coff_data_shndx;
605 int data_shndx;
607 #define STRTAB_SIZE 4
609 #define DIR32 0x06
610 #define DISP32 0x14
612 #define T_FUNCTION 0x20
613 #define C_EXTERNAL 2
615 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
617 char *q;
618 int c, i, len;
620 if (ext_sym->e.e.e_zeroes != 0) {
621 q = sym->st_name;
622 for(i = 0; i < 8; i++) {
623 c = ext_sym->e.e_name[i];
624 if (c == '\0')
625 break;
626 *q++ = c;
628 *q = '\0';
629 } else {
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)
643 int i;
644 struct coff_sym *sym;
645 uint32_t text_data;
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) {
654 return sym->st_name;
658 return NULL;
661 static char *get_sym_name(EXE_SYM *sym)
663 return sym->st_name;
666 static char *get_rel_sym_name(EXE_RELOC *rel)
668 char *name;
669 name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
670 if (!strcmp(name, ".data"))
671 name = name_for_dotdata(rel);
672 if (name[0] == '.')
673 return NULL;
674 return name;
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)
684 int i;
685 const char *shname;
686 struct external_scnhdr *sec;
688 for(i = 0; i < shnum; i++) {
689 sec = &shdr[i];
690 if (!sec->s_name)
691 continue;
692 shname = sec->s_name;
693 if (!strcmp(shname, name))
694 return sec;
696 return NULL;
699 /* load a coff object file */
700 int load_object(const char *filename)
702 int fd;
703 struct external_scnhdr *sec, *text_sec, *data_sec;
704 int i;
705 struct external_syment *ext_sym;
706 struct external_reloc *coff_relocs;
707 struct external_reloc *ext_rel;
708 uint32_t *n_strtab;
709 EXE_SYM *sym;
710 EXE_RELOC *rel;
711 const char *p;
712 int aux_size, j;
714 fd = open(filename, O_RDONLY
715 #ifdef _WIN32
716 | O_BINARY
717 #endif
719 if (fd < 0)
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");
730 do_swap = 0;
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++) {
740 sec = &shdr[i];
741 if (!strstart(sec->s_name, ".bss", &p))
742 sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
746 /* text section */
747 text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
748 if (!text_sec)
749 error("could not find .text section");
750 coff_text_shndx = text_sec - shdr;
751 text = sdata[coff_text_shndx];
753 /* data section */
754 data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
755 if (!data_sec)
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++) {
761 for(i=0;i<8;i++)
762 printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
763 printf("\n");
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;
794 break;
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;
798 break;
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;
805 break;
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;
809 break;
812 } else {
813 sym->st_size = 0;
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;
835 return 0;
838 #endif /* CONFIG_FORMAT_COFF */
840 #ifdef CONFIG_FORMAT_MACH
842 /* File Header */
843 struct mach_header mach_hdr;
845 /* commands */
846 struct segment_command *segment = 0;
847 struct dysymtab_command *dysymtabcmd = 0;
848 struct symtab_command *symtabcmd = 0;
850 /* section */
851 struct section *section_hdr;
852 struct section *text_sec_hdr;
853 uint8_t **sdata;
855 /* relocs */
856 struct relocation_info *relocs;
858 /* symbols */
859 EXE_SYM *symtab;
860 struct nlist *symtab_std;
861 char *strtab;
863 /* indirect symbols */
864 uint32_t *tocdylib;
866 /* Utility functions */
868 static inline char *find_str_by_index(int index)
870 return strtab+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 */
879 return "debug";
881 if(!name)
882 return name;
883 if(name[0]=='_')
884 return name + 1;
885 else
886 return name;
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)
893 int i;
894 struct section *sec = section_hdr;
896 for(i = 0; i < shnum; i++, sec++) {
897 if (!sec->segname || !sec->sectname)
898 continue;
899 if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
900 return i;
902 return -1;
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);
910 if(index == -1)
911 return NULL;
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;
925 } else {
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 )
935 int i, ret = -1;
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) )
943 ret = i;
946 if( ret < 0 ) {
947 *offset = 0;
948 return 0;
949 } else {
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;
964 /* Sanity check */
965 if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
966 return (char*)0;
968 if( sec_hdr->flags & S_SYMBOL_STUBS ){
969 size = sec_hdr->reserved2;
970 if(size == 0)
971 error("size = 0");
974 else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
975 sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
976 size = sizeof(unsigned long);
977 else
978 return 0;
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]);
986 return name;
989 static const char * find_reloc_name_given_its_address(int address)
991 unsigned int i;
992 for(i = 0; i < segment->nsects ; i++)
994 const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
995 if((long)name != -1)
996 return name;
998 return 0;
1001 static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
1003 char * name = 0;
1004 struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1005 int sectnum = rel->r_symbolnum;
1006 int sectoffset;
1007 int other_half=0;
1009 /* init the slide value */
1010 *sslide = 0;
1012 if(R_SCATTERED & rel->r_address)
1013 return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1015 if(rel->r_extern)
1017 /* ignore debug sym */
1018 if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1019 return 0;
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)
1027 return 0;
1029 /* Sanity Check */
1030 if(sectnum > segment->nsects)
1031 error("sectnum > segment->nsects");
1033 switch(rel->r_type)
1035 case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1036 break;
1037 case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1038 break;
1039 case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1040 break;
1041 case PPC_RELOC_BR24:
1042 sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1043 if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1044 break;
1045 default:
1046 error("switch(rel->type) not found");
1049 if(rel->r_pcrel)
1050 sectoffset += rel->r_address;
1052 if (rel->r_type == PPC_RELOC_BR24)
1053 name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1055 /* search it in the full symbol list, if not found */
1056 if(!name)
1057 name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1059 return name;
1062 /* Used by dyngen common code */
1063 static const char * get_rel_sym_name(EXE_RELOC * rel)
1065 int sslide;
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;
1075 else
1076 return rel->r_address;
1079 /* load a mach-o object file */
1080 int load_object(const char *filename)
1082 int fd;
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;
1087 unsigned int i, j;
1088 EXE_SYM *sym;
1089 struct nlist *syment;
1091 fd = open(filename, O_RDONLY);
1092 if (fd < 0)
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");
1139 j+=lc.cmdsize;
1141 lseek(fd, j, SEEK_SET);
1144 if(!segment)
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);
1159 /* text section */
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");
1164 text = sdata[i];
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 */
1174 if(!(int)symtabcmd)
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;
1186 unsigned int j;
1187 memset(sym, 0, sizeof(*sym));
1189 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1190 continue;
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))
1197 continue;
1198 if(!sym_next) {
1199 sym_next = sym_follow;
1200 continue;
1202 if(!(sym_next->n_value > sym_follow->n_value))
1203 continue;
1204 sym_next = sym_follow;
1206 if(sym_next)
1207 sym->st_size = sym_next->n_value - sym->st_value;
1208 else
1209 sym->st_size = text_sec_hdr->size - sym->st_value;
1212 /* Find Reloc */
1213 relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1214 nb_relocs = text_sec_hdr->nreloc;
1216 close(fd);
1217 return 0;
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)
1225 const char *p;
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);
1231 return 1;
1232 } else {
1233 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1234 if (sym_name[0] == '.')
1235 snprintf(name, name_size,
1236 "(long)(&__dot_%s)",
1237 sym_name + 1);
1238 else
1239 #endif
1240 snprintf(name, name_size, "(long)(&%s)", sym_name);
1242 return 0;
1245 #ifdef HOST_IA64
1247 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1249 struct plt_entry {
1250 struct plt_entry *next;
1251 const char *name;
1252 unsigned long addend;
1253 } *plt_list;
1255 static int
1256 get_plt_index (const char *name, unsigned long addend)
1258 struct plt_entry *plt, *prev= NULL;
1259 int index = 0;
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)
1264 return index;
1266 /* nope; create a new PLT entry: */
1268 plt = malloc(sizeof(*plt));
1269 if (!plt) {
1270 perror("malloc");
1271 exit(1);
1273 memset(plt, 0, sizeof(*plt));
1274 plt->name = strdup(name);
1275 plt->addend = addend;
1277 /* append to plt-list: */
1278 if (prev)
1279 prev->next = plt;
1280 else
1281 plt_list = plt;
1282 return index;
1285 #endif
1287 #ifdef HOST_ARM
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)
1293 uint8_t *p;
1294 uint32_t insn;
1295 int offset, min_offset, pc_offset, data_size, spare, max_pool;
1296 uint8_t data_allocated[1024];
1297 unsigned int data_index;
1298 int type;
1300 memset(data_allocated, 0, sizeof(data_allocated));
1302 p = p_start;
1303 min_offset = p_end - p_start;
1304 spare = 0x7fffffff;
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))
1313 offset = -offset;
1314 max_pool = 4096;
1315 type = 0;
1316 } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1317 /* FPA ldf. */
1318 offset = (insn & 0xff) << 2;
1319 if (!(insn & 0x00800000))
1320 offset = -offset;
1321 max_pool = 1024;
1322 type = 1;
1323 } else if ((insn & 0x0fff0000) == 0x028f0000) {
1324 /* Some gcc load a doubleword immediate with
1325 add regN, pc, #imm
1326 ldmia regN, {regN, regM}
1327 Hope and pray the compiler never generates somethin like
1328 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1329 int r;
1331 r = (insn & 0xf00) >> 7;
1332 offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1333 max_pool = 1024;
1334 type = 2;
1335 } else {
1336 max_pool = 0;
1337 type = -1;
1339 if (type >= 0) {
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);
1346 if (offset < 0)
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;
1356 if (outfile) {
1357 /* The intruction position */
1358 fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1359 p - p_start);
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",
1363 data_index);
1364 fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
1365 fprintf(outfile, " arm_ldr_ptr++;\n");
1368 p += 4;
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",
1379 spare, spare);
1381 data_index = 0;
1382 for (pc_offset = min_offset;
1383 pc_offset < p_end - p_start;
1384 pc_offset += 4) {
1386 ELF_RELOC *rel;
1387 int i, addend, type;
1388 const char *sym_name;
1389 char relname[1024];
1391 /* data value */
1392 addend = get32((uint32_t *)(p_start + pc_offset));
1393 relname[0] = '\0';
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);
1402 break;
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");
1411 data_index++;
1415 if (p == p_start)
1416 goto arm_ret_error;
1417 p -= 4;
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)
1422 ldmia sp, {..., pc}
1423 ldmea fp, {..., pc} */
1424 if ((insn & 0xffff8000) == 0xe99d8000) {
1425 if (outfile) {
1426 fprintf(outfile,
1427 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1428 p - p_start);
1430 p += 4;
1431 } else if ((insn & 0xffff8000) != 0xe89d8000
1432 && (insn & 0xffff8000) != 0xe91b8000) {
1433 arm_ret_error:
1434 if (!outfile)
1435 printf("%s: invalid epilog\n", name);
1437 return p - p_start;
1439 #endif
1442 #define MAX_ARGS 3
1444 /* generate op code */
1445 void gen_code(const char *name, host_ulong offset, host_ulong size,
1446 FILE *outfile, int gen_switch)
1448 int copy_size = 0;
1449 uint8_t *p_start, *p_end;
1450 host_ulong start_offset;
1451 int nb_args, i, n;
1452 uint8_t args_present[MAX_ARGS];
1453 const char *sym_name, *p;
1454 EXE_RELOC *rel;
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
1459 * bytes).
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
1467 uint8_t *p;
1468 p = p_end - 1;
1469 if (p == p_start)
1470 error("empty code for %s", name);
1471 while (*p != 0xc3) {
1472 p--;
1473 if (p <= p_start)
1474 error("ret or jmp expected at the end of %s", name);
1476 copy_size = p - p_start;
1478 #else
1480 int len;
1481 len = p_end - p_start;
1482 if (len == 0)
1483 error("empty code for %s", name);
1484 if (p_end[-1] == 0xc3) {
1485 len--;
1486 } else {
1487 error("ret or jmp expected at the end of %s", name);
1489 copy_size = len;
1491 #endif
1492 #elif defined(HOST_PPC)
1494 uint8_t *p;
1495 p = (void *)(p_end - 4);
1496 if (p == p_start)
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)
1504 uint8_t *p;
1505 p = (void *)(p_end - 2);
1506 if (p == p_start)
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)
1514 uint8_t *p;
1515 p = p_end - 4;
1516 #if 0
1517 /* XXX: check why it occurs */
1518 if (p == p_start)
1519 error("empty code for %s", name);
1520 #endif
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)
1527 uint8_t *p;
1528 p = (void *)(p_end - 4);
1529 if (p == p_start)
1530 error("empty code for %s", name);
1531 /* br.ret.sptk.many b0;; */
1532 /* 08 00 84 00 */
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;
1549 uint8_t *p;
1550 p = (void *)(p_end - 8);
1551 if (p <= p_start)
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) {
1558 p_start += 0x4;
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; */ ;
1566 else
1568 error("ret; restore; not found at end of %s", name);
1569 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1571 } else {
1572 error("No save at the beginning of %s", name);
1574 #if 0
1575 /* Skip a preceeding nop, if present. */
1576 if (p > p_start) {
1577 skip_insn = get32((uint32_t *)(p - 0x4));
1578 if (skip_insn == INSN_NOP)
1579 p -= 4;
1581 #endif
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;
1596 uint8_t *p;
1597 p = (void *)(p_end - 8);
1598 #if 0
1599 /* XXX: check why it occurs */
1600 if (p <= p_start)
1601 error("empty code for %s", name);
1602 #endif
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) {
1608 p_start += 0x4;
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; */ ;
1616 else
1618 error("ret; restore; not found at end of %s", name);
1619 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1621 } else {
1622 error("No save at the beginning of %s", name);
1625 #if 0
1626 /* Skip a preceeding nop, if present. */
1627 if (p > p_start) {
1628 skip_insn = get32((uint32_t *)(p - 0x4));
1629 if (skip_insn == 0x01000000)
1630 p -= 4;
1632 #endif
1634 copy_size = p - p_start;
1636 #elif defined(HOST_ARM)
1638 uint32_t insn;
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);
1646 p_start += 12;
1647 start_offset += 12;
1648 insn = get32((uint32_t *)p_start);
1649 if ((insn & 0xffffff00) == 0xe24dd000) {
1650 /* Stack adjustment. Assume op uses the frame pointer. */
1651 p_start -= 4;
1652 start_offset -= 4;
1654 copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1655 relocs, nb_relocs);
1657 #elif defined(HOST_M68K)
1659 uint8_t *p;
1660 p = (void *)(p_end - 2);
1661 if (p == p_start)
1662 error("empty code for %s", name);
1663 // remove NOP's, probably added for alignment
1664 while ((get16((uint16_t *)p) == 0x4e71) &&
1665 (p>p_start))
1666 p -= 2;
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)
1673 uint8_t *p;
1674 p = p_start;
1675 while (p < p_end) {
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) */
1682 p += 4;
1683 else
1684 break;
1686 start_offset += p - p_start;
1687 p_start = p;
1688 p = p_end - 4;
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) */
1698 p -= 4;
1699 else
1700 break;
1702 p += 4;
1703 if (p <= p_start)
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
1713 uint8_t *p = p_end;
1715 if (p < (p_start + 0x8)) {
1716 error("empty code for %s", name);
1717 } else {
1718 uint32_t end_insn1, end_insn2;
1720 p -= 0x8;
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;
1728 #else
1729 #error unsupported CPU
1730 #endif
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);
1741 if(!sym_name)
1742 continue;
1743 if (strstart(sym_name, "__op_param", &p) ||
1744 strstart(sym_name, "__op_gen_label", &p)) {
1745 n = strtoul(p, NULL, 10);
1746 if (n > MAX_ARGS)
1747 error("too many arguments in %s", name);
1748 args_present[n - 1] = 1;
1753 nb_args = 0;
1754 while (nb_args < MAX_ARGS && args_present[nb_args])
1755 nb_args++;
1756 for(i = nb_args; i < MAX_ARGS; i++) {
1757 if (args_present[i])
1758 error("inconsistent argument numbering in %s", name);
1761 if (gen_switch == 2) {
1763 #if defined(HOST_HPPA)
1764 int op_size = copy_size;
1765 int has_stubs = 0;
1766 char relname[256];
1767 int type, is_label;
1769 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1770 if (rel->r_offset >= start_offset &&
1771 rel->r_offset < start_offset + copy_size) {
1772 sym_name = get_rel_sym_name(rel);
1773 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
1774 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1775 type = ELF32_R_TYPE(rel->r_info);
1777 if (!is_label && type == R_PARISC_PCREL17F) {
1778 has_stubs = 1;
1779 op_size += 8; /* ldil and be,n instructions */
1784 if (has_stubs)
1785 op_size += 4; /* b,l,n instruction, to skip past the stubs */
1787 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, op_size);
1788 #else
1789 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1790 #endif
1792 } else if (gen_switch == 1) {
1794 /* output C code */
1795 fprintf(outfile, "case INDEX_%s: {\n", name);
1796 if (nb_args > 0) {
1797 fprintf(outfile, " long ");
1798 for(i = 0; i < nb_args; i++) {
1799 if (i != 0)
1800 fprintf(outfile, ", ");
1801 fprintf(outfile, "param%d", i + 1);
1803 fprintf(outfile, ";\n");
1805 #if defined(HOST_IA64)
1806 fprintf(outfile, " extern char %s;\n", name);
1807 #else
1808 fprintf(outfile, " extern void %s();\n", name);
1809 #endif
1811 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1812 host_ulong offset = get_rel_offset(rel);
1813 if (offset >= start_offset &&
1814 offset < start_offset + (p_end - p_start)) {
1815 sym_name = get_rel_sym_name(rel);
1816 if(!sym_name)
1817 continue;
1818 if (*sym_name &&
1819 !strstart(sym_name, "__op_param", NULL) &&
1820 !strstart(sym_name, "__op_jmp", NULL) &&
1821 !strstart(sym_name, "__op_gen_label", NULL)) {
1822 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1823 if (sym_name[0] == '.') {
1824 fprintf(outfile,
1825 "extern char __dot_%s __asm__(\"%s\");\n",
1826 sym_name+1, sym_name);
1827 continue;
1829 #endif
1830 #if defined(__APPLE__)
1831 /* Set __attribute((unused)) on darwin because we
1832 want to avoid warning when we don't use the symbol. */
1833 fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name);
1834 #elif defined(HOST_IA64)
1835 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1837 * PCREL21 br.call targets generally
1838 * are out of range and need to go
1839 * through an "import stub".
1841 fprintf(outfile, " extern char %s;\n",
1842 sym_name);
1843 #else
1844 fprintf(outfile, "extern char %s;\n", sym_name);
1845 #endif
1850 #ifdef __hppa__
1851 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1852 name, (int)(start_offset - offset), copy_size);
1853 #else
1854 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1855 name, (int)(start_offset - offset), copy_size);
1856 #endif
1858 /* emit code offset information */
1860 EXE_SYM *sym;
1861 const char *sym_name, *p;
1862 host_ulong val;
1863 int n;
1865 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1866 sym_name = get_sym_name(sym);
1867 if (strstart(sym_name, "__op_label", &p)) {
1868 uint8_t *ptr;
1869 unsigned long offset;
1871 /* test if the variable refers to a label inside
1872 the code we are generating */
1873 #ifdef CONFIG_FORMAT_COFF
1874 if (sym->st_shndx == text_shndx) {
1875 ptr = sdata[coff_text_shndx];
1876 } else if (sym->st_shndx == data_shndx) {
1877 ptr = sdata[coff_data_shndx];
1878 } else {
1879 ptr = NULL;
1881 #elif defined(CONFIG_FORMAT_MACH)
1882 if(!sym->n_sect)
1883 continue;
1884 ptr = sdata[sym->n_sect-1];
1885 #else
1886 ptr = sdata[sym->st_shndx];
1887 #endif
1888 if (!ptr)
1889 error("__op_labelN in invalid section");
1890 offset = sym->st_value;
1891 #ifdef CONFIG_FORMAT_MACH
1892 offset -= section_hdr[sym->n_sect-1].addr;
1893 #endif
1894 val = *(host_ulong *)(ptr + offset);
1895 #ifdef ELF_USES_RELOCA
1897 int reloc_shndx, nb_relocs1, j;
1899 /* try to find a matching relocation */
1900 reloc_shndx = find_reloc(sym->st_shndx);
1901 if (reloc_shndx) {
1902 nb_relocs1 = shdr[reloc_shndx].sh_size /
1903 shdr[reloc_shndx].sh_entsize;
1904 rel = (ELF_RELOC *)sdata[reloc_shndx];
1905 for(j = 0; j < nb_relocs1; j++) {
1906 if (rel->r_offset == offset) {
1907 val = rel->r_addend;
1908 break;
1910 rel++;
1914 #endif
1915 if (val >= start_offset && val <= start_offset + copy_size) {
1916 n = strtol(p, NULL, 10);
1917 fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1923 /* load parameters in variables */
1924 for(i = 0; i < nb_args; i++) {
1925 fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
1928 /* patch relocations */
1929 #if defined(HOST_I386)
1931 char relname[256];
1932 int type, is_label;
1933 int addend;
1934 int reloc_offset;
1935 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1936 if (rel->r_offset >= start_offset &&
1937 rel->r_offset < start_offset + copy_size) {
1938 sym_name = get_rel_sym_name(rel);
1939 if (!sym_name)
1940 continue;
1941 reloc_offset = rel->r_offset - start_offset;
1942 if (strstart(sym_name, "__op_jmp", &p)) {
1943 int n;
1944 n = strtol(p, NULL, 10);
1945 /* __op_jmp relocations are done at
1946 runtime to do translated block
1947 chaining: the offset of the instruction
1948 needs to be stored */
1949 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1950 n, reloc_offset);
1951 continue;
1954 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1955 addend = get32((uint32_t *)(text + rel->r_offset));
1956 #ifdef CONFIG_FORMAT_ELF
1957 type = ELF32_R_TYPE(rel->r_info);
1958 if (is_label) {
1959 switch(type) {
1960 case R_386_32:
1961 case R_386_PC32:
1962 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1963 reloc_offset, type, relname, addend);
1964 break;
1965 default:
1966 error("unsupported i386 relocation (%d)", type);
1968 } else {
1969 switch(type) {
1970 case R_386_32:
1971 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1972 reloc_offset, relname, addend);
1973 break;
1974 case R_386_PC32:
1975 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1976 reloc_offset, relname, reloc_offset, addend);
1977 break;
1978 default:
1979 error("unsupported i386 relocation (%d)", type);
1982 #elif defined(CONFIG_FORMAT_COFF)
1984 char *temp_name;
1985 int j;
1986 EXE_SYM *sym;
1987 temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1988 if (!strcmp(temp_name, ".data")) {
1989 for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1990 if (strstart(sym->st_name, sym_name, NULL)) {
1991 addend -= sym->st_value;
1996 type = rel->r_type;
1997 if (is_label) {
1998 /* TCG uses elf relocation constants */
1999 #define R_386_32 1
2000 #define R_386_PC32 2
2001 switch(type) {
2002 case DIR32:
2003 type = R_386_32;
2004 goto do_reloc;
2005 case DISP32:
2006 type = R_386_PC32;
2007 addend -= 4;
2008 do_reloc:
2009 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2010 reloc_offset, type, relname, addend);
2011 break;
2012 default:
2013 error("unsupported i386 relocation (%d)", type);
2015 } else {
2016 switch(type) {
2017 case DIR32:
2018 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2019 reloc_offset, relname, addend);
2020 break;
2021 case DISP32:
2022 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
2023 reloc_offset, relname, reloc_offset, addend);
2024 break;
2025 default:
2026 error("unsupported i386 relocation (%d)", type);
2029 #else
2030 #error unsupport object format
2031 #endif
2035 #elif defined(HOST_X86_64)
2037 char relname[256];
2038 int type, is_label;
2039 int addend;
2040 int reloc_offset;
2041 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2042 if (rel->r_offset >= start_offset &&
2043 rel->r_offset < start_offset + copy_size) {
2044 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2045 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2046 type = ELF32_R_TYPE(rel->r_info);
2047 addend = rel->r_addend;
2048 reloc_offset = rel->r_offset - start_offset;
2049 if (is_label) {
2050 switch(type) {
2051 case R_X86_64_32:
2052 case R_X86_64_32S:
2053 case R_X86_64_PC32:
2054 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2055 reloc_offset, type, relname, addend);
2056 break;
2057 default:
2058 error("unsupported X86_64 relocation (%d)", type);
2060 } else {
2061 switch(type) {
2062 case R_X86_64_32:
2063 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2064 reloc_offset, relname, addend);
2065 break;
2066 case R_X86_64_32S:
2067 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2068 reloc_offset, relname, addend);
2069 break;
2070 case R_X86_64_PC32:
2071 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2072 reloc_offset, relname, reloc_offset, addend);
2073 break;
2074 default:
2075 error("unsupported X86_64 relocation (%d)", type);
2081 #elif defined(HOST_PPC)
2083 #ifdef CONFIG_FORMAT_ELF
2084 char relname[256];
2085 int type;
2086 int addend;
2087 int reloc_offset;
2088 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2089 if (rel->r_offset >= start_offset &&
2090 rel->r_offset < start_offset + copy_size) {
2091 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2092 reloc_offset = rel->r_offset - start_offset;
2093 if (strstart(sym_name, "__op_jmp", &p)) {
2094 int n;
2095 n = strtol(p, NULL, 10);
2096 /* __op_jmp relocations are done at
2097 runtime to do translated block
2098 chaining: the offset of the instruction
2099 needs to be stored */
2100 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2101 n, reloc_offset);
2102 continue;
2105 get_reloc_expr(relname, sizeof(relname), sym_name);
2106 type = ELF32_R_TYPE(rel->r_info);
2107 addend = rel->r_addend;
2108 switch(type) {
2109 case R_PPC_ADDR32:
2110 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2111 reloc_offset, relname, addend);
2112 break;
2113 case R_PPC_ADDR16_LO:
2114 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2115 reloc_offset, relname, addend);
2116 break;
2117 case R_PPC_ADDR16_HI:
2118 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2119 reloc_offset, relname, addend);
2120 break;
2121 case R_PPC_ADDR16_HA:
2122 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2123 reloc_offset, relname, addend);
2124 break;
2125 case R_PPC_REL24:
2126 /* warning: must be at 32 MB distancy */
2127 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2128 reloc_offset, reloc_offset, relname, reloc_offset, addend);
2129 break;
2130 default:
2131 error("unsupported powerpc relocation (%d)", type);
2135 #elif defined(CONFIG_FORMAT_MACH)
2136 struct scattered_relocation_info *scarel;
2137 struct relocation_info * rel;
2138 char final_sym_name[256];
2139 const char *sym_name;
2140 const char *p;
2141 int slide, sslide;
2142 int i;
2144 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2145 unsigned int offset, length, value = 0;
2146 unsigned int type, pcrel, isym = 0;
2147 unsigned int usesym = 0;
2149 if(R_SCATTERED & rel->r_address) {
2150 scarel = (struct scattered_relocation_info*)rel;
2151 offset = (unsigned int)scarel->r_address;
2152 length = scarel->r_length;
2153 pcrel = scarel->r_pcrel;
2154 type = scarel->r_type;
2155 value = scarel->r_value;
2156 } else {
2157 value = isym = rel->r_symbolnum;
2158 usesym = (rel->r_extern);
2159 offset = rel->r_address;
2160 length = rel->r_length;
2161 pcrel = rel->r_pcrel;
2162 type = rel->r_type;
2165 slide = offset - start_offset;
2167 if (!(offset >= start_offset && offset < start_offset + size))
2168 continue; /* not in our range */
2170 sym_name = get_reloc_name(rel, &sslide);
2172 if(usesym && symtab[isym].n_type & N_STAB)
2173 continue; /* don't handle STAB (debug sym) */
2175 if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2176 int n;
2177 n = strtol(p, NULL, 10);
2178 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2179 n, slide);
2180 continue; /* Nothing more to do */
2183 if(!sym_name) {
2184 fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2185 name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2186 continue; /* dunno how to handle without final_sym_name */
2189 get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2190 sym_name);
2191 switch(type) {
2192 case PPC_RELOC_BR24:
2193 if (!strstart(sym_name,"__op_gen_label",&p)) {
2194 fprintf(outfile, "{\n");
2195 fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2196 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
2197 slide, slide, name, sslide);
2198 fprintf(outfile, "}\n");
2199 } else {
2200 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2201 slide, slide, final_sym_name, slide);
2203 break;
2204 case PPC_RELOC_HI16:
2205 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2206 slide, final_sym_name, sslide);
2207 break;
2208 case PPC_RELOC_LO16:
2209 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2210 slide, final_sym_name, sslide);
2211 break;
2212 case PPC_RELOC_HA16:
2213 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2214 slide, final_sym_name, sslide);
2215 break;
2216 default:
2217 error("unsupported powerpc relocation (%d)", type);
2220 #else
2221 #error unsupport object format
2222 #endif
2224 #elif defined(HOST_S390)
2226 char relname[256];
2227 int type;
2228 int addend;
2229 int reloc_offset;
2230 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2231 if (rel->r_offset >= start_offset &&
2232 rel->r_offset < start_offset + copy_size) {
2233 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2234 get_reloc_expr(relname, sizeof(relname), sym_name);
2235 type = ELF32_R_TYPE(rel->r_info);
2236 addend = rel->r_addend;
2237 reloc_offset = rel->r_offset - start_offset;
2238 switch(type) {
2239 case R_390_32:
2240 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2241 reloc_offset, relname, addend);
2242 break;
2243 case R_390_16:
2244 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2245 reloc_offset, relname, addend);
2246 break;
2247 case R_390_8:
2248 fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2249 reloc_offset, relname, addend);
2250 break;
2251 case R_390_PC32DBL:
2252 if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2253 fprintf(outfile,
2254 " *(uint32_t *)(gen_code_ptr + %d) += "
2255 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2256 reloc_offset, name);
2258 else
2259 fprintf(outfile,
2260 " *(uint32_t *)(gen_code_ptr + %d) = "
2261 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2262 reloc_offset, relname, addend, reloc_offset);
2263 break;
2264 default:
2265 error("unsupported s390 relocation (%d)", type);
2270 #elif defined(HOST_ALPHA)
2272 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2273 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2274 int type;
2275 long reloc_offset;
2277 type = ELF64_R_TYPE(rel->r_info);
2278 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2279 reloc_offset = rel->r_offset - start_offset;
2280 switch (type) {
2281 case R_ALPHA_GPDISP:
2282 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2283 as an immediate instead of constructing it from the pv or ra. */
2284 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2285 reloc_offset);
2286 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2287 reloc_offset + (int)rel->r_addend);
2288 break;
2289 case R_ALPHA_LITUSE:
2290 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2291 now, since some called functions (libc) need pv to be set up. */
2292 break;
2293 case R_ALPHA_HINT:
2294 /* Branch target prediction hint. Ignore for now. Should be already
2295 correct for in-function jumps. */
2296 break;
2297 case R_ALPHA_LITERAL:
2298 /* Load a literal from the GOT relative to the gp. Since there's only a
2299 single gp, nothing is to be done. */
2300 break;
2301 case R_ALPHA_GPRELHIGH:
2302 /* Handle fake relocations against __op_param symbol. Need to emit the
2303 high part of the immediate value instead. Other symbols need no
2304 special treatment. */
2305 if (strstart(sym_name, "__op_param", &p))
2306 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2307 reloc_offset, p);
2308 break;
2309 case R_ALPHA_GPRELLOW:
2310 if (strstart(sym_name, "__op_param", &p))
2311 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2312 reloc_offset, p);
2313 break;
2314 case R_ALPHA_BRSGP:
2315 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2316 set up the gp from the pv. */
2317 fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2318 reloc_offset, sym_name, reloc_offset);
2319 break;
2320 default:
2321 error("unsupported Alpha relocation (%d)", type);
2326 #elif defined(HOST_IA64)
2328 unsigned long sym_idx;
2329 long code_offset;
2330 char relname[256];
2331 int type;
2332 long addend;
2334 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2335 sym_idx = ELF64_R_SYM(rel->r_info);
2336 if (rel->r_offset < start_offset
2337 || rel->r_offset >= start_offset + copy_size)
2338 continue;
2339 sym_name = (strtab + symtab[sym_idx].st_name);
2340 code_offset = rel->r_offset - start_offset;
2341 if (strstart(sym_name, "__op_jmp", &p)) {
2342 int n;
2343 n = strtol(p, NULL, 10);
2344 /* __op_jmp relocations are done at
2345 runtime to do translated block
2346 chaining: the offset of the instruction
2347 needs to be stored */
2348 fprintf(outfile, " jmp_offsets[%d] ="
2349 "%ld + (gen_code_ptr - gen_code_buf);\n",
2350 n, code_offset);
2351 continue;
2353 get_reloc_expr(relname, sizeof(relname), sym_name);
2354 type = ELF64_R_TYPE(rel->r_info);
2355 addend = rel->r_addend;
2356 switch(type) {
2357 case R_IA64_IMM64:
2358 fprintf(outfile,
2359 " ia64_imm64(gen_code_ptr + %ld, "
2360 "%s + %ld);\n",
2361 code_offset, relname, addend);
2362 break;
2363 case R_IA64_LTOFF22X:
2364 case R_IA64_LTOFF22:
2365 fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
2366 " %s + %ld, %d);\n",
2367 code_offset, relname, addend,
2368 (type == R_IA64_LTOFF22X));
2369 break;
2370 case R_IA64_LDXMOV:
2371 fprintf(outfile,
2372 " ia64_ldxmov(gen_code_ptr + %ld,"
2373 " %s + %ld);\n", code_offset, relname, addend);
2374 break;
2376 case R_IA64_PCREL21B:
2377 if (strstart(sym_name, "__op_gen_label", NULL)) {
2378 fprintf(outfile,
2379 " ia64_imm21b(gen_code_ptr + %ld,"
2380 " (long) (%s + %ld -\n\t\t"
2381 "((long) gen_code_ptr + %ld)) >> 4);\n",
2382 code_offset, relname, addend,
2383 code_offset & ~0xfUL);
2384 } else {
2385 fprintf(outfile,
2386 " IA64_PLT(gen_code_ptr + %ld, "
2387 "%d);\t/* %s + %ld */\n",
2388 code_offset,
2389 get_plt_index(sym_name, addend),
2390 sym_name, addend);
2392 break;
2393 default:
2394 error("unsupported ia64 relocation (0x%x)",
2395 type);
2398 fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2399 copy_size - 16 + 2);
2401 #elif defined(HOST_SPARC)
2403 char relname[256];
2404 int type;
2405 int addend;
2406 int reloc_offset;
2407 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2408 if (rel->r_offset >= start_offset &&
2409 rel->r_offset < start_offset + copy_size) {
2410 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2411 get_reloc_expr(relname, sizeof(relname), sym_name);
2412 type = ELF32_R_TYPE(rel->r_info);
2413 addend = rel->r_addend;
2414 reloc_offset = rel->r_offset - start_offset;
2415 switch(type) {
2416 case R_SPARC_32:
2417 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2418 reloc_offset, relname, addend);
2419 break;
2420 case R_SPARC_HI22:
2421 fprintf(outfile,
2422 " *(uint32_t *)(gen_code_ptr + %d) = "
2423 "((*(uint32_t *)(gen_code_ptr + %d)) "
2424 " & ~0x3fffff) "
2425 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2426 reloc_offset, reloc_offset, relname, addend);
2427 break;
2428 case R_SPARC_LO10:
2429 fprintf(outfile,
2430 " *(uint32_t *)(gen_code_ptr + %d) = "
2431 "((*(uint32_t *)(gen_code_ptr + %d)) "
2432 " & ~0x3ff) "
2433 " | ((%s + %d) & 0x3ff);\n",
2434 reloc_offset, reloc_offset, relname, addend);
2435 break;
2436 case R_SPARC_WDISP30:
2437 fprintf(outfile,
2438 " *(uint32_t *)(gen_code_ptr + %d) = "
2439 "((*(uint32_t *)(gen_code_ptr + %d)) "
2440 " & ~0x3fffffff) "
2441 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2442 " & 0x3fffffff);\n",
2443 reloc_offset, reloc_offset, relname, addend,
2444 reloc_offset);
2445 break;
2446 case R_SPARC_WDISP22:
2447 fprintf(outfile,
2448 " *(uint32_t *)(gen_code_ptr + %d) = "
2449 "((*(uint32_t *)(gen_code_ptr + %d)) "
2450 " & ~0x3fffff) "
2451 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2452 " & 0x3fffff);\n",
2453 rel->r_offset - start_offset,
2454 rel->r_offset - start_offset,
2455 relname, addend,
2456 rel->r_offset - start_offset);
2457 break;
2458 default:
2459 error("unsupported sparc relocation (%d)", type);
2464 #elif defined(HOST_SPARC64)
2466 char relname[256];
2467 int type;
2468 int addend;
2469 int reloc_offset;
2470 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2471 if (rel->r_offset >= start_offset &&
2472 rel->r_offset < start_offset + copy_size) {
2473 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2474 get_reloc_expr(relname, sizeof(relname), sym_name);
2475 type = ELF32_R_TYPE(rel->r_info);
2476 addend = rel->r_addend;
2477 reloc_offset = rel->r_offset - start_offset;
2478 switch(type) {
2479 case R_SPARC_32:
2480 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2481 reloc_offset, relname, addend);
2482 break;
2483 case R_SPARC_HI22:
2484 fprintf(outfile,
2485 " *(uint32_t *)(gen_code_ptr + %d) = "
2486 "((*(uint32_t *)(gen_code_ptr + %d)) "
2487 " & ~0x3fffff) "
2488 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2489 reloc_offset, reloc_offset, relname, addend);
2490 break;
2491 case R_SPARC_LO10:
2492 fprintf(outfile,
2493 " *(uint32_t *)(gen_code_ptr + %d) = "
2494 "((*(uint32_t *)(gen_code_ptr + %d)) "
2495 " & ~0x3ff) "
2496 " | ((%s + %d) & 0x3ff);\n",
2497 reloc_offset, reloc_offset, relname, addend);
2498 break;
2499 case R_SPARC_OLO10:
2500 addend += ELF64_R_TYPE_DATA (rel->r_info);
2501 fprintf(outfile,
2502 " *(uint32_t *)(gen_code_ptr + %d) = "
2503 "((*(uint32_t *)(gen_code_ptr + %d)) "
2504 " & ~0x3ff) "
2505 " | ((%s + %d) & 0x3ff);\n",
2506 reloc_offset, reloc_offset, relname, addend);
2507 break;
2508 case R_SPARC_WDISP30:
2509 fprintf(outfile,
2510 " *(uint32_t *)(gen_code_ptr + %d) = "
2511 "((*(uint32_t *)(gen_code_ptr + %d)) "
2512 " & ~0x3fffffff) "
2513 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2514 " & 0x3fffffff);\n",
2515 reloc_offset, reloc_offset, relname, addend,
2516 reloc_offset);
2517 break;
2518 case R_SPARC_WDISP22:
2519 fprintf(outfile,
2520 " *(uint32_t *)(gen_code_ptr + %d) = "
2521 "((*(uint32_t *)(gen_code_ptr + %d)) "
2522 " & ~0x3fffff) "
2523 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2524 " & 0x3fffff);\n",
2525 reloc_offset, reloc_offset, relname, addend,
2526 reloc_offset);
2527 break;
2528 case R_SPARC_HH22:
2529 fprintf(outfile,
2530 " *(uint32_t *)(gen_code_ptr + %d) = "
2531 "((*(uint32_t *)(gen_code_ptr + %d)) "
2532 " & ~0x00000000) "
2533 " | (((%s + %d) >> 42) & 0x00000000);\n",
2534 reloc_offset, reloc_offset, relname, addend);
2535 break;
2537 case R_SPARC_LM22:
2538 fprintf(outfile,
2539 " *(uint32_t *)(gen_code_ptr + %d) = "
2540 "((*(uint32_t *)(gen_code_ptr + %d)) "
2541 " & ~0x00000000) "
2542 " | (((%s + %d) >> 10) & 0x00000000);\n",
2543 reloc_offset, reloc_offset, relname, addend);
2544 break;
2546 case R_SPARC_HM10:
2547 fprintf(outfile,
2548 " *(uint32_t *)(gen_code_ptr + %d) = "
2549 "((*(uint32_t *)(gen_code_ptr + %d)) "
2550 " & ~0x00000000) "
2551 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2552 reloc_offset, reloc_offset, relname, addend);
2553 break;
2555 default:
2556 error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2561 #elif defined(HOST_ARM)
2563 char relname[256];
2564 int type;
2565 int addend;
2566 int reloc_offset;
2567 uint32_t insn;
2569 insn = get32((uint32_t *)(p_start + 4));
2570 /* If prologue ends in sub sp, sp, #const then assume
2571 op has a stack frame and needs the frame pointer. */
2572 if ((insn & 0xffffff00) == 0xe24dd000) {
2573 int i;
2574 uint32_t opcode;
2575 opcode = 0xe28db000; /* add fp, sp, #0. */
2576 #if 0
2577 /* ??? Need to undo the extra stack adjustment at the end of the op.
2578 For now just leave the stack misaligned and hope it doesn't break anything
2579 too important. */
2580 if ((insn & 4) != 0) {
2581 /* Preserve doubleword stack alignment. */
2582 fprintf(outfile,
2583 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2584 insn + 4);
2585 opcode -= 4;
2587 #endif
2588 insn = get32((uint32_t *)(p_start - 4));
2589 /* Calculate the size of the saved registers,
2590 excluding pc. */
2591 for (i = 0; i < 15; i++) {
2592 if (insn & (1 << i))
2593 opcode += 4;
2595 fprintf(outfile,
2596 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2598 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2599 relocs, nb_relocs);
2601 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2602 if (rel->r_offset >= start_offset &&
2603 rel->r_offset < start_offset + copy_size) {
2604 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2605 /* the compiler leave some unnecessary references to the code */
2606 if (sym_name[0] == '\0')
2607 continue;
2608 get_reloc_expr(relname, sizeof(relname), sym_name);
2609 type = ELF32_R_TYPE(rel->r_info);
2610 addend = get32((uint32_t *)(text + rel->r_offset));
2611 reloc_offset = rel->r_offset - start_offset;
2612 switch(type) {
2613 case R_ARM_ABS32:
2614 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2615 reloc_offset, relname, addend);
2616 break;
2617 case R_ARM_PC24:
2618 case R_ARM_JUMP24:
2619 case R_ARM_CALL:
2620 fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2621 reloc_offset, addend, relname);
2622 break;
2623 default:
2624 error("unsupported arm relocation (%d)", type);
2629 #elif defined(HOST_M68K)
2631 char relname[256];
2632 int type;
2633 int addend;
2634 int reloc_offset;
2635 Elf32_Sym *sym;
2636 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2637 if (rel->r_offset >= start_offset &&
2638 rel->r_offset < start_offset + copy_size) {
2639 sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2640 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2641 get_reloc_expr(relname, sizeof(relname), sym_name);
2642 type = ELF32_R_TYPE(rel->r_info);
2643 addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2644 reloc_offset = rel->r_offset - start_offset;
2645 switch(type) {
2646 case R_68K_32:
2647 fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2648 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2649 reloc_offset, relname, addend );
2650 break;
2651 case R_68K_PC32:
2652 fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2653 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2654 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2655 break;
2656 default:
2657 error("unsupported m68k relocation (%d)", type);
2662 #elif defined(HOST_HPPA)
2664 char relname[256];
2665 int type, is_label;
2666 int addend;
2667 int reloc_offset;
2668 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2669 if (rel->r_offset >= start_offset &&
2670 rel->r_offset < start_offset + copy_size) {
2671 sym_name = get_rel_sym_name(rel);
2672 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2673 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2674 type = ELF32_R_TYPE(rel->r_info);
2675 addend = rel->r_addend;
2676 reloc_offset = rel->r_offset - start_offset;
2678 if (is_label) {
2679 switch (type) {
2680 case R_PARISC_PCREL17F:
2681 fprintf(outfile,
2682 " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2683 reloc_offset, type, relname, addend);
2684 break;
2685 default:
2686 error("unsupported hppa label relocation (%d)", type);
2688 } else {
2689 switch (type) {
2690 case R_PARISC_DIR21L:
2691 fprintf(outfile,
2692 " hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2693 reloc_offset, relname, addend);
2694 break;
2695 case R_PARISC_DIR14R:
2696 fprintf(outfile,
2697 " hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2698 reloc_offset, relname, addend);
2699 break;
2700 case R_PARISC_PCREL17F:
2701 if (strstart(sym_name, "__op_gen_label", NULL)) {
2702 fprintf(outfile,
2703 " hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2704 reloc_offset, relname, addend);
2705 } else {
2706 fprintf(outfile,
2707 " HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2708 reloc_offset, relname);
2710 break;
2711 case R_PARISC_DPREL21L:
2712 if (strstart(sym_name, "__op_param", &p))
2713 fprintf(outfile,
2714 " hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2715 reloc_offset, p, addend);
2716 else
2717 fprintf(outfile,
2718 " hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2719 reloc_offset, relname, addend);
2720 break;
2721 case R_PARISC_DPREL14R:
2722 if (strstart(sym_name, "__op_param", &p))
2723 fprintf(outfile,
2724 " hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2725 reloc_offset, p, addend);
2726 else
2727 fprintf(outfile,
2728 " hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2729 reloc_offset, relname, addend);
2730 break;
2731 default:
2732 error("unsupported hppa relocation (%d)", type);
2738 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2740 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2741 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2742 char relname[256];
2743 int type;
2744 int addend;
2745 int reloc_offset;
2747 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2748 /* the compiler leave some unnecessary references to the code */
2749 if (sym_name[0] == '\0')
2750 continue;
2751 get_reloc_expr(relname, sizeof(relname), sym_name);
2752 type = ELF32_R_TYPE(rel->r_info);
2753 addend = get32((uint32_t *)(text + rel->r_offset));
2754 reloc_offset = rel->r_offset - start_offset;
2755 switch (type) {
2756 case R_MIPS_26:
2757 fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2758 rel->r_offset, sym_name);
2759 fprintf(outfile,
2760 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2761 "(0x%x & ~0x3fffff) "
2762 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2763 " & 0x3fffff);\n",
2764 reloc_offset, addend, addend, relname, reloc_offset);
2765 break;
2766 case R_MIPS_HI16:
2767 fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2768 rel->r_offset, sym_name);
2769 fprintf(outfile,
2770 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2771 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2772 " & ~0xffff) "
2773 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2774 reloc_offset, reloc_offset, relname);
2775 break;
2776 case R_MIPS_LO16:
2777 fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2778 rel->r_offset, sym_name);
2779 fprintf(outfile,
2780 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2781 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2782 " & ~0xffff) "
2783 " | (%s & 0xffff);\n",
2784 reloc_offset, reloc_offset, relname);
2785 break;
2786 case R_MIPS_PC16:
2787 fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2788 rel->r_offset, sym_name);
2789 fprintf(outfile,
2790 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2791 "(0x%x & ~0xffff) "
2792 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2793 " & 0xffff);\n",
2794 reloc_offset, addend, addend, relname, reloc_offset);
2795 break;
2796 case R_MIPS_GOT16:
2797 case R_MIPS_CALL16:
2798 fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2799 rel->r_offset, sym_name);
2800 fprintf(outfile,
2801 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2802 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2803 " & ~0xffff) "
2804 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2805 reloc_offset, reloc_offset, relname);
2806 break;
2807 default:
2808 error("unsupported MIPS relocation (%d)", type);
2813 #else
2814 #error unsupported CPU
2815 #endif
2816 fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
2817 fprintf(outfile, "}\n");
2818 fprintf(outfile, "break;\n\n");
2819 } else {
2820 fprintf(outfile, "static inline void gen_%s(", name);
2821 if (nb_args == 0) {
2822 fprintf(outfile, "void");
2823 } else {
2824 for(i = 0; i < nb_args; i++) {
2825 if (i != 0)
2826 fprintf(outfile, ", ");
2827 fprintf(outfile, "long param%d", i + 1);
2830 fprintf(outfile, ")\n");
2831 fprintf(outfile, "{\n");
2832 for(i = 0; i < nb_args; i++) {
2833 fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1);
2835 fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2836 fprintf(outfile, "}\n\n");
2840 int gen_file(FILE *outfile, int out_type)
2842 int i;
2843 EXE_SYM *sym;
2845 if (out_type == OUT_INDEX_OP) {
2846 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2847 const char *name;
2848 name = get_sym_name(sym);
2849 if (strstart(name, OP_PREFIX, NULL)) {
2850 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2853 } else if (out_type == OUT_GEN_OP) {
2854 /* generate gen_xxx functions */
2855 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2856 const char *name;
2857 name = get_sym_name(sym);
2858 if (strstart(name, OP_PREFIX, NULL)) {
2859 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2860 if (sym->st_shndx != text_shndx)
2861 error("invalid section for opcode (0x%x)", sym->st_shndx);
2862 #endif
2863 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2867 } else {
2868 /* generate big code generation switch */
2870 #ifdef HOST_ARM
2871 #error broken
2872 /* We need to know the size of all the ops so we can figure out when
2873 to emit constant pools. This must be consistent with opc.h. */
2874 fprintf(outfile,
2875 "static const uint32_t arm_opc_size[] = {\n"
2876 " 0,\n" /* end */
2877 " 0,\n" /* nop */
2878 " 0,\n" /* nop1 */
2879 " 0,\n" /* nop2 */
2880 " 0,\n"); /* nop3 */
2881 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2882 const char *name;
2883 name = get_sym_name(sym);
2884 if (strstart(name, OP_PREFIX, NULL)) {
2885 fprintf(outfile, " %d,\n", sym->st_size);
2888 fprintf(outfile,
2889 "};\n");
2890 #endif
2892 #ifdef HOST_ARM
2893 #error broken
2894 /* Arm is tricky because it uses constant pools for loading immediate values.
2895 We assume (and require) each function is code followed by a constant pool.
2896 All the ops are small so this should be ok. For each op we figure
2897 out how much "spare" range we have in the load instructions. This allows
2898 us to insert subsequent ops in between the op and the constant pool,
2899 eliminating the neeed to jump around the pool.
2901 We currently generate:
2903 [ For this example we assume merging would move op1_pool out of range.
2904 In practice we should be able to combine many ops before the offset
2905 limits are reached. ]
2906 op1_code;
2907 op2_code;
2908 goto op3;
2909 op2_pool;
2910 op1_pool;
2911 op3:
2912 op3_code;
2913 ret;
2914 op3_pool;
2916 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2918 fprintf(outfile,
2919 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2920 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2921 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2922 /* Initialise the parmissible pool offset to an arbitary large value. */
2923 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2924 #endif
2925 #ifdef HOST_IA64
2926 #error broken
2928 long addend, not_first = 0;
2929 unsigned long sym_idx;
2930 int index, max_index;
2931 const char *sym_name;
2932 EXE_RELOC *rel;
2934 max_index = -1;
2935 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2936 sym_idx = ELF64_R_SYM(rel->r_info);
2937 sym_name = (strtab + symtab[sym_idx].st_name);
2938 if (strstart(sym_name, "__op_gen_label", NULL))
2939 continue;
2940 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2941 continue;
2943 addend = rel->r_addend;
2944 index = get_plt_index(sym_name, addend);
2945 if (index <= max_index)
2946 continue;
2947 max_index = index;
2948 fprintf(outfile, " extern void %s(void);\n", sym_name);
2951 fprintf(outfile,
2952 " struct ia64_fixup *plt_fixes = NULL, "
2953 "*ltoff_fixes = NULL;\n"
2954 " static long plt_target[] = {\n\t");
2956 max_index = -1;
2957 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2958 sym_idx = ELF64_R_SYM(rel->r_info);
2959 sym_name = (strtab + symtab[sym_idx].st_name);
2960 if (strstart(sym_name, "__op_gen_label", NULL))
2961 continue;
2962 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2963 continue;
2965 addend = rel->r_addend;
2966 index = get_plt_index(sym_name, addend);
2967 if (index <= max_index)
2968 continue;
2969 max_index = index;
2971 if (not_first)
2972 fprintf(outfile, ",\n\t");
2973 not_first = 1;
2974 if (addend)
2975 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2976 else
2977 fprintf(outfile, "(long) &%s", sym_name);
2979 fprintf(outfile, "\n };\n"
2980 " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2982 #endif
2984 #ifdef HOST_ARM
2985 #error broken
2986 /* Generate constant pool if needed */
2987 fprintf(outfile,
2988 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2989 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2990 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2991 " last_gen_code_ptr = gen_code_ptr;\n"
2992 " arm_ldr_ptr = arm_ldr_table;\n"
2993 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2994 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2995 " }\n");
2996 #endif
2998 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2999 const char *name;
3000 name = get_sym_name(sym);
3001 if (strstart(name, OP_PREFIX, NULL)) {
3002 #if 0
3003 printf("%4d: %s pos=0x%08x len=%d\n",
3004 i, name, sym->st_value, sym->st_size);
3005 #endif
3006 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
3007 if (sym->st_shndx != text_shndx)
3008 error("invalid section for opcode (0x%x)", sym->st_shndx);
3009 #endif
3010 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
3015 return 0;
3018 void usage(void)
3020 printf("dyngen (c) 2003 Fabrice Bellard\n"
3021 "usage: dyngen [-o outfile] [-c] objfile\n"
3022 "Generate a dynamic code generator from an object file\n"
3023 "-c output enum of operations\n"
3024 "-g output gen_op_xx() functions\n"
3026 exit(1);
3029 int main(int argc, char **argv)
3031 int c, out_type;
3032 const char *filename, *outfilename;
3033 FILE *outfile;
3035 outfilename = "out.c";
3036 out_type = OUT_CODE;
3037 for(;;) {
3038 c = getopt(argc, argv, "ho:cg");
3039 if (c == -1)
3040 break;
3041 switch(c) {
3042 case 'h':
3043 usage();
3044 break;
3045 case 'o':
3046 outfilename = optarg;
3047 break;
3048 case 'c':
3049 out_type = OUT_INDEX_OP;
3050 break;
3051 case 'g':
3052 out_type = OUT_GEN_OP;
3053 break;
3056 if (optind >= argc)
3057 usage();
3058 filename = argv[optind];
3059 outfile = fopen(outfilename, "w");
3060 if (!outfile)
3061 error("could not open '%s'", outfilename);
3063 load_object(filename);
3064 gen_file(outfile, out_type);
3065 fclose(outfile);
3066 return 0;