3b073c18f5a57ae849d437294660f49d1a1fdf78
[qemu] / dyngen.c
1 /*
2  *  Generic Dynamic compiler generator
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  *  The COFF object format support was extracted from Kazu's QEMU port
7  *  to Win32.
8  *
9  *  Mach-O Support by Matt Reda and Pierre d'Herbemont
10  *
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.
15  *
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.
20  *
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.
24  */
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>
32
33 #include "config-host.h"
34
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
44
45 #ifdef CONFIG_FORMAT_ELF
46
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)
51
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
56
57 #elif defined(HOST_X86_64)
58
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
63
64 #elif defined(HOST_PPC)
65
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
70
71 #elif defined(HOST_S390)
72
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
77
78 #elif defined(HOST_ALPHA)
79
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
84
85 #elif defined(HOST_IA64)
86
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
91
92 #elif defined(HOST_SPARC)
93
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
98
99 #elif defined(HOST_SPARC64)
100
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
105
106 #elif defined(HOST_ARM)
107
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
112
113 #elif defined(HOST_M68K)
114
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
119
120 #elif defined(HOST_MIPS)
121
122 #define ELF_CLASS       ELFCLASS32
123 #define ELF_ARCH        EM_MIPS
124 #define elf_check_arch(x) ((x) == EM_MIPS)
125 #define ELF_USES_RELOC
126
127 #elif defined(HOST_MIPS64)
128
129 /* Assume n32 ABI here, which is ELF32. */
130 #define ELF_CLASS       ELFCLASS32
131 #define ELF_ARCH        EM_MIPS
132 #define elf_check_arch(x) ((x) == EM_MIPS)
133 #define ELF_USES_RELOCA
134
135 #else
136 #error unsupported CPU - please update the code
137 #endif
138
139 #include "elf.h"
140
141 #if ELF_CLASS == ELFCLASS32
142 typedef int32_t host_long;
143 typedef uint32_t host_ulong;
144 #define swabls(x) swab32s(x)
145 #define swablss(x) swab32ss(x)
146 #else
147 typedef int64_t host_long;
148 typedef uint64_t host_ulong;
149 #define swabls(x) swab64s(x)
150 #define swablss(x) swab64ss(x)
151 #endif
152
153 #ifdef ELF_USES_RELOCA
154 #define SHT_RELOC SHT_RELA
155 #else
156 #define SHT_RELOC SHT_REL
157 #endif
158
159 #define EXE_RELOC ELF_RELOC
160 #define EXE_SYM ElfW(Sym)
161
162 #endif /* CONFIG_FORMAT_ELF */
163
164 #ifdef CONFIG_FORMAT_COFF
165
166 typedef int32_t host_long;
167 typedef uint32_t host_ulong;
168
169 #include "a.out.h"
170
171 #define FILENAMELEN 256
172
173 typedef struct coff_sym {
174     struct external_syment *st_syment;
175     char st_name[FILENAMELEN];
176     uint32_t st_value;
177     int  st_size;
178     uint8_t st_type;
179     uint8_t st_shndx;
180 } coff_Sym;
181
182 typedef struct coff_rel {
183     struct external_reloc *r_reloc;
184     int  r_offset;
185     uint8_t r_type;
186 } coff_Rel;
187
188 #define EXE_RELOC struct coff_rel
189 #define EXE_SYM struct coff_sym
190
191 #endif /* CONFIG_FORMAT_COFF */
192
193 #ifdef CONFIG_FORMAT_MACH
194
195 #include <mach-o/loader.h>
196 #include <mach-o/nlist.h>
197 #include <mach-o/reloc.h>
198 #include <mach-o/ppc/reloc.h>
199
200 # define check_mach_header(x) (x.magic == MH_MAGIC)
201 typedef int32_t host_long;
202 typedef uint32_t host_ulong;
203
204 struct nlist_extended
205 {
206    union {
207    char *n_name;
208    long  n_strx;
209    } n_un;
210    unsigned char n_type;
211    unsigned char n_sect;
212    short st_desc;
213    unsigned long st_value;
214    unsigned long st_size;
215 };
216
217 #define EXE_RELOC struct relocation_info
218 #define EXE_SYM struct nlist_extended
219
220 #endif /* CONFIG_FORMAT_MACH */
221
222 #include "bswap.h"
223
224 enum {
225     OUT_GEN_OP,
226     OUT_CODE,
227     OUT_INDEX_OP,
228 };
229
230 /* all dynamically generated functions begin with this code */
231 #define OP_PREFIX "op_"
232
233 int do_swap;
234
235 static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
236 {
237     va_list ap;
238     va_start(ap, fmt);
239     fprintf(stderr, "dyngen: ");
240     vfprintf(stderr, fmt, ap);
241     fprintf(stderr, "\n");
242     va_end(ap);
243     exit(1);
244 }
245
246 static void *load_data(int fd, long offset, unsigned int size)
247 {
248     char *data;
249
250     data = malloc(size);
251     if (!data)
252         return NULL;
253     lseek(fd, offset, SEEK_SET);
254     if (read(fd, data, size) != size) {
255         free(data);
256         return NULL;
257     }
258     return data;
259 }
260
261 int strstart(const char *str, const char *val, const char **ptr)
262 {
263     const char *p, *q;
264     p = str;
265     q = val;
266     while (*q != '\0') {
267         if (*p != *q)
268             return 0;
269         p++;
270         q++;
271     }
272     if (ptr)
273         *ptr = p;
274     return 1;
275 }
276
277 void pstrcpy(char *buf, int buf_size, const char *str)
278 {
279     int c;
280     char *q = buf;
281
282     if (buf_size <= 0)
283         return;
284
285     for(;;) {
286         c = *str++;
287         if (c == 0 || q >= buf + buf_size - 1)
288             break;
289         *q++ = c;
290     }
291     *q = '\0';
292 }
293
294 void swab16s(uint16_t *p)
295 {
296     *p = bswap16(*p);
297 }
298
299 void swab32s(uint32_t *p)
300 {
301     *p = bswap32(*p);
302 }
303
304 void swab32ss(int32_t *p)
305 {
306     *p = bswap32(*p);
307 }
308
309 void swab64s(uint64_t *p)
310 {
311     *p = bswap64(*p);
312 }
313
314 void swab64ss(int64_t *p)
315 {
316     *p = bswap64(*p);
317 }
318
319 uint16_t get16(uint16_t *p)
320 {
321     uint16_t val;
322     val = *p;
323     if (do_swap)
324         val = bswap16(val);
325     return val;
326 }
327
328 uint32_t get32(uint32_t *p)
329 {
330     uint32_t val;
331     val = *p;
332     if (do_swap)
333         val = bswap32(val);
334     return val;
335 }
336
337 void put16(uint16_t *p, uint16_t val)
338 {
339     if (do_swap)
340         val = bswap16(val);
341     *p = val;
342 }
343
344 void put32(uint32_t *p, uint32_t val)
345 {
346     if (do_swap)
347         val = bswap32(val);
348     *p = val;
349 }
350
351 /* executable information */
352 EXE_SYM *symtab;
353 int nb_syms;
354 int text_shndx;
355 uint8_t *text;
356 EXE_RELOC *relocs;
357 int nb_relocs;
358
359 #ifdef CONFIG_FORMAT_ELF
360
361 /* ELF file info */
362 struct elf_shdr *shdr;
363 uint8_t **sdata;
364 struct elfhdr ehdr;
365 char *strtab;
366
367 int elf_must_swap(struct elfhdr *h)
368 {
369   union {
370       uint32_t i;
371       uint8_t b[4];
372   } swaptest;
373
374   swaptest.i = 1;
375   return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
376       (swaptest.b[0] == 0);
377 }
378
379 void elf_swap_ehdr(struct elfhdr *h)
380 {
381     swab16s(&h->e_type);                        /* Object file type */
382     swab16s(&h->        e_machine);             /* Architecture */
383     swab32s(&h->        e_version);             /* Object file version */
384     swabls(&h-> e_entry);               /* Entry point virtual address */
385     swabls(&h-> e_phoff);               /* Program header table file offset */
386     swabls(&h-> e_shoff);               /* Section header table file offset */
387     swab32s(&h->        e_flags);               /* Processor-specific flags */
388     swab16s(&h->        e_ehsize);              /* ELF header size in bytes */
389     swab16s(&h->        e_phentsize);           /* Program header table entry size */
390     swab16s(&h->        e_phnum);               /* Program header table entry count */
391     swab16s(&h->        e_shentsize);           /* Section header table entry size */
392     swab16s(&h->        e_shnum);               /* Section header table entry count */
393     swab16s(&h->        e_shstrndx);            /* Section header string table index */
394 }
395
396 void elf_swap_shdr(struct elf_shdr *h)
397 {
398   swab32s(&h->  sh_name);               /* Section name (string tbl index) */
399   swab32s(&h->  sh_type);               /* Section type */
400   swabls(&h->   sh_flags);              /* Section flags */
401   swabls(&h->   sh_addr);               /* Section virtual addr at execution */
402   swabls(&h->   sh_offset);             /* Section file offset */
403   swabls(&h->   sh_size);               /* Section size in bytes */
404   swab32s(&h->  sh_link);               /* Link to another section */
405   swab32s(&h->  sh_info);               /* Additional section information */
406   swabls(&h->   sh_addralign);          /* Section alignment */
407   swabls(&h->   sh_entsize);            /* Entry size if section holds table */
408 }
409
410 void elf_swap_phdr(struct elf_phdr *h)
411 {
412     swab32s(&h->p_type);                        /* Segment type */
413     swabls(&h->p_offset);               /* Segment file offset */
414     swabls(&h->p_vaddr);                /* Segment virtual address */
415     swabls(&h->p_paddr);                /* Segment physical address */
416     swabls(&h->p_filesz);               /* Segment size in file */
417     swabls(&h->p_memsz);                /* Segment size in memory */
418     swab32s(&h->p_flags);               /* Segment flags */
419     swabls(&h->p_align);                /* Segment alignment */
420 }
421
422 void elf_swap_rel(ELF_RELOC *rel)
423 {
424     swabls(&rel->r_offset);
425     swabls(&rel->r_info);
426 #ifdef ELF_USES_RELOCA
427     swablss(&rel->r_addend);
428 #endif
429 }
430
431 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
432                                   const char *name)
433 {
434     int i;
435     const char *shname;
436     struct elf_shdr *sec;
437
438     for(i = 0; i < shnum; i++) {
439         sec = &shdr[i];
440         if (!sec->sh_name)
441             continue;
442         shname = shstr + sec->sh_name;
443         if (!strcmp(shname, name))
444             return sec;
445     }
446     return NULL;
447 }
448
449 int find_reloc(int sh_index)
450 {
451     struct elf_shdr *sec;
452     int i;
453
454     for(i = 0; i < ehdr.e_shnum; i++) {
455         sec = &shdr[i];
456         if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
457             return i;
458     }
459     return 0;
460 }
461
462 static host_ulong get_rel_offset(EXE_RELOC *rel)
463 {
464     return rel->r_offset;
465 }
466
467 static char *get_rel_sym_name(EXE_RELOC *rel)
468 {
469     return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
470 }
471
472 static char *get_sym_name(EXE_SYM *sym)
473 {
474     return strtab + sym->st_name;
475 }
476
477 /* load an elf object file */
478 int load_object(const char *filename)
479 {
480     int fd;
481     struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
482     int i, j;
483     ElfW(Sym) *sym;
484     char *shstr;
485     ELF_RELOC *rel;
486
487     fd = open(filename, O_RDONLY);
488     if (fd < 0)
489         error("can't open file '%s'", filename);
490
491     /* Read ELF header.  */
492     if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
493         error("unable to read file header");
494
495     /* Check ELF identification.  */
496     if (ehdr.e_ident[EI_MAG0] != ELFMAG0
497      || ehdr.e_ident[EI_MAG1] != ELFMAG1
498      || ehdr.e_ident[EI_MAG2] != ELFMAG2
499      || ehdr.e_ident[EI_MAG3] != ELFMAG3
500      || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
501         error("bad ELF header");
502     }
503
504     do_swap = elf_must_swap(&ehdr);
505     if (do_swap)
506         elf_swap_ehdr(&ehdr);
507     if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
508         error("Unsupported ELF class");
509     if (ehdr.e_type != ET_REL)
510         error("ELF object file expected");
511     if (ehdr.e_version != EV_CURRENT)
512         error("Invalid ELF version");
513     if (!elf_check_arch(ehdr.e_machine))
514         error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
515
516     /* read section headers */
517     shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
518     if (do_swap) {
519         for(i = 0; i < ehdr.e_shnum; i++) {
520             elf_swap_shdr(&shdr[i]);
521         }
522     }
523
524     /* read all section data */
525     sdata = malloc(sizeof(void *) * ehdr.e_shnum);
526     memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
527
528     for(i = 0;i < ehdr.e_shnum; i++) {
529         sec = &shdr[i];
530         if (sec->sh_type != SHT_NOBITS)
531             sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
532     }
533
534     sec = &shdr[ehdr.e_shstrndx];
535     shstr = (char *)sdata[ehdr.e_shstrndx];
536
537     /* swap relocations */
538     for(i = 0; i < ehdr.e_shnum; i++) {
539         sec = &shdr[i];
540         if (sec->sh_type == SHT_RELOC) {
541             nb_relocs = sec->sh_size / sec->sh_entsize;
542             if (do_swap) {
543                 for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
544                     elf_swap_rel(rel);
545             }
546         }
547     }
548     /* text section */
549
550     text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
551     if (!text_sec)
552         error("could not find .text section");
553     text_shndx = text_sec - shdr;
554     text = sdata[text_shndx];
555
556     /* find text relocations, if any */
557     relocs = NULL;
558     nb_relocs = 0;
559     i = find_reloc(text_shndx);
560     if (i != 0) {
561         relocs = (ELF_RELOC *)sdata[i];
562         nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
563     }
564
565     symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
566     if (!symtab_sec)
567         error("could not find .symtab section");
568     strtab_sec = &shdr[symtab_sec->sh_link];
569
570     symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
571     strtab = (char *)sdata[symtab_sec->sh_link];
572
573     nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
574     if (do_swap) {
575         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
576             swab32s(&sym->st_name);
577             swabls(&sym->st_value);
578             swabls(&sym->st_size);
579             swab16s(&sym->st_shndx);
580         }
581     }
582     close(fd);
583     return 0;
584 }
585
586 #endif /* CONFIG_FORMAT_ELF */
587
588 #ifdef CONFIG_FORMAT_COFF
589
590 /* COFF file info */
591 struct external_scnhdr *shdr;
592 uint8_t **sdata;
593 struct external_filehdr fhdr;
594 struct external_syment *coff_symtab;
595 char *strtab;
596 int coff_text_shndx, coff_data_shndx;
597
598 int data_shndx;
599
600 #define STRTAB_SIZE 4
601
602 #define DIR32   0x06
603 #define DISP32  0x14
604
605 #define T_FUNCTION  0x20
606 #define C_EXTERNAL  2
607
608 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
609 {
610     char *q;
611     int c, i, len;
612
613     if (ext_sym->e.e.e_zeroes != 0) {
614         q = sym->st_name;
615         for(i = 0; i < 8; i++) {
616             c = ext_sym->e.e_name[i];
617             if (c == '\0')
618                 break;
619             *q++ = c;
620         }
621         *q = '\0';
622     } else {
623         pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
624     }
625
626     /* now convert the name to a C name (suppress the leading '_') */
627     if (sym->st_name[0] == '_') {
628         len = strlen(sym->st_name);
629         memmove(sym->st_name, sym->st_name + 1, len - 1);
630         sym->st_name[len - 1] = '\0';
631     }
632 }
633
634 char *name_for_dotdata(struct coff_rel *rel)
635 {
636         int i;
637         struct coff_sym *sym;
638         uint32_t text_data;
639
640         text_data = *(uint32_t *)(text + rel->r_offset);
641
642         for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
643                 if (sym->st_syment->e_scnum == data_shndx &&
644                     text_data >= sym->st_value &&
645                     text_data < sym->st_value + sym->st_size) {
646
647                     return sym->st_name;
648
649                 }
650         }
651         return NULL;
652 }
653
654 static char *get_sym_name(EXE_SYM *sym)
655 {
656     return sym->st_name;
657 }
658
659 static char *get_rel_sym_name(EXE_RELOC *rel)
660 {
661     char *name;
662     name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
663     if (!strcmp(name, ".data"))
664         name = name_for_dotdata(rel);
665     if (name[0] == '.')
666         return NULL;
667     return name;
668 }
669
670 static host_ulong get_rel_offset(EXE_RELOC *rel)
671 {
672     return rel->r_offset;
673 }
674
675 struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
676 {
677     int i;
678     const char *shname;
679     struct external_scnhdr *sec;
680
681     for(i = 0; i < shnum; i++) {
682         sec = &shdr[i];
683         if (!sec->s_name)
684             continue;
685         shname = sec->s_name;
686         if (!strcmp(shname, name))
687             return sec;
688     }
689     return NULL;
690 }
691
692 /* load a coff object file */
693 int load_object(const char *filename)
694 {
695     int fd;
696     struct external_scnhdr *sec, *text_sec, *data_sec;
697     int i;
698     struct external_syment *ext_sym;
699     struct external_reloc *coff_relocs;
700     struct external_reloc *ext_rel;
701     uint32_t *n_strtab;
702     EXE_SYM *sym;
703     EXE_RELOC *rel;
704     const char *p;
705     int aux_size, j;
706
707     fd = open(filename, O_RDONLY
708 #ifdef _WIN32
709               | O_BINARY
710 #endif
711               );
712     if (fd < 0)
713         error("can't open file '%s'", filename);
714
715     /* Read COFF header.  */
716     if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
717         error("unable to read file header");
718
719     /* Check COFF identification.  */
720     if (fhdr.f_magic != I386MAGIC) {
721         error("bad COFF header");
722     }
723     do_swap = 0;
724
725     /* read section headers */
726     shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
727
728     /* read all section data */
729     sdata = malloc(sizeof(void *) * fhdr.f_nscns);
730     memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
731
732     for(i = 0;i < fhdr.f_nscns; i++) {
733         sec = &shdr[i];
734         if (!strstart(sec->s_name,  ".bss", &p))
735             sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
736     }
737
738
739     /* text section */
740     text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
741     if (!text_sec)
742         error("could not find .text section");
743     coff_text_shndx = text_sec - shdr;
744     text = sdata[coff_text_shndx];
745
746     /* data section */
747     data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
748     if (!data_sec)
749         error("could not find .data section");
750     coff_data_shndx = data_sec - shdr;
751
752     coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
753     for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
754         for(i=0;i<8;i++)
755             printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
756         printf("\n");
757     }
758
759
760     n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
761     strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
762
763     nb_syms = fhdr.f_nsyms;
764
765     for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
766       if (strstart(ext_sym->e.e_name, ".text", NULL))
767                   text_shndx = ext_sym->e_scnum;
768           if (strstart(ext_sym->e.e_name, ".data", NULL))
769                   data_shndx = ext_sym->e_scnum;
770     }
771
772         /* set coff symbol */
773         symtab = malloc(sizeof(struct coff_sym) * nb_syms);
774
775         for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
776                 memset(sym, 0, sizeof(*sym));
777                 sym->st_syment = ext_sym;
778                 sym_ent_name(ext_sym, sym);
779                 sym->st_value = ext_sym->e_value;
780
781                 aux_size = *(int8_t *)ext_sym->e_numaux;
782                 if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
783                         for (j = aux_size + 1; j < nb_syms - i; j++) {
784                                 if ((ext_sym + j)->e_scnum == text_shndx &&
785                                         (ext_sym + j)->e_type == T_FUNCTION ){
786                                         sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
787                                         break;
788                                 } else if (j == nb_syms - i - 1) {
789                                         sec = &shdr[coff_text_shndx];
790                                         sym->st_size = sec->s_size - ext_sym->e_value;
791                                         break;
792                                 }
793                         }
794                 } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
795                         for (j = aux_size + 1; j < nb_syms - i; j++) {
796                                 if ((ext_sym + j)->e_scnum == data_shndx) {
797                                         sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
798                                         break;
799                                 } else if (j == nb_syms - i - 1) {
800                                         sec = &shdr[coff_data_shndx];
801                                         sym->st_size = sec->s_size - ext_sym->e_value;
802                                         break;
803                                 }
804                         }
805                 } else {
806                         sym->st_size = 0;
807                 }
808
809                 sym->st_type = ext_sym->e_type;
810                 sym->st_shndx = ext_sym->e_scnum;
811         }
812
813
814     /* find text relocations, if any */
815     sec = &shdr[coff_text_shndx];
816     coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
817     nb_relocs = sec->s_nreloc;
818
819     /* set coff relocation */
820     relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
821     for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
822          i++, ext_rel++, rel++) {
823         memset(rel, 0, sizeof(*rel));
824         rel->r_reloc = ext_rel;
825         rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
826         rel->r_type = *(uint16_t *)ext_rel->r_type;
827     }
828     return 0;
829 }
830
831 #endif /* CONFIG_FORMAT_COFF */
832
833 #ifdef CONFIG_FORMAT_MACH
834
835 /* File Header */
836 struct mach_header      mach_hdr;
837
838 /* commands */
839 struct segment_command  *segment = 0;
840 struct dysymtab_command *dysymtabcmd = 0;
841 struct symtab_command   *symtabcmd = 0;
842
843 /* section */
844 struct section  *section_hdr;
845 struct section *text_sec_hdr;
846 uint8_t         **sdata;
847
848 /* relocs */
849 struct relocation_info *relocs;
850
851 /* symbols */
852 EXE_SYM                 *symtab;
853 struct nlist    *symtab_std;
854 char                    *strtab;
855
856 /* indirect symbols */
857 uint32_t        *tocdylib;
858
859 /* Utility functions */
860
861 static inline char *find_str_by_index(int index)
862 {
863     return strtab+index;
864 }
865
866 /* Used by dyngen common code */
867 static char *get_sym_name(EXE_SYM *sym)
868 {
869         char *name = find_str_by_index(sym->n_un.n_strx);
870
871         if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
872                 return "debug";
873
874         if(!name)
875                 return name;
876         if(name[0]=='_')
877                 return name + 1;
878         else
879                 return name;
880 }
881
882 /* find a section index given its segname, sectname */
883 static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
884                                   const char *sectname)
885 {
886     int i;
887     struct section *sec = section_hdr;
888
889     for(i = 0; i < shnum; i++, sec++) {
890         if (!sec->segname || !sec->sectname)
891             continue;
892         if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
893             return i;
894     }
895     return -1;
896 }
897
898 /* find a section header given its segname, sectname */
899 struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
900                                   const char *sectname)
901 {
902     int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
903         if(index == -1)
904                 return NULL;
905         return section_hdr+index;
906 }
907
908
909 static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
910 {
911     struct scattered_relocation_info * scarel;
912
913     if(R_SCATTERED & rel->r_address) {
914         scarel = (struct scattered_relocation_info*)rel;
915         if(scarel->r_type != PPC_RELOC_PAIR)
916             error("fetch_next_pair_value: looking for a pair which was not found (1)");
917         *value = scarel->r_value;
918     } else {
919                 if(rel->r_type != PPC_RELOC_PAIR)
920                         error("fetch_next_pair_value: looking for a pair which was not found (2)");
921                 *value = rel->r_address;
922         }
923 }
924
925 /* find a sym name given its value, in a section number */
926 static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
927 {
928         int i, ret = -1;
929
930         for( i = 0 ; i < nb_syms; i++ )
931         {
932             if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
933                          (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
934                 {
935                         if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
936                                 ret = i;
937                 }
938         }
939         if( ret < 0 ) {
940                 *offset = 0;
941                 return 0;
942         } else {
943                 *offset = value - symtab[ret].st_value;
944                 return get_sym_name(&symtab[ret]);
945         }
946 }
947
948 /*
949  *  Find symbol name given a (virtual) address, and a section which is of type
950  *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
951  */
952 static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
953 {
954     unsigned int tocindex, symindex, size;
955     const char *name = 0;
956
957     /* Sanity check */
958     if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
959         return (char*)0;
960
961         if( sec_hdr->flags & S_SYMBOL_STUBS ){
962                 size = sec_hdr->reserved2;
963                 if(size == 0)
964                     error("size = 0");
965
966         }
967         else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
968                     sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
969                 size = sizeof(unsigned long);
970         else
971                 return 0;
972
973     /* Compute our index in toc */
974         tocindex = (address - sec_hdr->addr)/size;
975         symindex = tocdylib[sec_hdr->reserved1 + tocindex];
976
977         name = get_sym_name(&symtab[symindex]);
978
979     return name;
980 }
981
982 static const char * find_reloc_name_given_its_address(int address)
983 {
984     unsigned int i;
985     for(i = 0; i < segment->nsects ; i++)
986     {
987         const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
988         if((long)name != -1)
989             return name;
990     }
991     return 0;
992 }
993
994 static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
995 {
996         char * name = 0;
997         struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
998         int sectnum = rel->r_symbolnum;
999         int sectoffset;
1000         int other_half=0;
1001
1002         /* init the slide value */
1003         *sslide = 0;
1004
1005         if(R_SCATTERED & rel->r_address)
1006                 return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1007
1008         if(rel->r_extern)
1009         {
1010                 /* ignore debug sym */
1011                 if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1012                         return 0;
1013                 return get_sym_name(&symtab[rel->r_symbolnum]);
1014         }
1015
1016         /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1017         sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1018
1019         if(sectnum==0xffffff)
1020                 return 0;
1021
1022         /* Sanity Check */
1023         if(sectnum > segment->nsects)
1024                 error("sectnum > segment->nsects");
1025
1026         switch(rel->r_type)
1027         {
1028                 case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1029                         break;
1030                 case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1031                         break;
1032                 case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1033                         break;
1034                 case PPC_RELOC_BR24:
1035                         sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1036                         if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1037                         break;
1038                 default:
1039                         error("switch(rel->type) not found");
1040         }
1041
1042         if(rel->r_pcrel)
1043                 sectoffset += rel->r_address;
1044
1045         if (rel->r_type == PPC_RELOC_BR24)
1046                 name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1047
1048         /* search it in the full symbol list, if not found */
1049         if(!name)
1050                 name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1051
1052         return name;
1053 }
1054
1055 /* Used by dyngen common code */
1056 static const char * get_rel_sym_name(EXE_RELOC * rel)
1057 {
1058         int sslide;
1059         return get_reloc_name( rel, &sslide);
1060 }
1061
1062 /* Used by dyngen common code */
1063 static host_ulong get_rel_offset(EXE_RELOC *rel)
1064 {
1065         struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1066     if(R_SCATTERED & rel->r_address)
1067                 return sca_rel->r_address;
1068         else
1069                 return rel->r_address;
1070 }
1071
1072 /* load a mach-o object file */
1073 int load_object(const char *filename)
1074 {
1075         int fd;
1076         unsigned int offset_to_segment = 0;
1077     unsigned int offset_to_dysymtab = 0;
1078     unsigned int offset_to_symtab = 0;
1079     struct load_command lc;
1080     unsigned int i, j;
1081         EXE_SYM *sym;
1082         struct nlist *syment;
1083
1084         fd = open(filename, O_RDONLY);
1085     if (fd < 0)
1086         error("can't open file '%s'", filename);
1087
1088     /* Read Mach header.  */
1089     if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1090         error("unable to read file header");
1091
1092     /* Check Mach identification.  */
1093     if (!check_mach_header(mach_hdr)) {
1094         error("bad Mach header");
1095     }
1096
1097     if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1098         error("Unsupported CPU");
1099
1100     if (mach_hdr.filetype != MH_OBJECT)
1101         error("Unsupported Mach Object");
1102
1103     /* read segment headers */
1104     for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1105     {
1106         if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1107             error("unable to read load_command");
1108         if(lc.cmd == LC_SEGMENT)
1109         {
1110             offset_to_segment = j;
1111             lseek(fd, offset_to_segment, SEEK_SET);
1112             segment = malloc(sizeof(struct segment_command));
1113             if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1114                 error("unable to read LC_SEGMENT");
1115         }
1116         if(lc.cmd == LC_DYSYMTAB)
1117         {
1118             offset_to_dysymtab = j;
1119             lseek(fd, offset_to_dysymtab, SEEK_SET);
1120             dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1121             if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1122                 error("unable to read LC_DYSYMTAB");
1123         }
1124         if(lc.cmd == LC_SYMTAB)
1125         {
1126             offset_to_symtab = j;
1127             lseek(fd, offset_to_symtab, SEEK_SET);
1128             symtabcmd = malloc(sizeof(struct symtab_command));
1129             if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1130                 error("unable to read LC_SYMTAB");
1131         }
1132         j+=lc.cmdsize;
1133
1134         lseek(fd, j, SEEK_SET);
1135     }
1136
1137     if(!segment)
1138         error("unable to find LC_SEGMENT");
1139
1140     /* read section headers */
1141     section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1142
1143     /* read all section data */
1144     sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1145     memset(sdata, 0, sizeof(void *) * segment->nsects);
1146
1147         /* Load the data in section data */
1148         for(i = 0; i < segment->nsects; i++) {
1149         sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1150     }
1151
1152     /* text section */
1153         text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1154         i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1155         if (i == -1 || !text_sec_hdr)
1156         error("could not find __TEXT,__text section");
1157     text = sdata[i];
1158
1159     /* Make sure dysym was loaded */
1160     if(!(int)dysymtabcmd)
1161         error("could not find __DYSYMTAB segment");
1162
1163     /* read the table of content of the indirect sym */
1164     tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1165
1166     /* Make sure symtab was loaded  */
1167     if(!(int)symtabcmd)
1168         error("could not find __SYMTAB segment");
1169     nb_syms = symtabcmd->nsyms;
1170
1171     symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1172     strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1173
1174         symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1175
1176         /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1177         for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1178         struct nlist *sym_follow, *sym_next = 0;
1179         unsigned int j;
1180                 memset(sym, 0, sizeof(*sym));
1181
1182                 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1183             continue;
1184
1185                 memcpy(sym, syment, sizeof(*syment));
1186
1187                 /* Find the following symbol in order to get the current symbol size */
1188         for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1189             if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1190                 continue;
1191             if(!sym_next) {
1192                 sym_next = sym_follow;
1193                 continue;
1194             }
1195             if(!(sym_next->n_value > sym_follow->n_value))
1196                 continue;
1197             sym_next = sym_follow;
1198         }
1199                 if(sym_next)
1200             sym->st_size = sym_next->n_value - sym->st_value;
1201                 else
1202             sym->st_size = text_sec_hdr->size - sym->st_value;
1203         }
1204
1205     /* Find Reloc */
1206     relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1207     nb_relocs = text_sec_hdr->nreloc;
1208
1209         close(fd);
1210         return 0;
1211 }
1212
1213 #endif /* CONFIG_FORMAT_MACH */
1214
1215 /* return true if the expression is a label reference */
1216 int get_reloc_expr(char *name, int name_size, const char *sym_name)
1217 {
1218     const char *p;
1219
1220     if (strstart(sym_name, "__op_param", &p)) {
1221         snprintf(name, name_size, "param%s", p);
1222     } else if (strstart(sym_name, "__op_gen_label", &p)) {
1223         snprintf(name, name_size, "param%s", p);
1224         return 1;
1225     } else {
1226 #ifdef HOST_SPARC
1227         if (sym_name[0] == '.')
1228             snprintf(name, name_size,
1229                      "(long)(&__dot_%s)",
1230                      sym_name + 1);
1231         else
1232 #endif
1233             snprintf(name, name_size, "(long)(&%s)", sym_name);
1234     }
1235     return 0;
1236 }
1237
1238 #ifdef HOST_IA64
1239
1240 #define PLT_ENTRY_SIZE  16      /* 1 bundle containing "brl" */
1241
1242 struct plt_entry {
1243     struct plt_entry *next;
1244     const char *name;
1245     unsigned long addend;
1246 } *plt_list;
1247
1248 static int
1249 get_plt_index (const char *name, unsigned long addend)
1250 {
1251     struct plt_entry *plt, *prev= NULL;
1252     int index = 0;
1253
1254     /* see if we already have an entry for this target: */
1255     for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1256         if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1257             return index;
1258
1259     /* nope; create a new PLT entry: */
1260
1261     plt = malloc(sizeof(*plt));
1262     if (!plt) {
1263         perror("malloc");
1264         exit(1);
1265     }
1266     memset(plt, 0, sizeof(*plt));
1267     plt->name = strdup(name);
1268     plt->addend = addend;
1269
1270     /* append to plt-list: */
1271     if (prev)
1272         prev->next = plt;
1273     else
1274         plt_list = plt;
1275     return index;
1276 }
1277
1278 #endif
1279
1280 #ifdef HOST_ARM
1281
1282 int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1283                       FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1284                       ELF_RELOC *relocs, int nb_relocs)
1285 {
1286     uint8_t *p;
1287     uint32_t insn;
1288     int offset, min_offset, pc_offset, data_size, spare, max_pool;
1289     uint8_t data_allocated[1024];
1290     unsigned int data_index;
1291     int type;
1292
1293     memset(data_allocated, 0, sizeof(data_allocated));
1294
1295     p = p_start;
1296     min_offset = p_end - p_start;
1297     spare = 0x7fffffff;
1298     while (p < p_start + min_offset) {
1299         insn = get32((uint32_t *)p);
1300         /* TODO: Armv5e ldrd.  */
1301         /* TODO: VFP load.  */
1302         if ((insn & 0x0d5f0000) == 0x051f0000) {
1303             /* ldr reg, [pc, #im] */
1304             offset = insn & 0xfff;
1305             if (!(insn & 0x00800000))
1306                 offset = -offset;
1307             max_pool = 4096;
1308             type = 0;
1309         } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1310             /* FPA ldf.  */
1311             offset = (insn & 0xff) << 2;
1312             if (!(insn & 0x00800000))
1313                 offset = -offset;
1314             max_pool = 1024;
1315             type = 1;
1316         } else if ((insn & 0x0fff0000) == 0x028f0000) {
1317             /* Some gcc load a doubleword immediate with
1318                add regN, pc, #imm
1319                ldmia regN, {regN, regM}
1320                Hope and pray the compiler never generates somethin like
1321                add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1322             int r;
1323
1324             r = (insn & 0xf00) >> 7;
1325             offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1326             max_pool = 1024;
1327             type = 2;
1328         } else {
1329             max_pool = 0;
1330             type = -1;
1331         }
1332         if (type >= 0) {
1333             /* PC-relative load needs fixing up.  */
1334             if (spare > max_pool - offset)
1335                 spare = max_pool - offset;
1336             if ((offset & 3) !=0)
1337                 error("%s:%04x: pc offset must be 32 bit aligned",
1338                       name, start_offset + p - p_start);
1339             if (offset < 0)
1340                 error("%s:%04x: Embedded literal value",
1341                       name, start_offset + p - p_start);
1342             pc_offset = p - p_start + offset + 8;
1343             if (pc_offset <= (p - p_start) ||
1344                 pc_offset >= (p_end - p_start))
1345                 error("%s:%04x: pc offset must point inside the function code",
1346                       name, start_offset + p - p_start);
1347             if (pc_offset < min_offset)
1348                 min_offset = pc_offset;
1349             if (outfile) {
1350                 /* The intruction position */
1351                 fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1352                         p - p_start);
1353                 /* The position of the constant pool data.  */
1354                 data_index = ((p_end - p_start) - pc_offset) >> 2;
1355                 fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1356                         data_index);
1357                 fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
1358                 fprintf(outfile, "    arm_ldr_ptr++;\n");
1359             }
1360         }
1361         p += 4;
1362     }
1363
1364     /* Copy and relocate the constant pool data.  */
1365     data_size = (p_end - p_start) - min_offset;
1366     if (data_size > 0 && outfile) {
1367         spare += min_offset;
1368         fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1369         fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1370         fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1371                          "        arm_pool_ptr = gen_code_ptr + %d;\n",
1372                          spare, spare);
1373
1374         data_index = 0;
1375         for (pc_offset = min_offset;
1376              pc_offset < p_end - p_start;
1377              pc_offset += 4) {
1378
1379             ELF_RELOC *rel;
1380             int i, addend, type;
1381             const char *sym_name;
1382             char relname[1024];
1383
1384             /* data value */
1385             addend = get32((uint32_t *)(p_start + pc_offset));
1386             relname[0] = '\0';
1387             for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1388                 if (rel->r_offset == (pc_offset + start_offset)) {
1389                     sym_name = get_rel_sym_name(rel);
1390                     /* the compiler leave some unnecessary references to the code */
1391                     get_reloc_expr(relname, sizeof(relname), sym_name);
1392                     type = ELF32_R_TYPE(rel->r_info);
1393                     if (type != R_ARM_ABS32)
1394                         error("%s: unsupported data relocation", name);
1395                     break;
1396                 }
1397             }
1398             fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1399                     data_index, addend);
1400             if (relname[0] != '\0')
1401                 fprintf(outfile, " + %s", relname);
1402             fprintf(outfile, ";\n");
1403
1404             data_index++;
1405         }
1406     }
1407
1408     if (p == p_start)
1409         goto arm_ret_error;
1410     p -= 4;
1411     insn = get32((uint32_t *)p);
1412     /* The last instruction must be an ldm instruction.  There are several
1413        forms generated by gcc:
1414         ldmib sp, {..., pc}  (implies a sp adjustment of +4)
1415         ldmia sp, {..., pc}
1416         ldmea fp, {..., pc} */
1417     if ((insn & 0xffff8000) == 0xe99d8000) {
1418         if (outfile) {
1419             fprintf(outfile,
1420                     "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1421                     p - p_start);
1422         }
1423         p += 4;
1424     } else if ((insn & 0xffff8000) != 0xe89d8000
1425         && (insn & 0xffff8000) != 0xe91b8000) {
1426     arm_ret_error:
1427         if (!outfile)
1428             printf("%s: invalid epilog\n", name);
1429     }
1430     return p - p_start;
1431 }
1432 #endif
1433
1434
1435 #define MAX_ARGS 3
1436
1437 /* generate op code */
1438 void gen_code(const char *name, host_ulong offset, host_ulong size,
1439               FILE *outfile, int gen_switch)
1440 {
1441     int copy_size = 0;
1442     uint8_t *p_start, *p_end;
1443     host_ulong start_offset;
1444     int nb_args, i, n;
1445     uint8_t args_present[MAX_ARGS];
1446     const char *sym_name, *p;
1447     EXE_RELOC *rel;
1448
1449     /* Compute exact size excluding prologue and epilogue instructions.
1450      * Increment start_offset to skip epilogue instructions, then compute
1451      * copy_size the indicate the size of the remaining instructions (in
1452      * bytes).
1453      */
1454     p_start = text + offset;
1455     p_end = p_start + size;
1456     start_offset = offset;
1457 #if defined(HOST_I386) || defined(HOST_X86_64)
1458 #ifdef CONFIG_FORMAT_COFF
1459     {
1460         uint8_t *p;
1461         p = p_end - 1;
1462         if (p == p_start)
1463             error("empty code for %s", name);
1464         while (*p != 0xc3) {
1465             p--;
1466             if (p <= p_start)
1467                 error("ret or jmp expected at the end of %s", name);
1468         }
1469         copy_size = p - p_start;
1470     }
1471 #else
1472     {
1473         int len;
1474         len = p_end - p_start;
1475         if (len == 0)
1476             error("empty code for %s", name);
1477         if (p_end[-1] == 0xc3) {
1478             len--;
1479         } else {
1480             error("ret or jmp expected at the end of %s", name);
1481         }
1482         copy_size = len;
1483     }
1484 #endif
1485 #elif defined(HOST_PPC)
1486     {
1487         uint8_t *p;
1488         p = (void *)(p_end - 4);
1489         if (p == p_start)
1490             error("empty code for %s", name);
1491         if (get32((uint32_t *)p) != 0x4e800020)
1492             error("blr expected at the end of %s", name);
1493         copy_size = p - p_start;
1494     }
1495 #elif defined(HOST_S390)
1496     {
1497         uint8_t *p;
1498         p = (void *)(p_end - 2);
1499         if (p == p_start)
1500             error("empty code for %s", name);
1501         if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1502             error("br expected at the end of %s", name);
1503         copy_size = p - p_start;
1504     }
1505 #elif defined(HOST_ALPHA)
1506     {
1507         uint8_t *p;
1508         p = p_end - 4;
1509 #if 0
1510         /* XXX: check why it occurs */
1511         if (p == p_start)
1512             error("empty code for %s", name);
1513 #endif
1514         if (get32((uint32_t *)p) != 0x6bfa8001)
1515             error("ret expected at the end of %s", name);
1516         copy_size = p - p_start;
1517     }
1518 #elif defined(HOST_IA64)
1519     {
1520         uint8_t *p;
1521         p = (void *)(p_end - 4);
1522         if (p == p_start)
1523             error("empty code for %s", name);
1524         /* br.ret.sptk.many b0;; */
1525         /* 08 00 84 00 */
1526         if (get32((uint32_t *)p) != 0x00840008)
1527             error("br.ret.sptk.many b0;; expected at the end of %s", name);
1528         copy_size = p_end - p_start;
1529     }
1530 #elif defined(HOST_SPARC)
1531     {
1532 #define INSN_SAVE       0x9de3a000
1533 #define INSN_RET        0x81c7e008
1534 #define INSN_RETL       0x81c3e008
1535 #define INSN_RESTORE    0x81e80000
1536 #define INSN_RETURN     0x81cfe008
1537 #define INSN_NOP        0x01000000
1538 #define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1539 #define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1540
1541         uint32_t start_insn, end_insn1, end_insn2;
1542         uint8_t *p;
1543         p = (void *)(p_end - 8);
1544         if (p <= p_start)
1545             error("empty code for %s", name);
1546         start_insn = get32((uint32_t *)(p_start + 0x0));
1547         end_insn1 = get32((uint32_t *)(p + 0x0));
1548         end_insn2 = get32((uint32_t *)(p + 0x4));
1549         if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1550             (start_insn & ~0x1fff) == INSN_ADD_SP) {
1551             p_start += 0x4;
1552             start_offset += 0x4;
1553             if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1554                 /* SPARC v7: ret; restore; */ ;
1555             else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1556                 /* SPARC v9: return; nop; */ ;
1557             else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1558                 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1559             else
1560
1561                 error("ret; restore; not found at end of %s", name);
1562         } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1563             ;
1564         } else {
1565             error("No save at the beginning of %s", name);
1566         }
1567 #if 0
1568         /* Skip a preceeding nop, if present.  */
1569         if (p > p_start) {
1570             skip_insn = get32((uint32_t *)(p - 0x4));
1571             if (skip_insn == INSN_NOP)
1572                 p -= 4;
1573         }
1574 #endif
1575         copy_size = p - p_start;
1576     }
1577 #elif defined(HOST_SPARC64)
1578     {
1579 #define INSN_SAVE       0x9de3a000
1580 #define INSN_RET        0x81c7e008
1581 #define INSN_RETL       0x81c3e008
1582 #define INSN_RESTORE    0x81e80000
1583 #define INSN_RETURN     0x81cfe008
1584 #define INSN_NOP        0x01000000
1585 #define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1586 #define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1587
1588         uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1589         uint8_t *p;
1590         p = (void *)(p_end - 8);
1591 #if 0
1592         /* XXX: check why it occurs */
1593         if (p <= p_start)
1594             error("empty code for %s", name);
1595 #endif
1596         start_insn = get32((uint32_t *)(p_start + 0x0));
1597         end_insn1 = get32((uint32_t *)(p + 0x0));
1598         end_insn2 = get32((uint32_t *)(p + 0x4));
1599         if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1600             (start_insn & ~0x1fff) == INSN_ADD_SP) {
1601             p_start += 0x4;
1602             start_offset += 0x4;
1603             if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1604                 /* SPARC v7: ret; restore; */ ;
1605             else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1606                 /* SPARC v9: return; nop; */ ;
1607             else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1608                 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1609             else
1610
1611                 error("ret; restore; not found at end of %s", name);
1612         } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1613             ;
1614         } else {
1615             error("No save at the beginning of %s", name);
1616         }
1617
1618 #if 0
1619         /* Skip a preceeding nop, if present.  */
1620         if (p > p_start) {
1621             skip_insn = get32((uint32_t *)(p - 0x4));
1622             if (skip_insn == 0x01000000)
1623                 p -= 4;
1624         }
1625 #endif
1626
1627         copy_size = p - p_start;
1628     }
1629 #elif defined(HOST_ARM)
1630     {
1631         uint32_t insn;
1632
1633         if ((p_end - p_start) <= 16)
1634             error("%s: function too small", name);
1635         if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1636             (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1637             get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1638             error("%s: invalid prolog", name);
1639         p_start += 12;
1640         start_offset += 12;
1641         insn = get32((uint32_t *)p_start);
1642         if ((insn & 0xffffff00) == 0xe24dd000) {
1643             /* Stack adjustment.  Assume op uses the frame pointer.  */
1644             p_start -= 4;
1645             start_offset -= 4;
1646         }
1647         copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1648                                       relocs, nb_relocs);
1649     }
1650 #elif defined(HOST_M68K)
1651     {
1652         uint8_t *p;
1653         p = (void *)(p_end - 2);
1654         if (p == p_start)
1655             error("empty code for %s", name);
1656         // remove NOP's, probably added for alignment
1657         while ((get16((uint16_t *)p) == 0x4e71) &&
1658                (p>p_start))
1659             p -= 2;
1660         if (get16((uint16_t *)p) != 0x4e75)
1661             error("rts expected at the end of %s", name);
1662         copy_size = p - p_start;
1663     }
1664 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1665     {
1666 #define INSN_RETURN     0x03e00008
1667 #define INSN_NOP        0x00000000
1668
1669         uint8_t *p = p_end;
1670
1671         if (p < (p_start + 0x8)) {
1672             error("empty code for %s", name);
1673         } else {
1674             uint32_t end_insn1, end_insn2;
1675
1676             p -= 0x8;
1677             end_insn1 = get32((uint32_t *)(p + 0x0));
1678             end_insn2 = get32((uint32_t *)(p + 0x4));
1679             if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1680                 error("jr ra not found at end of %s", name);
1681         }
1682         copy_size = p - p_start;
1683     }
1684 #else
1685 #error unsupported CPU
1686 #endif
1687
1688     /* compute the number of arguments by looking at the relocations */
1689     for(i = 0;i < MAX_ARGS; i++)
1690         args_present[i] = 0;
1691
1692     for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1693         host_ulong offset = get_rel_offset(rel);
1694         if (offset >= start_offset &&
1695             offset < start_offset + (p_end - p_start)) {
1696             sym_name = get_rel_sym_name(rel);
1697             if(!sym_name)
1698                 continue;
1699             if (strstart(sym_name, "__op_param", &p) ||
1700                 strstart(sym_name, "__op_gen_label", &p)) {
1701                 n = strtoul(p, NULL, 10);
1702                 if (n > MAX_ARGS)
1703                     error("too many arguments in %s", name);
1704                 args_present[n - 1] = 1;
1705             }
1706         }
1707     }
1708
1709     nb_args = 0;
1710     while (nb_args < MAX_ARGS && args_present[nb_args])
1711         nb_args++;
1712     for(i = nb_args; i < MAX_ARGS; i++) {
1713         if (args_present[i])
1714             error("inconsistent argument numbering in %s", name);
1715     }
1716
1717     if (gen_switch == 2) {
1718         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1719     } else if (gen_switch == 1) {
1720
1721         /* output C code */
1722         fprintf(outfile, "case INDEX_%s: {\n", name);
1723         if (nb_args > 0) {
1724             fprintf(outfile, "    long ");
1725             for(i = 0; i < nb_args; i++) {
1726                 if (i != 0)
1727                     fprintf(outfile, ", ");
1728                 fprintf(outfile, "param%d", i + 1);
1729             }
1730             fprintf(outfile, ";\n");
1731         }
1732 #if defined(HOST_IA64)
1733         fprintf(outfile, "    extern char %s;\n", name);
1734 #else
1735         fprintf(outfile, "    extern void %s();\n", name);
1736 #endif
1737
1738         for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1739             host_ulong offset = get_rel_offset(rel);
1740             if (offset >= start_offset &&
1741                 offset < start_offset + (p_end - p_start)) {
1742                 sym_name = get_rel_sym_name(rel);
1743                 if(!sym_name)
1744                     continue;
1745                 if (*sym_name &&
1746                     !strstart(sym_name, "__op_param", NULL) &&
1747                     !strstart(sym_name, "__op_jmp", NULL) &&
1748                     !strstart(sym_name, "__op_gen_label", NULL)) {
1749 #if defined(HOST_SPARC)
1750                     if (sym_name[0] == '.') {
1751                         fprintf(outfile,
1752                                 "extern char __dot_%s __asm__(\"%s\");\n",
1753                                 sym_name+1, sym_name);
1754                         continue;
1755                     }
1756 #endif
1757 #if defined(__APPLE__)
1758                     /* Set __attribute((unused)) on darwin because we
1759                        want to avoid warning when we don't use the symbol.  */
1760                     fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1761 #elif defined(HOST_IA64)
1762                         if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1763                                 /*
1764                                  * PCREL21 br.call targets generally
1765                                  * are out of range and need to go
1766                                  * through an "import stub".
1767                                  */
1768                                 fprintf(outfile, "    extern char %s;\n",
1769                                         sym_name);
1770 #else
1771                     fprintf(outfile, "extern char %s;\n", sym_name);
1772 #endif
1773                 }
1774             }
1775         }
1776
1777         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1778                                         name, (int)(start_offset - offset), copy_size);
1779
1780         /* emit code offset information */
1781         {
1782             EXE_SYM *sym;
1783             const char *sym_name, *p;
1784             host_ulong val;
1785             int n;
1786
1787             for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1788                 sym_name = get_sym_name(sym);
1789                 if (strstart(sym_name, "__op_label", &p)) {
1790                     uint8_t *ptr;
1791                     unsigned long offset;
1792
1793                     /* test if the variable refers to a label inside
1794                        the code we are generating */
1795 #ifdef CONFIG_FORMAT_COFF
1796                     if (sym->st_shndx == text_shndx) {
1797                         ptr = sdata[coff_text_shndx];
1798                     } else if (sym->st_shndx == data_shndx) {
1799                         ptr = sdata[coff_data_shndx];
1800                     } else {
1801                         ptr = NULL;
1802                     }
1803 #elif defined(CONFIG_FORMAT_MACH)
1804                     if(!sym->n_sect)
1805                         continue;
1806                     ptr = sdata[sym->n_sect-1];
1807 #else
1808                     ptr = sdata[sym->st_shndx];
1809 #endif
1810                     if (!ptr)
1811                         error("__op_labelN in invalid section");
1812                     offset = sym->st_value;
1813 #ifdef CONFIG_FORMAT_MACH
1814                     offset -= section_hdr[sym->n_sect-1].addr;
1815 #endif
1816                     val = *(host_ulong *)(ptr + offset);
1817 #ifdef ELF_USES_RELOCA
1818                     {
1819                         int reloc_shndx, nb_relocs1, j;
1820
1821                         /* try to find a matching relocation */
1822                         reloc_shndx = find_reloc(sym->st_shndx);
1823                         if (reloc_shndx) {
1824                             nb_relocs1 = shdr[reloc_shndx].sh_size /
1825                                 shdr[reloc_shndx].sh_entsize;
1826                             rel = (ELF_RELOC *)sdata[reloc_shndx];
1827                             for(j = 0; j < nb_relocs1; j++) {
1828                                 if (rel->r_offset == offset) {
1829                                     val = rel->r_addend;
1830                                     break;
1831                                 }
1832                                 rel++;
1833                             }
1834                         }
1835                     }
1836 #endif
1837                     if (val >= start_offset && val <= start_offset + copy_size) {
1838                         n = strtol(p, NULL, 10);
1839                         fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1840                     }
1841                 }
1842             }
1843         }
1844
1845         /* load parameters in variables */
1846         for(i = 0; i < nb_args; i++) {
1847             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1848         }
1849
1850         /* patch relocations */
1851 #if defined(HOST_I386)
1852             {
1853                 char relname[256];
1854                 int type, is_label;
1855                 int addend;
1856                 int reloc_offset;
1857                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1858                 if (rel->r_offset >= start_offset &&
1859                     rel->r_offset < start_offset + copy_size) {
1860                     sym_name = get_rel_sym_name(rel);
1861                     if (!sym_name)
1862                         continue;
1863                     reloc_offset = rel->r_offset - start_offset;
1864                     if (strstart(sym_name, "__op_jmp", &p)) {
1865                         int n;
1866                         n = strtol(p, NULL, 10);
1867                         /* __op_jmp relocations are done at
1868                            runtime to do translated block
1869                            chaining: the offset of the instruction
1870                            needs to be stored */
1871                         fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1872                                 n, reloc_offset);
1873                         continue;
1874                     }
1875
1876                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1877                     addend = get32((uint32_t *)(text + rel->r_offset));
1878 #ifdef CONFIG_FORMAT_ELF
1879                     type = ELF32_R_TYPE(rel->r_info);
1880                     if (is_label) {
1881                         switch(type) {
1882                         case R_386_32:
1883                         case R_386_PC32:
1884                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1885                                     reloc_offset, type, relname, addend);
1886                             break;
1887                         default:
1888                             error("unsupported i386 relocation (%d)", type);
1889                         }
1890                     } else {
1891                         switch(type) {
1892                         case R_386_32:
1893                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1894                                     reloc_offset, relname, addend);
1895                             break;
1896                         case R_386_PC32:
1897                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1898                                     reloc_offset, relname, reloc_offset, addend);
1899                             break;
1900                         default:
1901                             error("unsupported i386 relocation (%d)", type);
1902                         }
1903                     }
1904 #elif defined(CONFIG_FORMAT_COFF)
1905                     {
1906                         char *temp_name;
1907                         int j;
1908                         EXE_SYM *sym;
1909                         temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1910                         if (!strcmp(temp_name, ".data")) {
1911                             for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1912                                 if (strstart(sym->st_name, sym_name, NULL)) {
1913                                     addend -= sym->st_value;
1914                                 }
1915                             }
1916                         }
1917                     }
1918                     type = rel->r_type;
1919                     if (is_label) {
1920 /* TCG uses elf relocation constants */
1921 #define R_386_32        1
1922 #define R_386_PC32      2
1923                         switch(type) {
1924                         case DIR32:
1925                             type = R_386_32;
1926                             goto do_reloc;
1927                         case DISP32:
1928                             type = R_386_PC32;
1929                             addend -= 4;
1930                         do_reloc:
1931                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1932                                     reloc_offset, type, relname, addend);
1933                             break;
1934                         default:
1935                             error("unsupported i386 relocation (%d)", type);
1936                         }
1937                     } else {
1938                         switch(type) {
1939                         case DIR32:
1940                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1941                                     reloc_offset, relname, addend);
1942                             break;
1943                         case DISP32:
1944                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1945                                     reloc_offset, relname, reloc_offset, addend);
1946                             break;
1947                         default:
1948                             error("unsupported i386 relocation (%d)", type);
1949                         }
1950                     }
1951 #else
1952 #error unsupport object format
1953 #endif
1954                 }
1955                 }
1956             }
1957 #elif defined(HOST_X86_64)
1958             {
1959                 char relname[256];
1960                 int type, is_label;
1961                 int addend;
1962                 int reloc_offset;
1963                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1964                 if (rel->r_offset >= start_offset &&
1965                     rel->r_offset < start_offset + copy_size) {
1966                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1967                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1968                     type = ELF32_R_TYPE(rel->r_info);
1969                     addend = rel->r_addend;
1970                     reloc_offset = rel->r_offset - start_offset;
1971                     if (is_label) {
1972                         switch(type) {
1973                         case R_X86_64_32:
1974                         case R_X86_64_32S:
1975                         case R_X86_64_PC32:
1976                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1977                                     reloc_offset, type, relname, addend);
1978                             break;
1979                         default:
1980                             error("unsupported X86_64 relocation (%d)", type);
1981                         }
1982                     } else {
1983                         switch(type) {
1984                         case R_X86_64_32:
1985                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1986                                     reloc_offset, relname, addend);
1987                             break;
1988                         case R_X86_64_32S:
1989                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1990                                     reloc_offset, relname, addend);
1991                             break;
1992                         case R_X86_64_PC32:
1993                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1994                                     reloc_offset, relname, reloc_offset, addend);
1995                             break;
1996                         default:
1997                             error("unsupported X86_64 relocation (%d)", type);
1998                         }
1999                     }
2000                 }
2001                 }
2002             }
2003 #elif defined(HOST_PPC)
2004             {
2005 #ifdef CONFIG_FORMAT_ELF
2006                 char relname[256];
2007                 int type;
2008                 int addend;
2009                 int reloc_offset;
2010                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2011                     if (rel->r_offset >= start_offset &&
2012                         rel->r_offset < start_offset + copy_size) {
2013                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2014                         reloc_offset = rel->r_offset - start_offset;
2015                         if (strstart(sym_name, "__op_jmp", &p)) {
2016                             int n;
2017                             n = strtol(p, NULL, 10);
2018                             /* __op_jmp relocations are done at
2019                                runtime to do translated block
2020                                chaining: the offset of the instruction
2021                                needs to be stored */
2022                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2023                                     n, reloc_offset);
2024                             continue;
2025                         }
2026
2027                         get_reloc_expr(relname, sizeof(relname), sym_name);
2028                         type = ELF32_R_TYPE(rel->r_info);
2029                         addend = rel->r_addend;
2030                         switch(type) {
2031                         case R_PPC_ADDR32:
2032                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2033                                     reloc_offset, relname, addend);
2034                             break;
2035                         case R_PPC_ADDR16_LO:
2036                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2037                                     reloc_offset, relname, addend);
2038                             break;
2039                         case R_PPC_ADDR16_HI:
2040                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2041                                     reloc_offset, relname, addend);
2042                             break;
2043                         case R_PPC_ADDR16_HA:
2044                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2045                                     reloc_offset, relname, addend);
2046                             break;
2047                         case R_PPC_REL24:
2048                             /* warning: must be at 32 MB distancy */
2049                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2050                                     reloc_offset, reloc_offset, relname, reloc_offset, addend);
2051                             break;
2052                         default:
2053                             error("unsupported powerpc relocation (%d)", type);
2054                         }
2055                     }
2056                 }
2057 #elif defined(CONFIG_FORMAT_MACH)
2058                 struct scattered_relocation_info *scarel;
2059                 struct relocation_info * rel;
2060                 char final_sym_name[256];
2061                 const char *sym_name;
2062                 const char *p;
2063                 int slide, sslide;
2064                 int i;
2065
2066                 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2067                     unsigned int offset, length, value = 0;
2068                     unsigned int type, pcrel, isym = 0;
2069                     unsigned int usesym = 0;
2070
2071                     if(R_SCATTERED & rel->r_address) {
2072                         scarel = (struct scattered_relocation_info*)rel;
2073                         offset = (unsigned int)scarel->r_address;
2074                         length = scarel->r_length;
2075                         pcrel = scarel->r_pcrel;
2076                         type = scarel->r_type;
2077                         value = scarel->r_value;
2078                     } else {
2079                         value = isym = rel->r_symbolnum;
2080                         usesym = (rel->r_extern);
2081                         offset = rel->r_address;
2082                         length = rel->r_length;
2083                         pcrel = rel->r_pcrel;
2084                         type = rel->r_type;
2085                     }
2086
2087                     slide = offset - start_offset;
2088
2089                     if (!(offset >= start_offset && offset < start_offset + size))
2090                         continue;  /* not in our range */
2091
2092                         sym_name = get_reloc_name(rel, &sslide);
2093
2094                         if(usesym && symtab[isym].n_type & N_STAB)
2095                             continue; /* don't handle STAB (debug sym) */
2096
2097                         if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2098                             int n;
2099                             n = strtol(p, NULL, 10);
2100                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2101                                     n, slide);
2102                             continue; /* Nothing more to do */
2103                         }
2104
2105                         if(!sym_name) {
2106                             fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2107                                     name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2108                             continue; /* dunno how to handle without final_sym_name */
2109                         }
2110
2111                         get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2112                                        sym_name);
2113                         switch(type) {
2114                         case PPC_RELOC_BR24:
2115                             if (!strstart(sym_name,"__op_gen_label",&p)) {
2116                                 fprintf(outfile, "{\n");
2117                                 fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2118                                 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",
2119                                         slide, slide, name, sslide);
2120                                 fprintf(outfile, "}\n");
2121                             } else {
2122                                 fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2123                                         slide, slide, final_sym_name, slide);
2124                             }
2125                             break;
2126                         case PPC_RELOC_HI16:
2127                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2128                                     slide, final_sym_name, sslide);
2129                             break;
2130                         case PPC_RELOC_LO16:
2131                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2132                                     slide, final_sym_name, sslide);
2133                             break;
2134                         case PPC_RELOC_HA16:
2135                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2136                                     slide, final_sym_name, sslide);
2137                             break;
2138                         default:
2139                             error("unsupported powerpc relocation (%d)", type);
2140                     }
2141                 }
2142 #else
2143 #error unsupport object format
2144 #endif
2145             }
2146 #elif defined(HOST_S390)
2147             {
2148                 char relname[256];
2149                 int type;
2150                 int addend;
2151                 int reloc_offset;
2152                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2153                     if (rel->r_offset >= start_offset &&
2154                         rel->r_offset < start_offset + copy_size) {
2155                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2156                         get_reloc_expr(relname, sizeof(relname), sym_name);
2157                         type = ELF32_R_TYPE(rel->r_info);
2158                         addend = rel->r_addend;
2159                         reloc_offset = rel->r_offset - start_offset;
2160                         switch(type) {
2161                         case R_390_32:
2162                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2163                                     reloc_offset, relname, addend);
2164                             break;
2165                         case R_390_16:
2166                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2167                                     reloc_offset, relname, addend);
2168                             break;
2169                         case R_390_8:
2170                             fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2171                                     reloc_offset, relname, addend);
2172                             break;
2173                         case R_390_PC32DBL:
2174                             if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2175                                 fprintf(outfile,
2176                                         "    *(uint32_t *)(gen_code_ptr + %d) += "
2177                                         "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2178                                         reloc_offset, name);
2179                             }
2180                             else
2181                                 fprintf(outfile,
2182                                         "    *(uint32_t *)(gen_code_ptr + %d) = "
2183                                         "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2184                                         reloc_offset, relname, addend, reloc_offset);
2185                             break;
2186                         default:
2187                             error("unsupported s390 relocation (%d)", type);
2188                         }
2189                     }
2190                 }
2191             }
2192 #elif defined(HOST_ALPHA)
2193             {
2194                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2195                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2196                         int type;
2197                         long reloc_offset;
2198
2199                         type = ELF64_R_TYPE(rel->r_info);
2200                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2201                         reloc_offset = rel->r_offset - start_offset;
2202                         switch (type) {
2203                         case R_ALPHA_GPDISP:
2204                             /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2205                                as an immediate instead of constructing it from the pv or ra.  */
2206                             fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2207                                     reloc_offset);
2208                             fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2209                                     reloc_offset + (int)rel->r_addend);
2210                             break;
2211                         case R_ALPHA_LITUSE:
2212                             /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2213                                now, since some called functions (libc) need pv to be set up.  */
2214                             break;
2215                         case R_ALPHA_HINT:
2216                             /* Branch target prediction hint. Ignore for now.  Should be already
2217                                correct for in-function jumps.  */
2218                             break;
2219                         case R_ALPHA_LITERAL:
2220                             /* Load a literal from the GOT relative to the gp.  Since there's only a
2221                                single gp, nothing is to be done.  */
2222                             break;
2223                         case R_ALPHA_GPRELHIGH:
2224                             /* Handle fake relocations against __op_param symbol.  Need to emit the
2225                                high part of the immediate value instead.  Other symbols need no
2226                                special treatment.  */
2227                             if (strstart(sym_name, "__op_param", &p))
2228                                 fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2229                                         reloc_offset, p);
2230                             break;
2231                         case R_ALPHA_GPRELLOW:
2232                             if (strstart(sym_name, "__op_param", &p))
2233                                 fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2234                                         reloc_offset, p);
2235                             break;
2236                         case R_ALPHA_BRSGP:
2237                             /* PC-relative jump. Tweak offset to skip the two instructions that try to
2238                                set up the gp from the pv.  */
2239                             fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2240                                     reloc_offset, sym_name, reloc_offset);
2241                             break;
2242                         default:
2243                             error("unsupported Alpha relocation (%d)", type);
2244                         }
2245                     }
2246                 }
2247             }
2248 #elif defined(HOST_IA64)
2249             {
2250                 unsigned long sym_idx;
2251                 long code_offset;
2252                 char relname[256];
2253                 int type;
2254                 long addend;
2255
2256                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2257                     sym_idx = ELF64_R_SYM(rel->r_info);
2258                     if (rel->r_offset < start_offset
2259                         || rel->r_offset >= start_offset + copy_size)
2260                         continue;
2261                     sym_name = (strtab + symtab[sym_idx].st_name);
2262                     code_offset = rel->r_offset - start_offset;
2263                     if (strstart(sym_name, "__op_jmp", &p)) {
2264                         int n;
2265                         n = strtol(p, NULL, 10);
2266                         /* __op_jmp relocations are done at
2267                            runtime to do translated block
2268                            chaining: the offset of the instruction
2269                            needs to be stored */
2270                         fprintf(outfile, "    jmp_offsets[%d] ="
2271                                 "%ld + (gen_code_ptr - gen_code_buf);\n",
2272                                 n, code_offset);
2273                         continue;
2274                     }
2275                     get_reloc_expr(relname, sizeof(relname), sym_name);
2276                     type = ELF64_R_TYPE(rel->r_info);
2277                     addend = rel->r_addend;
2278                     switch(type) {
2279                       case R_IA64_IMM64:
2280                           fprintf(outfile,
2281                                   "    ia64_imm64(gen_code_ptr + %ld, "
2282                                   "%s + %ld);\n",
2283                                   code_offset, relname, addend);
2284                           break;
2285                       case R_IA64_LTOFF22X:
2286                       case R_IA64_LTOFF22:
2287                           fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2288                                   " %s + %ld, %d);\n",
2289                                   code_offset, relname, addend,
2290                                   (type == R_IA64_LTOFF22X));
2291                           break;
2292                       case R_IA64_LDXMOV:
2293                           fprintf(outfile,
2294                                   "    ia64_ldxmov(gen_code_ptr + %ld,"
2295                                   " %s + %ld);\n", code_offset, relname, addend);
2296                           break;
2297
2298                       case R_IA64_PCREL21B:
2299                           if (strstart(sym_name, "__op_gen_label", NULL)) {
2300                               fprintf(outfile,
2301                                       "    ia64_imm21b(gen_code_ptr + %ld,"
2302                                       " (long) (%s + %ld -\n\t\t"
2303                                       "((long) gen_code_ptr + %ld)) >> 4);\n",
2304                                       code_offset, relname, addend,
2305                                       code_offset & ~0xfUL);
2306                           } else {
2307                               fprintf(outfile,
2308                                       "    IA64_PLT(gen_code_ptr + %ld, "
2309                                       "%d);\t/* %s + %ld */\n",
2310                                       code_offset,
2311                                       get_plt_index(sym_name, addend),
2312                                       sym_name, addend);
2313                           }
2314                           break;
2315                       default:
2316                           error("unsupported ia64 relocation (0x%x)",
2317                                 type);
2318                     }
2319                 }
2320                 fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2321                         copy_size - 16 + 2);
2322             }
2323 #elif defined(HOST_SPARC)
2324             {
2325                 char relname[256];
2326                 int type;
2327                 int addend;
2328                 int reloc_offset;
2329                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2330                     if (rel->r_offset >= start_offset &&
2331                         rel->r_offset < start_offset + copy_size) {
2332                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2333                         get_reloc_expr(relname, sizeof(relname), sym_name);
2334                         type = ELF32_R_TYPE(rel->r_info);
2335                         addend = rel->r_addend;
2336                         reloc_offset = rel->r_offset - start_offset;
2337                         switch(type) {
2338                         case R_SPARC_32:
2339                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2340                                     reloc_offset, relname, addend);
2341                             break;
2342                         case R_SPARC_HI22:
2343                             fprintf(outfile,
2344                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2345                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2346                                     " & ~0x3fffff) "
2347                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2348                                     reloc_offset, reloc_offset, relname, addend);
2349                             break;
2350                         case R_SPARC_LO10:
2351                             fprintf(outfile,
2352                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2353                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2354                                     " & ~0x3ff) "
2355                                     " | ((%s + %d) & 0x3ff);\n",
2356                                     reloc_offset, reloc_offset, relname, addend);
2357                             break;
2358                         case R_SPARC_WDISP30:
2359                             fprintf(outfile,
2360                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2361                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2362                                     " & ~0x3fffffff) "
2363                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2364                                     "    & 0x3fffffff);\n",
2365                                     reloc_offset, reloc_offset, relname, addend,
2366                                     reloc_offset);
2367                             break;
2368                         case R_SPARC_WDISP22:
2369                             fprintf(outfile,
2370                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2371                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2372                                     " & ~0x3fffff) "
2373                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2374                                     "    & 0x3fffff);\n",
2375                                     rel->r_offset - start_offset,
2376                                     rel->r_offset - start_offset,
2377                                     relname, addend,
2378                                     rel->r_offset - start_offset);
2379                             break;
2380                         default:
2381                             error("unsupported sparc relocation (%d)", type);
2382                         }
2383                     }
2384                 }
2385             }
2386 #elif defined(HOST_SPARC64)
2387             {
2388                 char relname[256];
2389                 int type;
2390                 int addend;
2391                 int reloc_offset;
2392                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2393                     if (rel->r_offset >= start_offset &&
2394                         rel->r_offset < start_offset + copy_size) {
2395                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2396                         get_reloc_expr(relname, sizeof(relname), sym_name);
2397                         type = ELF32_R_TYPE(rel->r_info);
2398                         addend = rel->r_addend;
2399                         reloc_offset = rel->r_offset - start_offset;
2400                         switch(type) {
2401                         case R_SPARC_32:
2402                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2403                                     reloc_offset, relname, addend);
2404                             break;
2405                         case R_SPARC_HI22:
2406                             fprintf(outfile,
2407                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2408                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2409                                     " & ~0x3fffff) "
2410                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2411                                     reloc_offset, reloc_offset, relname, addend);
2412                             break;
2413                         case R_SPARC_LO10:
2414                             fprintf(outfile,
2415                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2416                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2417                                     " & ~0x3ff) "
2418                                     " | ((%s + %d) & 0x3ff);\n",
2419                                     reloc_offset, reloc_offset, relname, addend);
2420                             break;
2421                         case R_SPARC_OLO10:
2422                             addend += ELF64_R_TYPE_DATA (rel->r_info);
2423                             fprintf(outfile,
2424                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2425                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2426                                     " & ~0x3ff) "
2427                                     " | ((%s + %d) & 0x3ff);\n",
2428                                     reloc_offset, reloc_offset, relname, addend);
2429                             break;
2430                         case R_SPARC_WDISP30:
2431                             fprintf(outfile,
2432                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2433                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2434                                     " & ~0x3fffffff) "
2435                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2436                                     "    & 0x3fffffff);\n",
2437                                     reloc_offset, reloc_offset, relname, addend,
2438                                     reloc_offset);
2439                             break;
2440                         case R_SPARC_WDISP22:
2441                             fprintf(outfile,
2442                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2443                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2444                                     " & ~0x3fffff) "
2445                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2446                                     "    & 0x3fffff);\n",
2447                                     reloc_offset, reloc_offset, relname, addend,
2448                                     reloc_offset);
2449                             break;
2450                         case R_SPARC_HH22:
2451                             fprintf(outfile,
2452                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2453                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2454                                     " & ~0x00000000) "
2455                                     " | (((%s + %d) >> 42) & 0x00000000);\n",
2456                                     reloc_offset, reloc_offset, relname, addend);
2457                              break;
2458
2459                         case R_SPARC_LM22:
2460                             fprintf(outfile,
2461                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2462                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2463                                     " & ~0x00000000) "
2464                                     " | (((%s + %d) >> 10) & 0x00000000);\n",
2465                                     reloc_offset, reloc_offset, relname, addend);
2466                             break;
2467
2468                         case R_SPARC_HM10:
2469                             fprintf(outfile,
2470                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2471                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2472                                     " & ~0x00000000) "
2473                                     " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2474                                     reloc_offset, reloc_offset, relname, addend);
2475                             break;
2476
2477                         default:
2478                             error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2479                         }
2480                     }
2481                 }
2482             }
2483 #elif defined(HOST_ARM)
2484             {
2485                 char relname[256];
2486                 int type;
2487                 int addend;
2488                 int reloc_offset;
2489                 uint32_t insn;
2490
2491                 insn = get32((uint32_t *)(p_start + 4));
2492                 /* If prologue ends in sub sp, sp, #const then assume
2493                    op has a stack frame and needs the frame pointer.  */
2494                 if ((insn & 0xffffff00) == 0xe24dd000) {
2495                     int i;
2496                     uint32_t opcode;
2497                     opcode = 0xe28db000; /* add fp, sp, #0.  */
2498 #if 0
2499 /* ??? Need to undo the extra stack adjustment at the end of the op.
2500    For now just leave the stack misaligned and hope it doesn't break anything
2501    too important.  */
2502                     if ((insn & 4) != 0) {
2503                         /* Preserve doubleword stack alignment.  */
2504                         fprintf(outfile,
2505                                 "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2506                                 insn + 4);
2507                         opcode -= 4;
2508                     }
2509 #endif
2510                     insn = get32((uint32_t *)(p_start - 4));
2511                     /* Calculate the size of the saved registers,
2512                        excluding pc.  */
2513                     for (i = 0; i < 15; i++) {
2514                         if (insn & (1 << i))
2515                             opcode += 4;
2516                     }
2517                     fprintf(outfile,
2518                             "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2519                 }
2520                 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2521                                   relocs, nb_relocs);
2522
2523                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2524                 if (rel->r_offset >= start_offset &&
2525                     rel->r_offset < start_offset + copy_size) {
2526                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2527                     /* the compiler leave some unnecessary references to the code */
2528                     if (sym_name[0] == '\0')
2529                         continue;
2530                     get_reloc_expr(relname, sizeof(relname), sym_name);
2531                     type = ELF32_R_TYPE(rel->r_info);
2532                     addend = get32((uint32_t *)(text + rel->r_offset));
2533                     reloc_offset = rel->r_offset - start_offset;
2534                     switch(type) {
2535                     case R_ARM_ABS32:
2536                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2537                                 reloc_offset, relname, addend);
2538                         break;
2539                     case R_ARM_PC24:
2540                     case R_ARM_JUMP24:
2541                     case R_ARM_CALL:
2542                         fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2543                                 reloc_offset, addend, relname);
2544                         break;
2545                     default:
2546                         error("unsupported arm relocation (%d)", type);
2547                     }
2548                 }
2549                 }
2550             }
2551 #elif defined(HOST_M68K)
2552             {
2553                 char relname[256];
2554                 int type;
2555                 int addend;
2556                 int reloc_offset;
2557                 Elf32_Sym *sym;
2558                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2559                 if (rel->r_offset >= start_offset &&
2560                     rel->r_offset < start_offset + copy_size) {
2561                     sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2562                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2563                     get_reloc_expr(relname, sizeof(relname), sym_name);
2564                     type = ELF32_R_TYPE(rel->r_info);
2565                     addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2566                     reloc_offset = rel->r_offset - start_offset;
2567                     switch(type) {
2568                     case R_68K_32:
2569                         fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2570                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2571                                 reloc_offset, relname, addend );
2572                         break;
2573                     case R_68K_PC32:
2574                         fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2575                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2576                                 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2577                         break;
2578                     default:
2579                         error("unsupported m68k relocation (%d)", type);
2580                     }
2581                 }
2582                 }
2583             }
2584 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2585             {
2586                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2587                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2588                         char relname[256];
2589                         int type;
2590                         int addend;
2591                         int reloc_offset;
2592
2593                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2594                         /* the compiler leave some unnecessary references to the code */
2595                         if (sym_name[0] == '\0')
2596                             continue;
2597                         get_reloc_expr(relname, sizeof(relname), sym_name);
2598                         type = ELF32_R_TYPE(rel->r_info);
2599                         addend = get32((uint32_t *)(text + rel->r_offset));
2600                         reloc_offset = rel->r_offset - start_offset;
2601                         switch (type) {
2602                         case R_MIPS_26:
2603                             fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2604                                     rel->r_offset, sym_name);
2605                             fprintf(outfile,
2606                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2607                                     "(0x%x & ~0x3fffff) "
2608                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2609                                     "   & 0x3fffff);\n",
2610                                     reloc_offset, addend, addend, relname, reloc_offset);
2611                             break;
2612                         case R_MIPS_HI16:
2613                             fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2614                                     rel->r_offset, sym_name);
2615                             fprintf(outfile,
2616                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2617                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2618                                     " & ~0xffff) "
2619                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2620                                     reloc_offset, reloc_offset, relname);
2621                             break;
2622                         case R_MIPS_LO16:
2623                             fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2624                                     rel->r_offset, sym_name);
2625                             fprintf(outfile,
2626                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2627                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2628                                     " & ~0xffff) "
2629                                     " | (%s & 0xffff);\n",
2630                                     reloc_offset, reloc_offset, relname);
2631                             break;
2632                         case R_MIPS_PC16:
2633                             fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2634                                     rel->r_offset, sym_name);
2635                             fprintf(outfile,
2636                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2637                                     "(0x%x & ~0xffff) "
2638                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2639                                     "   & 0xffff);\n",
2640                                     reloc_offset, addend, addend, relname, reloc_offset);
2641                             break;
2642                         case R_MIPS_GOT16:
2643                         case R_MIPS_CALL16:
2644                             fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2645                                     rel->r_offset, sym_name);
2646                             fprintf(outfile,
2647                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2648                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2649                                     " & ~0xffff) "
2650                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2651                                     reloc_offset, reloc_offset, relname);
2652                             break;
2653                         default:
2654                             error("unsupported MIPS relocation (%d)", type);
2655                         }
2656                     }
2657                 }
2658             }
2659 #else
2660 #error unsupported CPU
2661 #endif
2662         fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2663         fprintf(outfile, "}\n");
2664         fprintf(outfile, "break;\n\n");
2665     } else {
2666         fprintf(outfile, "static inline void gen_%s(", name);
2667         if (nb_args == 0) {
2668             fprintf(outfile, "void");
2669         } else {
2670             for(i = 0; i < nb_args; i++) {
2671                 if (i != 0)
2672                     fprintf(outfile, ", ");
2673                 fprintf(outfile, "long param%d", i + 1);
2674             }
2675         }
2676         fprintf(outfile, ")\n");
2677         fprintf(outfile, "{\n");
2678         for(i = 0; i < nb_args; i++) {
2679             fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2680         }
2681         fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2682         fprintf(outfile, "}\n\n");
2683     }
2684 }
2685
2686 int gen_file(FILE *outfile, int out_type)
2687 {
2688     int i;
2689     EXE_SYM *sym;
2690
2691     if (out_type == OUT_INDEX_OP) {
2692         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2693             const char *name;
2694             name = get_sym_name(sym);
2695             if (strstart(name, OP_PREFIX, NULL)) {
2696                 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2697             }
2698         }
2699     } else if (out_type == OUT_GEN_OP) {
2700         /* generate gen_xxx functions */
2701         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2702             const char *name;
2703             name = get_sym_name(sym);
2704             if (strstart(name, OP_PREFIX, NULL)) {
2705 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2706                 if (sym->st_shndx != text_shndx)
2707                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2708 #endif
2709                 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2710             }
2711         }
2712
2713     } else {
2714         /* generate big code generation switch */
2715
2716 #ifdef HOST_ARM
2717 #error broken
2718         /* We need to know the size of all the ops so we can figure out when
2719            to emit constant pools.  This must be consistent with opc.h.  */
2720 fprintf(outfile,
2721 "static const uint32_t arm_opc_size[] = {\n"
2722 "  0,\n" /* end */
2723 "  0,\n" /* nop */
2724 "  0,\n" /* nop1 */
2725 "  0,\n" /* nop2 */
2726 "  0,\n"); /* nop3 */
2727         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2728             const char *name;
2729             name = get_sym_name(sym);
2730             if (strstart(name, OP_PREFIX, NULL)) {
2731                 fprintf(outfile, "  %d,\n", sym->st_size);
2732             }
2733         }
2734 fprintf(outfile,
2735 "};\n");
2736 #endif
2737
2738 #ifdef HOST_ARM
2739 #error broken
2740 /* Arm is tricky because it uses constant pools for loading immediate values.
2741    We assume (and require) each function is code followed by a constant pool.
2742    All the ops are small so this should be ok.  For each op we figure
2743    out how much "spare" range we have in the load instructions.  This allows
2744    us to insert subsequent ops in between the op and the constant pool,
2745    eliminating the neeed to jump around the pool.
2746
2747    We currently generate:
2748
2749    [ For this example we assume merging would move op1_pool out of range.
2750      In practice we should be able to combine many ops before the offset
2751      limits are reached. ]
2752    op1_code;
2753    op2_code;
2754    goto op3;
2755    op2_pool;
2756    op1_pool;
2757 op3:
2758    op3_code;
2759    ret;
2760    op3_pool;
2761
2762    Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2763  */
2764 fprintf(outfile,
2765 "    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2766 "    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2767 "    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2768 /* Initialise the parmissible pool offset to an arbitary large value.  */
2769 "    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2770 #endif
2771 #ifdef HOST_IA64
2772 #error broken
2773     {
2774         long addend, not_first = 0;
2775         unsigned long sym_idx;
2776         int index, max_index;
2777         const char *sym_name;
2778         EXE_RELOC *rel;
2779
2780         max_index = -1;
2781         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2782             sym_idx = ELF64_R_SYM(rel->r_info);
2783             sym_name = (strtab + symtab[sym_idx].st_name);
2784             if (strstart(sym_name, "__op_gen_label", NULL))
2785                 continue;
2786             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2787                 continue;
2788
2789             addend = rel->r_addend;
2790             index = get_plt_index(sym_name, addend);
2791             if (index <= max_index)
2792                 continue;
2793             max_index = index;
2794             fprintf(outfile, "    extern void %s(void);\n", sym_name);
2795         }
2796
2797         fprintf(outfile,
2798                 "    struct ia64_fixup *plt_fixes = NULL, "
2799                 "*ltoff_fixes = NULL;\n"
2800                 "    static long plt_target[] = {\n\t");
2801
2802         max_index = -1;
2803         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2804             sym_idx = ELF64_R_SYM(rel->r_info);
2805             sym_name = (strtab + symtab[sym_idx].st_name);
2806             if (strstart(sym_name, "__op_gen_label", NULL))
2807                 continue;
2808             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2809                 continue;
2810
2811             addend = rel->r_addend;
2812             index = get_plt_index(sym_name, addend);
2813             if (index <= max_index)
2814                 continue;
2815             max_index = index;
2816
2817             if (not_first)
2818                 fprintf(outfile, ",\n\t");
2819             not_first = 1;
2820             if (addend)
2821                 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2822             else
2823                 fprintf(outfile, "(long) &%s", sym_name);
2824         }
2825         fprintf(outfile, "\n    };\n"
2826             "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2827     }
2828 #endif
2829
2830 #ifdef HOST_ARM
2831 #error broken
2832 /* Generate constant pool if needed */
2833 fprintf(outfile,
2834 "            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2835 "                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2836 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2837 "                last_gen_code_ptr = gen_code_ptr;\n"
2838 "                arm_ldr_ptr = arm_ldr_table;\n"
2839 "                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2840 "                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2841 "            }\n");
2842 #endif
2843
2844         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2845             const char *name;
2846             name = get_sym_name(sym);
2847             if (strstart(name, OP_PREFIX, NULL)) {
2848 #if 0
2849                 printf("%4d: %s pos=0x%08x len=%d\n",
2850                        i, name, sym->st_value, sym->st_size);
2851 #endif
2852 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2853                 if (sym->st_shndx != text_shndx)
2854                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2855 #endif
2856                 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2857             }
2858         }
2859     }
2860
2861     return 0;
2862 }
2863
2864 void usage(void)
2865 {
2866     printf("dyngen (c) 2003 Fabrice Bellard\n"
2867            "usage: dyngen [-o outfile] [-c] objfile\n"
2868            "Generate a dynamic code generator from an object file\n"
2869            "-c     output enum of operations\n"
2870            "-g     output gen_op_xx() functions\n"
2871            );
2872     exit(1);
2873 }
2874
2875 int main(int argc, char **argv)
2876 {
2877     int c, out_type;
2878     const char *filename, *outfilename;
2879     FILE *outfile;
2880
2881     outfilename = "out.c";
2882     out_type = OUT_CODE;
2883     for(;;) {
2884         c = getopt(argc, argv, "ho:cg");
2885         if (c == -1)
2886             break;
2887         switch(c) {
2888         case 'h':
2889             usage();
2890             break;
2891         case 'o':
2892             outfilename = optarg;
2893             break;
2894         case 'c':
2895             out_type = OUT_INDEX_OP;
2896             break;
2897         case 'g':
2898             out_type = OUT_GEN_OP;
2899             break;
2900         }
2901     }
2902     if (optind >= argc)
2903         usage();
2904     filename = argv[optind];
2905     outfile = fopen(outfilename, "w");
2906     if (!outfile)
2907         error("could not open '%s'", outfilename);
2908
2909     load_object(filename);
2910     gen_file(outfile, out_type);
2911     fclose(outfile);
2912     return 0;
2913 }