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