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