qemu_put signedness fixes, by Andre Przywara.
[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 void get_reloc_expr(char *name, int name_size, const char *sym_name)
1216 {
1217     const char *p;
1218
1219     if (strstart(sym_name, "__op_param", &p)) {
1220         snprintf(name, name_size, "param%s", p);
1221     } else if (strstart(sym_name, "__op_gen_label", &p)) {
1222         snprintf(name, name_size, "gen_labels[param%s]", p);
1223     } else {
1224 #ifdef HOST_SPARC
1225         if (sym_name[0] == '.')
1226             snprintf(name, name_size,
1227                      "(long)(&__dot_%s)",
1228                      sym_name + 1);
1229         else
1230 #endif
1231             snprintf(name, name_size, "(long)(&%s)", sym_name);
1232     }
1233 }
1234
1235 #ifdef HOST_IA64
1236
1237 #define PLT_ENTRY_SIZE  16      /* 1 bundle containing "brl" */
1238
1239 struct plt_entry {
1240     struct plt_entry *next;
1241     const char *name;
1242     unsigned long addend;
1243 } *plt_list;
1244
1245 static int
1246 get_plt_index (const char *name, unsigned long addend)
1247 {
1248     struct plt_entry *plt, *prev= NULL;
1249     int index = 0;
1250
1251     /* see if we already have an entry for this target: */
1252     for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1253         if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1254             return index;
1255
1256     /* nope; create a new PLT entry: */
1257
1258     plt = malloc(sizeof(*plt));
1259     if (!plt) {
1260         perror("malloc");
1261         exit(1);
1262     }
1263     memset(plt, 0, sizeof(*plt));
1264     plt->name = strdup(name);
1265     plt->addend = addend;
1266
1267     /* append to plt-list: */
1268     if (prev)
1269         prev->next = plt;
1270     else
1271         plt_list = plt;
1272     return index;
1273 }
1274
1275 #endif
1276
1277 #ifdef HOST_ARM
1278
1279 int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1280                       FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1281                       ELF_RELOC *relocs, int nb_relocs)
1282 {
1283     uint8_t *p;
1284     uint32_t insn;
1285     int offset, min_offset, pc_offset, data_size, spare, max_pool;
1286     uint8_t data_allocated[1024];
1287     unsigned int data_index;
1288     int type;
1289
1290     memset(data_allocated, 0, sizeof(data_allocated));
1291
1292     p = p_start;
1293     min_offset = p_end - p_start;
1294     spare = 0x7fffffff;
1295     while (p < p_start + min_offset) {
1296         insn = get32((uint32_t *)p);
1297         /* TODO: Armv5e ldrd.  */
1298         /* TODO: VFP load.  */
1299         if ((insn & 0x0d5f0000) == 0x051f0000) {
1300             /* ldr reg, [pc, #im] */
1301             offset = insn & 0xfff;
1302             if (!(insn & 0x00800000))
1303                 offset = -offset;
1304             max_pool = 4096;
1305             type = 0;
1306         } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1307             /* FPA ldf.  */
1308             offset = (insn & 0xff) << 2;
1309             if (!(insn & 0x00800000))
1310                 offset = -offset;
1311             max_pool = 1024;
1312             type = 1;
1313         } else if ((insn & 0x0fff0000) == 0x028f0000) {
1314             /* Some gcc load a doubleword immediate with
1315                add regN, pc, #imm
1316                ldmia regN, {regN, regM}
1317                Hope and pray the compiler never generates somethin like
1318                add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1319             int r;
1320
1321             r = (insn & 0xf00) >> 7;
1322             offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1323             max_pool = 1024;
1324             type = 2;
1325         } else {
1326             max_pool = 0;
1327             type = -1;
1328         }
1329         if (type >= 0) {
1330             /* PC-relative load needs fixing up.  */
1331             if (spare > max_pool - offset)
1332                 spare = max_pool - offset;
1333             if ((offset & 3) !=0)
1334                 error("%s:%04x: pc offset must be 32 bit aligned",
1335                       name, start_offset + p - p_start);
1336             if (offset < 0)
1337                 error("%s:%04x: Embedded literal value",
1338                       name, start_offset + p - p_start);
1339             pc_offset = p - p_start + offset + 8;
1340             if (pc_offset <= (p - p_start) ||
1341                 pc_offset >= (p_end - p_start))
1342                 error("%s:%04x: pc offset must point inside the function code",
1343                       name, start_offset + p - p_start);
1344             if (pc_offset < min_offset)
1345                 min_offset = pc_offset;
1346             if (outfile) {
1347                 /* The intruction position */
1348                 fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1349                         p - p_start);
1350                 /* The position of the constant pool data.  */
1351                 data_index = ((p_end - p_start) - pc_offset) >> 2;
1352                 fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1353                         data_index);
1354                 fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
1355                 fprintf(outfile, "    arm_ldr_ptr++;\n");
1356             }
1357         }
1358         p += 4;
1359     }
1360
1361     /* Copy and relocate the constant pool data.  */
1362     data_size = (p_end - p_start) - min_offset;
1363     if (data_size > 0 && outfile) {
1364         spare += min_offset;
1365         fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1366         fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1367         fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1368                          "        arm_pool_ptr = gen_code_ptr + %d;\n",
1369                          spare, spare);
1370
1371         data_index = 0;
1372         for (pc_offset = min_offset;
1373              pc_offset < p_end - p_start;
1374              pc_offset += 4) {
1375
1376             ELF_RELOC *rel;
1377             int i, addend, type;
1378             const char *sym_name;
1379             char relname[1024];
1380
1381             /* data value */
1382             addend = get32((uint32_t *)(p_start + pc_offset));
1383             relname[0] = '\0';
1384             for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1385                 if (rel->r_offset == (pc_offset + start_offset)) {
1386                     sym_name = get_rel_sym_name(rel);
1387                     /* the compiler leave some unnecessary references to the code */
1388                     get_reloc_expr(relname, sizeof(relname), sym_name);
1389                     type = ELF32_R_TYPE(rel->r_info);
1390                     if (type != R_ARM_ABS32)
1391                         error("%s: unsupported data relocation", name);
1392                     break;
1393                 }
1394             }
1395             fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1396                     data_index, addend);
1397             if (relname[0] != '\0')
1398                 fprintf(outfile, " + %s", relname);
1399             fprintf(outfile, ";\n");
1400
1401             data_index++;
1402         }
1403     }
1404
1405     if (p == p_start)
1406         goto arm_ret_error;
1407     p -= 4;
1408     insn = get32((uint32_t *)p);
1409     /* The last instruction must be an ldm instruction.  There are several
1410        forms generated by gcc:
1411         ldmib sp, {..., pc}  (implies a sp adjustment of +4)
1412         ldmia sp, {..., pc}
1413         ldmea fp, {..., pc} */
1414     if ((insn & 0xffff8000) == 0xe99d8000) {
1415         if (outfile) {
1416             fprintf(outfile,
1417                     "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1418                     p - p_start);
1419         }
1420         p += 4;
1421     } else if ((insn & 0xffff8000) != 0xe89d8000
1422         && (insn & 0xffff8000) != 0xe91b8000) {
1423     arm_ret_error:
1424         if (!outfile)
1425             printf("%s: invalid epilog\n", name);
1426     }
1427     return p - p_start;
1428 }
1429 #endif
1430
1431
1432 #define MAX_ARGS 3
1433
1434 /* generate op code */
1435 void gen_code(const char *name, host_ulong offset, host_ulong size,
1436               FILE *outfile, int gen_switch)
1437 {
1438     int copy_size = 0;
1439     uint8_t *p_start, *p_end;
1440     host_ulong start_offset;
1441     int nb_args, i, n;
1442     uint8_t args_present[MAX_ARGS];
1443     const char *sym_name, *p;
1444     EXE_RELOC *rel;
1445
1446     /* Compute exact size excluding prologue and epilogue instructions.
1447      * Increment start_offset to skip epilogue instructions, then compute
1448      * copy_size the indicate the size of the remaining instructions (in
1449      * bytes).
1450      */
1451     p_start = text + offset;
1452     p_end = p_start + size;
1453     start_offset = offset;
1454 #if defined(HOST_I386) || defined(HOST_X86_64)
1455 #ifdef CONFIG_FORMAT_COFF
1456     {
1457         uint8_t *p;
1458         p = p_end - 1;
1459         if (p == p_start)
1460             error("empty code for %s", name);
1461         while (*p != 0xc3) {
1462             p--;
1463             if (p <= p_start)
1464                 error("ret or jmp expected at the end of %s", name);
1465         }
1466         copy_size = p - p_start;
1467     }
1468 #else
1469     {
1470         int len;
1471         len = p_end - p_start;
1472         if (len == 0)
1473             error("empty code for %s", name);
1474         if (p_end[-1] == 0xc3) {
1475             len--;
1476         } else {
1477             error("ret or jmp expected at the end of %s", name);
1478         }
1479         copy_size = len;
1480     }
1481 #endif
1482 #elif defined(HOST_PPC)
1483     {
1484         uint8_t *p;
1485         p = (void *)(p_end - 4);
1486         if (p == p_start)
1487             error("empty code for %s", name);
1488         if (get32((uint32_t *)p) != 0x4e800020)
1489             error("blr expected at the end of %s", name);
1490         copy_size = p - p_start;
1491     }
1492 #elif defined(HOST_S390)
1493     {
1494         uint8_t *p;
1495         p = (void *)(p_end - 2);
1496         if (p == p_start)
1497             error("empty code for %s", name);
1498         if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1499             error("br expected at the end of %s", name);
1500         copy_size = p - p_start;
1501     }
1502 #elif defined(HOST_ALPHA)
1503     {
1504         uint8_t *p;
1505         p = p_end - 4;
1506 #if 0
1507         /* XXX: check why it occurs */
1508         if (p == p_start)
1509             error("empty code for %s", name);
1510 #endif
1511         if (get32((uint32_t *)p) != 0x6bfa8001)
1512             error("ret expected at the end of %s", name);
1513         copy_size = p - p_start;
1514     }
1515 #elif defined(HOST_IA64)
1516     {
1517         uint8_t *p;
1518         p = (void *)(p_end - 4);
1519         if (p == p_start)
1520             error("empty code for %s", name);
1521         /* br.ret.sptk.many b0;; */
1522         /* 08 00 84 00 */
1523         if (get32((uint32_t *)p) != 0x00840008)
1524             error("br.ret.sptk.many b0;; expected at the end of %s", name);
1525         copy_size = p_end - p_start;
1526     }
1527 #elif defined(HOST_SPARC)
1528     {
1529 #define INSN_SAVE       0x9de3a000
1530 #define INSN_RET        0x81c7e008
1531 #define INSN_RETL       0x81c3e008
1532 #define INSN_RESTORE    0x81e80000
1533 #define INSN_RETURN     0x81cfe008
1534 #define INSN_NOP        0x01000000
1535 #define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1536 #define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1537
1538         uint32_t start_insn, end_insn1, end_insn2;
1539         uint8_t *p;
1540         p = (void *)(p_end - 8);
1541         if (p <= p_start)
1542             error("empty code for %s", name);
1543         start_insn = get32((uint32_t *)(p_start + 0x0));
1544         end_insn1 = get32((uint32_t *)(p + 0x0));
1545         end_insn2 = get32((uint32_t *)(p + 0x4));
1546         if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1547             (start_insn & ~0x1fff) == INSN_ADD_SP) {
1548             p_start += 0x4;
1549             start_offset += 0x4;
1550             if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1551                 /* SPARC v7: ret; restore; */ ;
1552             else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1553                 /* SPARC v9: return; nop; */ ;
1554             else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1555                 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1556             else
1557
1558                 error("ret; restore; not found at end of %s", name);
1559         } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1560             ;
1561         } else {
1562             error("No save at the beginning of %s", name);
1563         }
1564 #if 0
1565         /* Skip a preceeding nop, if present.  */
1566         if (p > p_start) {
1567             skip_insn = get32((uint32_t *)(p - 0x4));
1568             if (skip_insn == INSN_NOP)
1569                 p -= 4;
1570         }
1571 #endif
1572         copy_size = p - p_start;
1573     }
1574 #elif defined(HOST_SPARC64)
1575     {
1576 #define INSN_SAVE       0x9de3a000
1577 #define INSN_RET        0x81c7e008
1578 #define INSN_RETL       0x81c3e008
1579 #define INSN_RESTORE    0x81e80000
1580 #define INSN_RETURN     0x81cfe008
1581 #define INSN_NOP        0x01000000
1582 #define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1583 #define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1584
1585         uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1586         uint8_t *p;
1587         p = (void *)(p_end - 8);
1588 #if 0
1589         /* XXX: check why it occurs */
1590         if (p <= p_start)
1591             error("empty code for %s", name);
1592 #endif
1593         start_insn = get32((uint32_t *)(p_start + 0x0));
1594         end_insn1 = get32((uint32_t *)(p + 0x0));
1595         end_insn2 = get32((uint32_t *)(p + 0x4));
1596         if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1597             (start_insn & ~0x1fff) == INSN_ADD_SP) {
1598             p_start += 0x4;
1599             start_offset += 0x4;
1600             if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1601                 /* SPARC v7: ret; restore; */ ;
1602             else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1603                 /* SPARC v9: return; nop; */ ;
1604             else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1605                 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1606             else
1607
1608                 error("ret; restore; not found at end of %s", name);
1609         } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1610             ;
1611         } else {
1612             error("No save at the beginning of %s", name);
1613         }
1614
1615         /* Skip a preceeding nop, if present.  */
1616         if (p > p_start) {
1617             skip_insn = get32((uint32_t *)(p - 0x4));
1618             if (skip_insn == 0x01000000)
1619                 p -= 4;
1620         }
1621
1622         copy_size = p - p_start;
1623     }
1624 #elif defined(HOST_ARM)
1625     {
1626         uint32_t insn;
1627
1628         if ((p_end - p_start) <= 16)
1629             error("%s: function too small", name);
1630         if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1631             (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1632             get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1633             error("%s: invalid prolog", name);
1634         p_start += 12;
1635         start_offset += 12;
1636         insn = get32((uint32_t *)p_start);
1637         if ((insn & 0xffffff00) == 0xe24dd000) {
1638             /* Stack adjustment.  Assume op uses the frame pointer.  */
1639             p_start -= 4;
1640             start_offset -= 4;
1641         }
1642         copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1643                                       relocs, nb_relocs);
1644     }
1645 #elif defined(HOST_M68K)
1646     {
1647         uint8_t *p;
1648         p = (void *)(p_end - 2);
1649         if (p == p_start)
1650             error("empty code for %s", name);
1651         // remove NOP's, probably added for alignment
1652         while ((get16((uint16_t *)p) == 0x4e71) &&
1653                (p>p_start))
1654             p -= 2;
1655         if (get16((uint16_t *)p) != 0x4e75)
1656             error("rts expected at the end of %s", name);
1657         copy_size = p - p_start;
1658     }
1659 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1660     {
1661 #define INSN_RETURN     0x03e00008
1662 #define INSN_NOP        0x00000000
1663
1664         uint8_t *p = p_end;
1665
1666         if (p < (p_start + 0x8)) {
1667             error("empty code for %s", name);
1668         } else {
1669             uint32_t end_insn1, end_insn2;
1670
1671             p -= 0x8;
1672             end_insn1 = get32((uint32_t *)(p + 0x0));
1673             end_insn2 = get32((uint32_t *)(p + 0x4));
1674             if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1675                 error("jr ra not found at end of %s", name);
1676         }
1677         copy_size = p - p_start;
1678     }
1679 #else
1680 #error unsupported CPU
1681 #endif
1682
1683     /* compute the number of arguments by looking at the relocations */
1684     for(i = 0;i < MAX_ARGS; i++)
1685         args_present[i] = 0;
1686
1687     for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1688         host_ulong offset = get_rel_offset(rel);
1689         if (offset >= start_offset &&
1690             offset < start_offset + (p_end - p_start)) {
1691             sym_name = get_rel_sym_name(rel);
1692             if(!sym_name)
1693                 continue;
1694             if (strstart(sym_name, "__op_param", &p) ||
1695                 strstart(sym_name, "__op_gen_label", &p)) {
1696                 n = strtoul(p, NULL, 10);
1697                 if (n > MAX_ARGS)
1698                     error("too many arguments in %s", name);
1699                 args_present[n - 1] = 1;
1700             }
1701         }
1702     }
1703
1704     nb_args = 0;
1705     while (nb_args < MAX_ARGS && args_present[nb_args])
1706         nb_args++;
1707     for(i = nb_args; i < MAX_ARGS; i++) {
1708         if (args_present[i])
1709             error("inconsistent argument numbering in %s", name);
1710     }
1711
1712     if (gen_switch == 2) {
1713         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1714     } else if (gen_switch == 1) {
1715
1716         /* output C code */
1717         fprintf(outfile, "case INDEX_%s: {\n", name);
1718         if (nb_args > 0) {
1719             fprintf(outfile, "    long ");
1720             for(i = 0; i < nb_args; i++) {
1721                 if (i != 0)
1722                     fprintf(outfile, ", ");
1723                 fprintf(outfile, "param%d", i + 1);
1724             }
1725             fprintf(outfile, ";\n");
1726         }
1727 #if defined(HOST_IA64)
1728         fprintf(outfile, "    extern char %s;\n", name);
1729 #else
1730         fprintf(outfile, "    extern void %s();\n", name);
1731 #endif
1732
1733         for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1734             host_ulong offset = get_rel_offset(rel);
1735             if (offset >= start_offset &&
1736                 offset < start_offset + (p_end - p_start)) {
1737                 sym_name = get_rel_sym_name(rel);
1738                 if(!sym_name)
1739                     continue;
1740                 if (*sym_name &&
1741                     !strstart(sym_name, "__op_param", NULL) &&
1742                     !strstart(sym_name, "__op_jmp", NULL) &&
1743                     !strstart(sym_name, "__op_gen_label", NULL)) {
1744 #if defined(HOST_SPARC)
1745                     if (sym_name[0] == '.') {
1746                         fprintf(outfile,
1747                                 "extern char __dot_%s __asm__(\"%s\");\n",
1748                                 sym_name+1, sym_name);
1749                         continue;
1750                     }
1751 #endif
1752 #if defined(__APPLE__)
1753                     /* Set __attribute((unused)) on darwin because we
1754                        want to avoid warning when we don't use the symbol.  */
1755                     fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1756 #elif defined(HOST_IA64)
1757                         if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1758                                 /*
1759                                  * PCREL21 br.call targets generally
1760                                  * are out of range and need to go
1761                                  * through an "import stub".
1762                                  */
1763                                 fprintf(outfile, "    extern char %s;\n",
1764                                         sym_name);
1765 #else
1766                     fprintf(outfile, "extern char %s;\n", sym_name);
1767 #endif
1768                 }
1769             }
1770         }
1771
1772         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1773                                         name, (int)(start_offset - offset), copy_size);
1774
1775         /* emit code offset information */
1776         {
1777             EXE_SYM *sym;
1778             const char *sym_name, *p;
1779             host_ulong val;
1780             int n;
1781
1782             for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1783                 sym_name = get_sym_name(sym);
1784                 if (strstart(sym_name, "__op_label", &p)) {
1785                     uint8_t *ptr;
1786                     unsigned long offset;
1787
1788                     /* test if the variable refers to a label inside
1789                        the code we are generating */
1790 #ifdef CONFIG_FORMAT_COFF
1791                     if (sym->st_shndx == text_shndx) {
1792                         ptr = sdata[coff_text_shndx];
1793                     } else if (sym->st_shndx == data_shndx) {
1794                         ptr = sdata[coff_data_shndx];
1795                     } else {
1796                         ptr = NULL;
1797                     }
1798 #elif defined(CONFIG_FORMAT_MACH)
1799                     if(!sym->n_sect)
1800                         continue;
1801                     ptr = sdata[sym->n_sect-1];
1802 #else
1803                     ptr = sdata[sym->st_shndx];
1804 #endif
1805                     if (!ptr)
1806                         error("__op_labelN in invalid section");
1807                     offset = sym->st_value;
1808 #ifdef CONFIG_FORMAT_MACH
1809                     offset -= section_hdr[sym->n_sect-1].addr;
1810 #endif
1811                     val = *(host_ulong *)(ptr + offset);
1812 #ifdef ELF_USES_RELOCA
1813                     {
1814                         int reloc_shndx, nb_relocs1, j;
1815
1816                         /* try to find a matching relocation */
1817                         reloc_shndx = find_reloc(sym->st_shndx);
1818                         if (reloc_shndx) {
1819                             nb_relocs1 = shdr[reloc_shndx].sh_size /
1820                                 shdr[reloc_shndx].sh_entsize;
1821                             rel = (ELF_RELOC *)sdata[reloc_shndx];
1822                             for(j = 0; j < nb_relocs1; j++) {
1823                                 if (rel->r_offset == offset) {
1824                                     val = rel->r_addend;
1825                                     break;
1826                                 }
1827                                 rel++;
1828                             }
1829                         }
1830                     }
1831 #endif
1832                     if (val >= start_offset && val <= start_offset + copy_size) {
1833                         n = strtol(p, NULL, 10);
1834                         fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1835                     }
1836                 }
1837             }
1838         }
1839
1840         /* load parameters in variables */
1841         for(i = 0; i < nb_args; i++) {
1842             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1843         }
1844
1845         /* patch relocations */
1846 #if defined(HOST_I386)
1847             {
1848                 char relname[256];
1849                 int type;
1850                 int addend;
1851                 int reloc_offset;
1852                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1853                 if (rel->r_offset >= start_offset &&
1854                     rel->r_offset < start_offset + copy_size) {
1855                     sym_name = get_rel_sym_name(rel);
1856                     if (!sym_name)
1857                         continue;
1858                     reloc_offset = rel->r_offset - start_offset;
1859                     if (strstart(sym_name, "__op_jmp", &p)) {
1860                         int n;
1861                         n = strtol(p, NULL, 10);
1862                         /* __op_jmp relocations are done at
1863                            runtime to do translated block
1864                            chaining: the offset of the instruction
1865                            needs to be stored */
1866                         fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1867                                 n, reloc_offset);
1868                         continue;
1869                     }
1870
1871                     get_reloc_expr(relname, sizeof(relname), sym_name);
1872                     addend = get32((uint32_t *)(text + rel->r_offset));
1873 #ifdef CONFIG_FORMAT_ELF
1874                     type = ELF32_R_TYPE(rel->r_info);
1875                     switch(type) {
1876                     case R_386_32:
1877                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1878                                 reloc_offset, relname, addend);
1879                         break;
1880                     case R_386_PC32:
1881                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1882                                 reloc_offset, relname, reloc_offset, addend);
1883                         break;
1884                     default:
1885                         error("unsupported i386 relocation (%d)", type);
1886                     }
1887 #elif defined(CONFIG_FORMAT_COFF)
1888                     {
1889                         char *temp_name;
1890                         int j;
1891                         EXE_SYM *sym;
1892                         temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1893                         if (!strcmp(temp_name, ".data")) {
1894                             for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1895                                 if (strstart(sym->st_name, sym_name, NULL)) {
1896                                     addend -= sym->st_value;
1897                                 }
1898                             }
1899                         }
1900                     }
1901                     type = rel->r_type;
1902                     switch(type) {
1903                     case DIR32:
1904                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1905                                 reloc_offset, relname, addend);
1906                         break;
1907                     case DISP32:
1908                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1909                                 reloc_offset, relname, reloc_offset, addend);
1910                         break;
1911                     default:
1912                         error("unsupported i386 relocation (%d)", type);
1913                     }
1914 #else
1915 #error unsupport object format
1916 #endif
1917                 }
1918                 }
1919             }
1920 #elif defined(HOST_X86_64)
1921             {
1922                 char relname[256];
1923                 int type;
1924                 int addend;
1925                 int reloc_offset;
1926                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1927                 if (rel->r_offset >= start_offset &&
1928                     rel->r_offset < start_offset + copy_size) {
1929                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1930                     get_reloc_expr(relname, sizeof(relname), sym_name);
1931                     type = ELF32_R_TYPE(rel->r_info);
1932                     addend = rel->r_addend;
1933                     reloc_offset = rel->r_offset - start_offset;
1934                     switch(type) {
1935                     case R_X86_64_32:
1936                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1937                                 reloc_offset, relname, addend);
1938                         break;
1939                     case R_X86_64_32S:
1940                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1941                                 reloc_offset, relname, addend);
1942                         break;
1943                     case R_X86_64_PC32:
1944                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1945                                 reloc_offset, relname, reloc_offset, addend);
1946                         break;
1947                     default:
1948                         error("unsupported X86_64 relocation (%d)", type);
1949                     }
1950                 }
1951                 }
1952             }
1953 #elif defined(HOST_PPC)
1954             {
1955 #ifdef CONFIG_FORMAT_ELF
1956                 char relname[256];
1957                 int type;
1958                 int addend;
1959                 int reloc_offset;
1960                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1961                     if (rel->r_offset >= start_offset &&
1962                         rel->r_offset < start_offset + copy_size) {
1963                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1964                         reloc_offset = rel->r_offset - start_offset;
1965                         if (strstart(sym_name, "__op_jmp", &p)) {
1966                             int n;
1967                             n = strtol(p, NULL, 10);
1968                             /* __op_jmp relocations are done at
1969                                runtime to do translated block
1970                                chaining: the offset of the instruction
1971                                needs to be stored */
1972                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1973                                     n, reloc_offset);
1974                             continue;
1975                         }
1976
1977                         get_reloc_expr(relname, sizeof(relname), sym_name);
1978                         type = ELF32_R_TYPE(rel->r_info);
1979                         addend = rel->r_addend;
1980                         switch(type) {
1981                         case R_PPC_ADDR32:
1982                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1983                                     reloc_offset, relname, addend);
1984                             break;
1985                         case R_PPC_ADDR16_LO:
1986                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1987                                     reloc_offset, relname, addend);
1988                             break;
1989                         case R_PPC_ADDR16_HI:
1990                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1991                                     reloc_offset, relname, addend);
1992                             break;
1993                         case R_PPC_ADDR16_HA:
1994                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1995                                     reloc_offset, relname, addend);
1996                             break;
1997                         case R_PPC_REL24:
1998                             /* warning: must be at 32 MB distancy */
1999                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2000                                     reloc_offset, reloc_offset, relname, reloc_offset, addend);
2001                             break;
2002                         default:
2003                             error("unsupported powerpc relocation (%d)", type);
2004                         }
2005                     }
2006                 }
2007 #elif defined(CONFIG_FORMAT_MACH)
2008                 struct scattered_relocation_info *scarel;
2009                 struct relocation_info * rel;
2010                 char final_sym_name[256];
2011                 const char *sym_name;
2012                 const char *p;
2013                 int slide, sslide;
2014                 int i;
2015
2016                 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2017                     unsigned int offset, length, value = 0;
2018                     unsigned int type, pcrel, isym = 0;
2019                     unsigned int usesym = 0;
2020
2021                     if(R_SCATTERED & rel->r_address) {
2022                         scarel = (struct scattered_relocation_info*)rel;
2023                         offset = (unsigned int)scarel->r_address;
2024                         length = scarel->r_length;
2025                         pcrel = scarel->r_pcrel;
2026                         type = scarel->r_type;
2027                         value = scarel->r_value;
2028                     } else {
2029                         value = isym = rel->r_symbolnum;
2030                         usesym = (rel->r_extern);
2031                         offset = rel->r_address;
2032                         length = rel->r_length;
2033                         pcrel = rel->r_pcrel;
2034                         type = rel->r_type;
2035                     }
2036
2037                     slide = offset - start_offset;
2038
2039                     if (!(offset >= start_offset && offset < start_offset + size))
2040                         continue;  /* not in our range */
2041
2042                         sym_name = get_reloc_name(rel, &sslide);
2043
2044                         if(usesym && symtab[isym].n_type & N_STAB)
2045                             continue; /* don't handle STAB (debug sym) */
2046
2047                         if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2048                             int n;
2049                             n = strtol(p, NULL, 10);
2050                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2051                                     n, slide);
2052                             continue; /* Nothing more to do */
2053                         }
2054
2055                         if(!sym_name) {
2056                             fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2057                                     name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2058                             continue; /* dunno how to handle without final_sym_name */
2059                         }
2060
2061                         get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2062                                        sym_name);
2063                         switch(type) {
2064                         case PPC_RELOC_BR24:
2065                             if (!strstart(sym_name,"__op_gen_label",&p)) {
2066                                 fprintf(outfile, "{\n");
2067                                 fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2068                                 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",
2069                                         slide, slide, name, sslide);
2070                                 fprintf(outfile, "}\n");
2071                             } else {
2072                                 fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2073                                         slide, slide, final_sym_name, slide);
2074                             }
2075                             break;
2076                         case PPC_RELOC_HI16:
2077                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2078                                     slide, final_sym_name, sslide);
2079                             break;
2080                         case PPC_RELOC_LO16:
2081                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2082                                     slide, final_sym_name, sslide);
2083                             break;
2084                         case PPC_RELOC_HA16:
2085                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2086                                     slide, final_sym_name, sslide);
2087                             break;
2088                         default:
2089                             error("unsupported powerpc relocation (%d)", type);
2090                     }
2091                 }
2092 #else
2093 #error unsupport object format
2094 #endif
2095             }
2096 #elif defined(HOST_S390)
2097             {
2098                 char relname[256];
2099                 int type;
2100                 int addend;
2101                 int reloc_offset;
2102                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2103                     if (rel->r_offset >= start_offset &&
2104                         rel->r_offset < start_offset + copy_size) {
2105                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2106                         get_reloc_expr(relname, sizeof(relname), sym_name);
2107                         type = ELF32_R_TYPE(rel->r_info);
2108                         addend = rel->r_addend;
2109                         reloc_offset = rel->r_offset - start_offset;
2110                         switch(type) {
2111                         case R_390_32:
2112                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2113                                     reloc_offset, relname, addend);
2114                             break;
2115                         case R_390_16:
2116                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2117                                     reloc_offset, relname, addend);
2118                             break;
2119                         case R_390_8:
2120                             fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2121                                     reloc_offset, relname, addend);
2122                             break;
2123                         case R_390_PC32DBL:
2124                             if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2125                                 fprintf(outfile,
2126                                         "    *(uint32_t *)(gen_code_ptr + %d) += "
2127                                         "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2128                                         reloc_offset, name);
2129                             }
2130                             else
2131                                 fprintf(outfile,
2132                                         "    *(uint32_t *)(gen_code_ptr + %d) = "
2133                                         "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2134                                         reloc_offset, relname, addend, reloc_offset);
2135                             break;
2136                         default:
2137                             error("unsupported s390 relocation (%d)", type);
2138                         }
2139                     }
2140                 }
2141             }
2142 #elif defined(HOST_ALPHA)
2143             {
2144                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2145                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2146                         int type;
2147                         long reloc_offset;
2148
2149                         type = ELF64_R_TYPE(rel->r_info);
2150                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2151                         reloc_offset = rel->r_offset - start_offset;
2152                         switch (type) {
2153                         case R_ALPHA_GPDISP:
2154                             /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2155                                as an immediate instead of constructing it from the pv or ra.  */
2156                             fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2157                                     reloc_offset);
2158                             fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2159                                     reloc_offset + (int)rel->r_addend);
2160                             break;
2161                         case R_ALPHA_LITUSE:
2162                             /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2163                                now, since some called functions (libc) need pv to be set up.  */
2164                             break;
2165                         case R_ALPHA_HINT:
2166                             /* Branch target prediction hint. Ignore for now.  Should be already
2167                                correct for in-function jumps.  */
2168                             break;
2169                         case R_ALPHA_LITERAL:
2170                             /* Load a literal from the GOT relative to the gp.  Since there's only a
2171                                single gp, nothing is to be done.  */
2172                             break;
2173                         case R_ALPHA_GPRELHIGH:
2174                             /* Handle fake relocations against __op_param symbol.  Need to emit the
2175                                high part of the immediate value instead.  Other symbols need no
2176                                special treatment.  */
2177                             if (strstart(sym_name, "__op_param", &p))
2178                                 fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2179                                         reloc_offset, p);
2180                             break;
2181                         case R_ALPHA_GPRELLOW:
2182                             if (strstart(sym_name, "__op_param", &p))
2183                                 fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2184                                         reloc_offset, p);
2185                             break;
2186                         case R_ALPHA_BRSGP:
2187                             /* PC-relative jump. Tweak offset to skip the two instructions that try to
2188                                set up the gp from the pv.  */
2189                             fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2190                                     reloc_offset, sym_name, reloc_offset);
2191                             break;
2192                         default:
2193                             error("unsupported Alpha relocation (%d)", type);
2194                         }
2195                     }
2196                 }
2197             }
2198 #elif defined(HOST_IA64)
2199             {
2200                 unsigned long sym_idx;
2201                 long code_offset;
2202                 char relname[256];
2203                 int type;
2204                 long addend;
2205
2206                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2207                     sym_idx = ELF64_R_SYM(rel->r_info);
2208                     if (rel->r_offset < start_offset
2209                         || rel->r_offset >= start_offset + copy_size)
2210                         continue;
2211                     sym_name = (strtab + symtab[sym_idx].st_name);
2212                     code_offset = rel->r_offset - start_offset;
2213                     if (strstart(sym_name, "__op_jmp", &p)) {
2214                         int n;
2215                         n = strtol(p, NULL, 10);
2216                         /* __op_jmp relocations are done at
2217                            runtime to do translated block
2218                            chaining: the offset of the instruction
2219                            needs to be stored */
2220                         fprintf(outfile, "    jmp_offsets[%d] ="
2221                                 "%ld + (gen_code_ptr - gen_code_buf);\n",
2222                                 n, code_offset);
2223                         continue;
2224                     }
2225                     get_reloc_expr(relname, sizeof(relname), sym_name);
2226                     type = ELF64_R_TYPE(rel->r_info);
2227                     addend = rel->r_addend;
2228                     switch(type) {
2229                       case R_IA64_IMM64:
2230                           fprintf(outfile,
2231                                   "    ia64_imm64(gen_code_ptr + %ld, "
2232                                   "%s + %ld);\n",
2233                                   code_offset, relname, addend);
2234                           break;
2235                       case R_IA64_LTOFF22X:
2236                       case R_IA64_LTOFF22:
2237                           fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2238                                   " %s + %ld, %d);\n",
2239                                   code_offset, relname, addend,
2240                                   (type == R_IA64_LTOFF22X));
2241                           break;
2242                       case R_IA64_LDXMOV:
2243                           fprintf(outfile,
2244                                   "    ia64_ldxmov(gen_code_ptr + %ld,"
2245                                   " %s + %ld);\n", code_offset, relname, addend);
2246                           break;
2247
2248                       case R_IA64_PCREL21B:
2249                           if (strstart(sym_name, "__op_gen_label", NULL)) {
2250                               fprintf(outfile,
2251                                       "    ia64_imm21b(gen_code_ptr + %ld,"
2252                                       " (long) (%s + %ld -\n\t\t"
2253                                       "((long) gen_code_ptr + %ld)) >> 4);\n",
2254                                       code_offset, relname, addend,
2255                                       code_offset & ~0xfUL);
2256                           } else {
2257                               fprintf(outfile,
2258                                       "    IA64_PLT(gen_code_ptr + %ld, "
2259                                       "%d);\t/* %s + %ld */\n",
2260                                       code_offset,
2261                                       get_plt_index(sym_name, addend),
2262                                       sym_name, addend);
2263                           }
2264                           break;
2265                       default:
2266                           error("unsupported ia64 relocation (0x%x)",
2267                                 type);
2268                     }
2269                 }
2270                 fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2271                         copy_size - 16 + 2);
2272             }
2273 #elif defined(HOST_SPARC)
2274             {
2275                 char relname[256];
2276                 int type;
2277                 int addend;
2278                 int reloc_offset;
2279                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2280                     if (rel->r_offset >= start_offset &&
2281                         rel->r_offset < start_offset + copy_size) {
2282                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2283                         get_reloc_expr(relname, sizeof(relname), sym_name);
2284                         type = ELF32_R_TYPE(rel->r_info);
2285                         addend = rel->r_addend;
2286                         reloc_offset = rel->r_offset - start_offset;
2287                         switch(type) {
2288                         case R_SPARC_32:
2289                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2290                                     reloc_offset, relname, addend);
2291                             break;
2292                         case R_SPARC_HI22:
2293                             fprintf(outfile,
2294                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2295                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2296                                     " & ~0x3fffff) "
2297                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2298                                     reloc_offset, reloc_offset, relname, addend);
2299                             break;
2300                         case R_SPARC_LO10:
2301                             fprintf(outfile,
2302                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2303                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2304                                     " & ~0x3ff) "
2305                                     " | ((%s + %d) & 0x3ff);\n",
2306                                     reloc_offset, reloc_offset, relname, addend);
2307                             break;
2308                         case R_SPARC_WDISP30:
2309                             fprintf(outfile,
2310                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2311                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2312                                     " & ~0x3fffffff) "
2313                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2314                                     "    & 0x3fffffff);\n",
2315                                     reloc_offset, reloc_offset, relname, addend,
2316                                     reloc_offset);
2317                             break;
2318                         case R_SPARC_WDISP22:
2319                             fprintf(outfile,
2320                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2321                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2322                                     " & ~0x3fffff) "
2323                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2324                                     "    & 0x3fffff);\n",
2325                                     rel->r_offset - start_offset,
2326                                     rel->r_offset - start_offset,
2327                                     relname, addend,
2328                                     rel->r_offset - start_offset);
2329                             break;
2330                         default:
2331                             error("unsupported sparc relocation (%d)", type);
2332                         }
2333                     }
2334                 }
2335             }
2336 #elif defined(HOST_SPARC64)
2337             {
2338                 char relname[256];
2339                 int type;
2340                 int addend;
2341                 int reloc_offset;
2342                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2343                     if (rel->r_offset >= start_offset &&
2344                         rel->r_offset < start_offset + copy_size) {
2345                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2346                         get_reloc_expr(relname, sizeof(relname), sym_name);
2347                         type = ELF32_R_TYPE(rel->r_info);
2348                         addend = rel->r_addend;
2349                         reloc_offset = rel->r_offset - start_offset;
2350                         switch(type) {
2351                         case R_SPARC_32:
2352                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2353                                     reloc_offset, relname, addend);
2354                             break;
2355                         case R_SPARC_HI22:
2356                             fprintf(outfile,
2357                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2358                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2359                                     " & ~0x3fffff) "
2360                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2361                                     reloc_offset, reloc_offset, relname, addend);
2362                             break;
2363                         case R_SPARC_LO10:
2364                             fprintf(outfile,
2365                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2366                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2367                                     " & ~0x3ff) "
2368                                     " | ((%s + %d) & 0x3ff);\n",
2369                                     reloc_offset, reloc_offset, relname, addend);
2370                             break;
2371                         case R_SPARC_OLO10:
2372                             addend += ELF64_R_TYPE_DATA (rel->r_info);
2373                             fprintf(outfile,
2374                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2375                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2376                                     " & ~0x3ff) "
2377                                     " | ((%s + %d) & 0x3ff);\n",
2378                                     reloc_offset, reloc_offset, relname, addend);
2379                             break;
2380                         case R_SPARC_WDISP30:
2381                             fprintf(outfile,
2382                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2383                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2384                                     " & ~0x3fffffff) "
2385                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2386                                     "    & 0x3fffffff);\n",
2387                                     reloc_offset, reloc_offset, relname, addend,
2388                                     reloc_offset);
2389                             break;
2390                         case R_SPARC_WDISP22:
2391                             fprintf(outfile,
2392                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2393                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2394                                     " & ~0x3fffff) "
2395                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2396                                     "    & 0x3fffff);\n",
2397                                     reloc_offset, reloc_offset, relname, addend,
2398                                     reloc_offset);
2399                             break;
2400                         case R_SPARC_HH22:
2401                             fprintf(outfile,
2402                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2403                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2404                                     " & ~0x00000000) "
2405                                     " | (((%s + %d) >> 42) & 0x00000000);\n",
2406                                     reloc_offset, reloc_offset, relname, addend);
2407                              break;
2408
2409                         case R_SPARC_LM22:
2410                             fprintf(outfile,
2411                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2412                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2413                                     " & ~0x00000000) "
2414                                     " | (((%s + %d) >> 10) & 0x00000000);\n",
2415                                     reloc_offset, reloc_offset, relname, addend);
2416                             break;
2417
2418                         case R_SPARC_HM10:
2419                             fprintf(outfile,
2420                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2421                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2422                                     " & ~0x00000000) "
2423                                     " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2424                                     reloc_offset, reloc_offset, relname, addend);
2425                             break;
2426
2427                         default:
2428                             error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2429                         }
2430                     }
2431                 }
2432             }
2433 #elif defined(HOST_ARM)
2434             {
2435                 char relname[256];
2436                 int type;
2437                 int addend;
2438                 int reloc_offset;
2439                 uint32_t insn;
2440
2441                 insn = get32((uint32_t *)(p_start + 4));
2442                 /* If prologue ends in sub sp, sp, #const then assume
2443                    op has a stack frame and needs the frame pointer.  */
2444                 if ((insn & 0xffffff00) == 0xe24dd000) {
2445                     int i;
2446                     uint32_t opcode;
2447                     opcode = 0xe28db000; /* add fp, sp, #0.  */
2448 #if 0
2449 /* ??? Need to undo the extra stack adjustment at the end of the op.
2450    For now just leave the stack misaligned and hope it doesn't break anything
2451    too important.  */
2452                     if ((insn & 4) != 0) {
2453                         /* Preserve doubleword stack alignment.  */
2454                         fprintf(outfile,
2455                                 "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2456                                 insn + 4);
2457                         opcode -= 4;
2458                     }
2459 #endif
2460                     insn = get32((uint32_t *)(p_start - 4));
2461                     /* Calculate the size of the saved registers,
2462                        excluding pc.  */
2463                     for (i = 0; i < 15; i++) {
2464                         if (insn & (1 << i))
2465                             opcode += 4;
2466                     }
2467                     fprintf(outfile,
2468                             "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2469                 }
2470                 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2471                                   relocs, nb_relocs);
2472
2473                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2474                 if (rel->r_offset >= start_offset &&
2475                     rel->r_offset < start_offset + copy_size) {
2476                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2477                     /* the compiler leave some unnecessary references to the code */
2478                     if (sym_name[0] == '\0')
2479                         continue;
2480                     get_reloc_expr(relname, sizeof(relname), sym_name);
2481                     type = ELF32_R_TYPE(rel->r_info);
2482                     addend = get32((uint32_t *)(text + rel->r_offset));
2483                     reloc_offset = rel->r_offset - start_offset;
2484                     switch(type) {
2485                     case R_ARM_ABS32:
2486                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2487                                 reloc_offset, relname, addend);
2488                         break;
2489                     case R_ARM_PC24:
2490                     case R_ARM_JUMP24:
2491                     case R_ARM_CALL:
2492                         fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2493                                 reloc_offset, addend, relname);
2494                         break;
2495                     default:
2496                         error("unsupported arm relocation (%d)", type);
2497                     }
2498                 }
2499                 }
2500             }
2501 #elif defined(HOST_M68K)
2502             {
2503                 char relname[256];
2504                 int type;
2505                 int addend;
2506                 int reloc_offset;
2507                 Elf32_Sym *sym;
2508                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2509                 if (rel->r_offset >= start_offset &&
2510                     rel->r_offset < start_offset + copy_size) {
2511                     sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2512                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2513                     get_reloc_expr(relname, sizeof(relname), sym_name);
2514                     type = ELF32_R_TYPE(rel->r_info);
2515                     addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2516                     reloc_offset = rel->r_offset - start_offset;
2517                     switch(type) {
2518                     case R_68K_32:
2519                         fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2520                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2521                                 reloc_offset, relname, addend );
2522                         break;
2523                     case R_68K_PC32:
2524                         fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2525                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2526                                 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2527                         break;
2528                     default:
2529                         error("unsupported m68k relocation (%d)", type);
2530                     }
2531                 }
2532                 }
2533             }
2534 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2535             {
2536                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2537                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2538                         char relname[256];
2539                         int type;
2540                         int addend;
2541                         int reloc_offset;
2542
2543                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2544                         /* the compiler leave some unnecessary references to the code */
2545                         if (sym_name[0] == '\0')
2546                             continue;
2547                         get_reloc_expr(relname, sizeof(relname), sym_name);
2548                         type = ELF32_R_TYPE(rel->r_info);
2549                         addend = get32((uint32_t *)(text + rel->r_offset));
2550                         reloc_offset = rel->r_offset - start_offset;
2551                         switch (type) {
2552                         case R_MIPS_26:
2553                             fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2554                                     rel->r_offset, sym_name);
2555                             fprintf(outfile,
2556                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2557                                     "(0x%x & ~0x3fffff) "
2558                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2559                                     "   & 0x3fffff);\n",
2560                                     reloc_offset, addend, addend, relname, reloc_offset);
2561                             break;
2562                         case R_MIPS_HI16:
2563                             fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2564                                     rel->r_offset, sym_name);
2565                             fprintf(outfile,
2566                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2567                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2568                                     " & ~0xffff) "
2569                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2570                                     reloc_offset, reloc_offset, relname);
2571                             break;
2572                         case R_MIPS_LO16:
2573                             fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2574                                     rel->r_offset, sym_name);
2575                             fprintf(outfile,
2576                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2577                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2578                                     " & ~0xffff) "
2579                                     " | (%s & 0xffff);\n",
2580                                     reloc_offset, reloc_offset, relname);
2581                             break;
2582                         case R_MIPS_PC16:
2583                             fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2584                                     rel->r_offset, sym_name);
2585                             fprintf(outfile,
2586                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2587                                     "(0x%x & ~0xffff) "
2588                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2589                                     "   & 0xffff);\n",
2590                                     reloc_offset, addend, addend, relname, reloc_offset);
2591                             break;
2592                         case R_MIPS_GOT16:
2593                         case R_MIPS_CALL16:
2594                             fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2595                                     rel->r_offset, sym_name);
2596                             fprintf(outfile,
2597                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2598                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2599                                     " & ~0xffff) "
2600                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2601                                     reloc_offset, reloc_offset, relname);
2602                             break;
2603                         default:
2604                             error("unsupported MIPS relocation (%d)", type);
2605                         }
2606                     }
2607                 }
2608             }
2609 #else
2610 #error unsupported CPU
2611 #endif
2612         fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2613         fprintf(outfile, "}\n");
2614         fprintf(outfile, "break;\n\n");
2615     } else {
2616         fprintf(outfile, "static inline void gen_%s(", name);
2617         if (nb_args == 0) {
2618             fprintf(outfile, "void");
2619         } else {
2620             for(i = 0; i < nb_args; i++) {
2621                 if (i != 0)
2622                     fprintf(outfile, ", ");
2623                 fprintf(outfile, "long param%d", i + 1);
2624             }
2625         }
2626         fprintf(outfile, ")\n");
2627         fprintf(outfile, "{\n");
2628         for(i = 0; i < nb_args; i++) {
2629             fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2630         }
2631         fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2632         fprintf(outfile, "}\n\n");
2633     }
2634 }
2635
2636 int gen_file(FILE *outfile, int out_type)
2637 {
2638     int i;
2639     EXE_SYM *sym;
2640
2641     if (out_type == OUT_INDEX_OP) {
2642         fprintf(outfile, "DEF(end, 0, 0)\n");
2643         fprintf(outfile, "DEF(nop, 0, 0)\n");
2644         fprintf(outfile, "DEF(nop1, 1, 0)\n");
2645         fprintf(outfile, "DEF(nop2, 2, 0)\n");
2646         fprintf(outfile, "DEF(nop3, 3, 0)\n");
2647         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2648             const char *name;
2649             name = get_sym_name(sym);
2650             if (strstart(name, OP_PREFIX, NULL)) {
2651                 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2652             }
2653         }
2654     } else if (out_type == OUT_GEN_OP) {
2655         /* generate gen_xxx functions */
2656         fprintf(outfile, "#include \"dyngen-op.h\"\n");
2657         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2658             const char *name;
2659             name = get_sym_name(sym);
2660             if (strstart(name, OP_PREFIX, NULL)) {
2661 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2662                 if (sym->st_shndx != text_shndx)
2663                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2664 #endif
2665                 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2666             }
2667         }
2668
2669     } else {
2670         /* generate big code generation switch */
2671
2672 #ifdef HOST_ARM
2673         /* We need to know the size of all the ops so we can figure out when
2674            to emit constant pools.  This must be consistent with opc.h.  */
2675 fprintf(outfile,
2676 "static const uint32_t arm_opc_size[] = {\n"
2677 "  0,\n" /* end */
2678 "  0,\n" /* nop */
2679 "  0,\n" /* nop1 */
2680 "  0,\n" /* nop2 */
2681 "  0,\n"); /* nop3 */
2682         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2683             const char *name;
2684             name = get_sym_name(sym);
2685             if (strstart(name, OP_PREFIX, NULL)) {
2686                 fprintf(outfile, "  %d,\n", sym->st_size);
2687             }
2688         }
2689 fprintf(outfile,
2690 "};\n");
2691 #endif
2692
2693 fprintf(outfile,
2694 "int dyngen_code(uint8_t *gen_code_buf,\n"
2695 "                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2696 "                const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2697 "{\n"
2698 "    uint8_t *gen_code_ptr;\n"
2699 "    const uint16_t *opc_ptr;\n"
2700 "    const uint32_t *opparam_ptr;\n");
2701
2702 #ifdef HOST_ARM
2703 /* Arm is tricky because it uses constant pools for loading immediate values.
2704    We assume (and require) each function is code followed by a constant pool.
2705    All the ops are small so this should be ok.  For each op we figure
2706    out how much "spare" range we have in the load instructions.  This allows
2707    us to insert subsequent ops in between the op and the constant pool,
2708    eliminating the neeed to jump around the pool.
2709
2710    We currently generate:
2711
2712    [ For this example we assume merging would move op1_pool out of range.
2713      In practice we should be able to combine many ops before the offset
2714      limits are reached. ]
2715    op1_code;
2716    op2_code;
2717    goto op3;
2718    op2_pool;
2719    op1_pool;
2720 op3:
2721    op3_code;
2722    ret;
2723    op3_pool;
2724
2725    Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2726  */
2727 fprintf(outfile,
2728 "    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2729 "    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2730 "    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2731 /* Initialise the parmissible pool offset to an arbitary large value.  */
2732 "    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2733 #endif
2734 #ifdef HOST_IA64
2735     {
2736         long addend, not_first = 0;
2737         unsigned long sym_idx;
2738         int index, max_index;
2739         const char *sym_name;
2740         EXE_RELOC *rel;
2741
2742         max_index = -1;
2743         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2744             sym_idx = ELF64_R_SYM(rel->r_info);
2745             sym_name = (strtab + symtab[sym_idx].st_name);
2746             if (strstart(sym_name, "__op_gen_label", NULL))
2747                 continue;
2748             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2749                 continue;
2750
2751             addend = rel->r_addend;
2752             index = get_plt_index(sym_name, addend);
2753             if (index <= max_index)
2754                 continue;
2755             max_index = index;
2756             fprintf(outfile, "    extern void %s(void);\n", sym_name);
2757         }
2758
2759         fprintf(outfile,
2760                 "    struct ia64_fixup *plt_fixes = NULL, "
2761                 "*ltoff_fixes = NULL;\n"
2762                 "    static long plt_target[] = {\n\t");
2763
2764         max_index = -1;
2765         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2766             sym_idx = ELF64_R_SYM(rel->r_info);
2767             sym_name = (strtab + symtab[sym_idx].st_name);
2768             if (strstart(sym_name, "__op_gen_label", NULL))
2769                 continue;
2770             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2771                 continue;
2772
2773             addend = rel->r_addend;
2774             index = get_plt_index(sym_name, addend);
2775             if (index <= max_index)
2776                 continue;
2777             max_index = index;
2778
2779             if (not_first)
2780                 fprintf(outfile, ",\n\t");
2781             not_first = 1;
2782             if (addend)
2783                 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2784             else
2785                 fprintf(outfile, "(long) &%s", sym_name);
2786         }
2787         fprintf(outfile, "\n    };\n"
2788             "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2789     }
2790 #endif
2791
2792 fprintf(outfile,
2793 "\n"
2794 "    gen_code_ptr = gen_code_buf;\n"
2795 "    opc_ptr = opc_buf;\n"
2796 "    opparam_ptr = opparam_buf;\n");
2797
2798         /* Generate prologue, if needed. */
2799
2800 fprintf(outfile,
2801 "    for(;;) {\n");
2802
2803 #ifdef HOST_ARM
2804 /* Generate constant pool if needed */
2805 fprintf(outfile,
2806 "            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2807 "                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2808 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2809 "                last_gen_code_ptr = gen_code_ptr;\n"
2810 "                arm_ldr_ptr = arm_ldr_table;\n"
2811 "                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2812 "                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2813 "            }\n");
2814 #endif
2815
2816 fprintf(outfile,
2817 "        switch(*opc_ptr++) {\n");
2818
2819         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2820             const char *name;
2821             name = get_sym_name(sym);
2822             if (strstart(name, OP_PREFIX, NULL)) {
2823 #if 0
2824                 printf("%4d: %s pos=0x%08x len=%d\n",
2825                        i, name, sym->st_value, sym->st_size);
2826 #endif
2827 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2828                 if (sym->st_shndx != text_shndx)
2829                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2830 #endif
2831                 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2832             }
2833         }
2834
2835 fprintf(outfile,
2836 "        case INDEX_op_nop:\n"
2837 "            break;\n"
2838 "        case INDEX_op_nop1:\n"
2839 "            opparam_ptr++;\n"
2840 "            break;\n"
2841 "        case INDEX_op_nop2:\n"
2842 "            opparam_ptr += 2;\n"
2843 "            break;\n"
2844 "        case INDEX_op_nop3:\n"
2845 "            opparam_ptr += 3;\n"
2846 "            break;\n"
2847 "        default:\n"
2848 "            goto the_end;\n"
2849 "        }\n");
2850
2851
2852 fprintf(outfile,
2853 "    }\n"
2854 " the_end:\n"
2855 );
2856 #ifdef HOST_IA64
2857     fprintf(outfile,
2858             "    {\n"
2859             "      extern char code_gen_buffer[];\n"
2860             "      ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2861             "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2862             "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2863             "plt_target, plt_offset);\n    }\n");
2864 #endif
2865
2866 /* generate some code patching */
2867 #ifdef HOST_ARM
2868 fprintf(outfile,
2869 "if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2870 "    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2871 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2872 #endif
2873     /* flush instruction cache */
2874     fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2875
2876     fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n");
2877     fprintf(outfile, "}\n\n");
2878
2879     }
2880
2881     return 0;
2882 }
2883
2884 void usage(void)
2885 {
2886     printf("dyngen (c) 2003 Fabrice Bellard\n"
2887            "usage: dyngen [-o outfile] [-c] objfile\n"
2888            "Generate a dynamic code generator from an object file\n"
2889            "-c     output enum of operations\n"
2890            "-g     output gen_op_xx() functions\n"
2891            );
2892     exit(1);
2893 }
2894
2895 int main(int argc, char **argv)
2896 {
2897     int c, out_type;
2898     const char *filename, *outfilename;
2899     FILE *outfile;
2900
2901     outfilename = "out.c";
2902     out_type = OUT_CODE;
2903     for(;;) {
2904         c = getopt(argc, argv, "ho:cg");
2905         if (c == -1)
2906             break;
2907         switch(c) {
2908         case 'h':
2909             usage();
2910             break;
2911         case 'o':
2912             outfilename = optarg;
2913             break;
2914         case 'c':
2915             out_type = OUT_INDEX_OP;
2916             break;
2917         case 'g':
2918             out_type = OUT_GEN_OP;
2919             break;
2920         }
2921     }
2922     if (optind >= argc)
2923         usage();
2924     filename = argv[optind];
2925     outfile = fopen(outfilename, "w");
2926     if (!outfile)
2927         error("could not open '%s'", outfilename);
2928
2929     load_object(filename);
2930     gen_file(outfile, out_type);
2931     fclose(outfile);
2932     return 0;
2933 }