]> Git Repo - qemu.git/blob - dyngen.c
RAM usage information in machine definition.
[qemu.git] / 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
1763 #if defined(HOST_HPPA)
1764         int op_size = copy_size;
1765         int has_stubs = 0;
1766         char relname[256];
1767         int type, is_label;
1768
1769         for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1770             if (rel->r_offset >= start_offset &&
1771                 rel->r_offset < start_offset + copy_size) {
1772                 sym_name = get_rel_sym_name(rel);
1773                 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
1774                 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1775                 type = ELF32_R_TYPE(rel->r_info);
1776
1777                 if (!is_label && type == R_PARISC_PCREL17F) {
1778                     has_stubs = 1;
1779                     op_size += 8; /* ldil and be,n instructions */
1780                 }
1781             }
1782         }
1783
1784         if (has_stubs)
1785             op_size += 4; /* b,l,n instruction, to skip past the stubs */
1786
1787         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, op_size);
1788 #else
1789         fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1790 #endif
1791
1792     } else if (gen_switch == 1) {
1793
1794         /* output C code */
1795         fprintf(outfile, "case INDEX_%s: {\n", name);
1796         if (nb_args > 0) {
1797             fprintf(outfile, "    long ");
1798             for(i = 0; i < nb_args; i++) {
1799                 if (i != 0)
1800                     fprintf(outfile, ", ");
1801                 fprintf(outfile, "param%d", i + 1);
1802             }
1803             fprintf(outfile, ";\n");
1804         }
1805 #if defined(HOST_IA64)
1806         fprintf(outfile, "    extern char %s;\n", name);
1807 #else
1808         fprintf(outfile, "    extern void %s();\n", name);
1809 #endif
1810
1811         for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1812             host_ulong offset = get_rel_offset(rel);
1813             if (offset >= start_offset &&
1814                 offset < start_offset + (p_end - p_start)) {
1815                 sym_name = get_rel_sym_name(rel);
1816                 if(!sym_name)
1817                     continue;
1818                 if (*sym_name &&
1819                     !strstart(sym_name, "__op_param", NULL) &&
1820                     !strstart(sym_name, "__op_jmp", NULL) &&
1821                     !strstart(sym_name, "__op_gen_label", NULL)) {
1822 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1823                     if (sym_name[0] == '.') {
1824                         fprintf(outfile,
1825                                 "extern char __dot_%s __asm__(\"%s\");\n",
1826                                 sym_name+1, sym_name);
1827                         continue;
1828                     }
1829 #endif
1830 #if defined(__APPLE__)
1831                     /* Set __attribute((unused)) on darwin because we
1832                        want to avoid warning when we don't use the symbol.  */
1833                     fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1834 #elif defined(HOST_IA64)
1835                         if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1836                                 /*
1837                                  * PCREL21 br.call targets generally
1838                                  * are out of range and need to go
1839                                  * through an "import stub".
1840                                  */
1841                                 fprintf(outfile, "    extern char %s;\n",
1842                                         sym_name);
1843 #else
1844                     fprintf(outfile, "extern char %s;\n", sym_name);
1845 #endif
1846                 }
1847             }
1848         }
1849
1850 #ifdef __hppa__
1851         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1852                                         name, (int)(start_offset - offset), copy_size);
1853 #else
1854         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1855                                         name, (int)(start_offset - offset), copy_size);
1856 #endif
1857
1858         /* emit code offset information */
1859         {
1860             EXE_SYM *sym;
1861             const char *sym_name, *p;
1862             host_ulong val;
1863             int n;
1864
1865             for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1866                 sym_name = get_sym_name(sym);
1867                 if (strstart(sym_name, "__op_label", &p)) {
1868                     uint8_t *ptr;
1869                     unsigned long offset;
1870
1871                     /* test if the variable refers to a label inside
1872                        the code we are generating */
1873 #ifdef CONFIG_FORMAT_COFF
1874                     if (sym->st_shndx == text_shndx) {
1875                         ptr = sdata[coff_text_shndx];
1876                     } else if (sym->st_shndx == data_shndx) {
1877                         ptr = sdata[coff_data_shndx];
1878                     } else {
1879                         ptr = NULL;
1880                     }
1881 #elif defined(CONFIG_FORMAT_MACH)
1882                     if(!sym->n_sect)
1883                         continue;
1884                     ptr = sdata[sym->n_sect-1];
1885 #else
1886                     ptr = sdata[sym->st_shndx];
1887 #endif
1888                     if (!ptr)
1889                         error("__op_labelN in invalid section");
1890                     offset = sym->st_value;
1891 #ifdef CONFIG_FORMAT_MACH
1892                     offset -= section_hdr[sym->n_sect-1].addr;
1893 #endif
1894                     val = *(host_ulong *)(ptr + offset);
1895 #ifdef ELF_USES_RELOCA
1896                     {
1897                         int reloc_shndx, nb_relocs1, j;
1898
1899                         /* try to find a matching relocation */
1900                         reloc_shndx = find_reloc(sym->st_shndx);
1901                         if (reloc_shndx) {
1902                             nb_relocs1 = shdr[reloc_shndx].sh_size /
1903                                 shdr[reloc_shndx].sh_entsize;
1904                             rel = (ELF_RELOC *)sdata[reloc_shndx];
1905                             for(j = 0; j < nb_relocs1; j++) {
1906                                 if (rel->r_offset == offset) {
1907                                     val = rel->r_addend;
1908                                     break;
1909                                 }
1910                                 rel++;
1911                             }
1912                         }
1913                     }
1914 #endif
1915                     if (val >= start_offset && val <= start_offset + copy_size) {
1916                         n = strtol(p, NULL, 10);
1917                         fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1918                     }
1919                 }
1920             }
1921         }
1922
1923         /* load parameters in variables */
1924         for(i = 0; i < nb_args; i++) {
1925             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1926         }
1927
1928         /* patch relocations */
1929 #if defined(HOST_I386)
1930             {
1931                 char relname[256];
1932                 int type, is_label;
1933                 int addend;
1934                 int reloc_offset;
1935                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1936                 if (rel->r_offset >= start_offset &&
1937                     rel->r_offset < start_offset + copy_size) {
1938                     sym_name = get_rel_sym_name(rel);
1939                     if (!sym_name)
1940                         continue;
1941                     reloc_offset = rel->r_offset - start_offset;
1942                     if (strstart(sym_name, "__op_jmp", &p)) {
1943                         int n;
1944                         n = strtol(p, NULL, 10);
1945                         /* __op_jmp relocations are done at
1946                            runtime to do translated block
1947                            chaining: the offset of the instruction
1948                            needs to be stored */
1949                         fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1950                                 n, reloc_offset);
1951                         continue;
1952                     }
1953
1954                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1955                     addend = get32((uint32_t *)(text + rel->r_offset));
1956 #ifdef CONFIG_FORMAT_ELF
1957                     type = ELF32_R_TYPE(rel->r_info);
1958                     if (is_label) {
1959                         switch(type) {
1960                         case R_386_32:
1961                         case R_386_PC32:
1962                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1963                                     reloc_offset, type, relname, addend);
1964                             break;
1965                         default:
1966                             error("unsupported i386 relocation (%d)", type);
1967                         }
1968                     } else {
1969                         switch(type) {
1970                         case R_386_32:
1971                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1972                                     reloc_offset, relname, addend);
1973                             break;
1974                         case R_386_PC32:
1975                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1976                                     reloc_offset, relname, reloc_offset, addend);
1977                             break;
1978                         default:
1979                             error("unsupported i386 relocation (%d)", type);
1980                         }
1981                     }
1982 #elif defined(CONFIG_FORMAT_COFF)
1983                     {
1984                         char *temp_name;
1985                         int j;
1986                         EXE_SYM *sym;
1987                         temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1988                         if (!strcmp(temp_name, ".data")) {
1989                             for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1990                                 if (strstart(sym->st_name, sym_name, NULL)) {
1991                                     addend -= sym->st_value;
1992                                 }
1993                             }
1994                         }
1995                     }
1996                     type = rel->r_type;
1997                     if (is_label) {
1998 /* TCG uses elf relocation constants */
1999 #define R_386_32        1
2000 #define R_386_PC32      2
2001                         switch(type) {
2002                         case DIR32:
2003                             type = R_386_32;
2004                             goto do_reloc;
2005                         case DISP32:
2006                             type = R_386_PC32;
2007                             addend -= 4;
2008                         do_reloc:
2009                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2010                                     reloc_offset, type, relname, addend);
2011                             break;
2012                         default:
2013                             error("unsupported i386 relocation (%d)", type);
2014                         }
2015                     } else {
2016                         switch(type) {
2017                         case DIR32:
2018                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2019                                     reloc_offset, relname, addend);
2020                             break;
2021                         case DISP32:
2022                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
2023                                     reloc_offset, relname, reloc_offset, addend);
2024                             break;
2025                         default:
2026                             error("unsupported i386 relocation (%d)", type);
2027                         }
2028                     }
2029 #else
2030 #error unsupport object format
2031 #endif
2032                 }
2033                 }
2034             }
2035 #elif defined(HOST_X86_64)
2036             {
2037                 char relname[256];
2038                 int type, is_label;
2039                 int addend;
2040                 int reloc_offset;
2041                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2042                 if (rel->r_offset >= start_offset &&
2043                     rel->r_offset < start_offset + copy_size) {
2044                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2045                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2046                     type = ELF32_R_TYPE(rel->r_info);
2047                     addend = rel->r_addend;
2048                     reloc_offset = rel->r_offset - start_offset;
2049                     if (is_label) {
2050                         switch(type) {
2051                         case R_X86_64_32:
2052                         case R_X86_64_32S:
2053                         case R_X86_64_PC32:
2054                             fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2055                                     reloc_offset, type, relname, addend);
2056                             break;
2057                         default:
2058                             error("unsupported X86_64 relocation (%d)", type);
2059                         }
2060                     } else {
2061                         switch(type) {
2062                         case R_X86_64_32:
2063                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2064                                     reloc_offset, relname, addend);
2065                             break;
2066                         case R_X86_64_32S:
2067                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2068                                     reloc_offset, relname, addend);
2069                             break;
2070                         case R_X86_64_PC32:
2071                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2072                                     reloc_offset, relname, reloc_offset, addend);
2073                             break;
2074                         default:
2075                             error("unsupported X86_64 relocation (%d)", type);
2076                         }
2077                     }
2078                 }
2079                 }
2080             }
2081 #elif defined(HOST_PPC)
2082             {
2083 #ifdef CONFIG_FORMAT_ELF
2084                 char relname[256];
2085                 int type;
2086                 int addend;
2087                 int reloc_offset;
2088                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2089                     if (rel->r_offset >= start_offset &&
2090                         rel->r_offset < start_offset + copy_size) {
2091                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2092                         reloc_offset = rel->r_offset - start_offset;
2093                         if (strstart(sym_name, "__op_jmp", &p)) {
2094                             int n;
2095                             n = strtol(p, NULL, 10);
2096                             /* __op_jmp relocations are done at
2097                                runtime to do translated block
2098                                chaining: the offset of the instruction
2099                                needs to be stored */
2100                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2101                                     n, reloc_offset);
2102                             continue;
2103                         }
2104
2105                         get_reloc_expr(relname, sizeof(relname), sym_name);
2106                         type = ELF32_R_TYPE(rel->r_info);
2107                         addend = rel->r_addend;
2108                         switch(type) {
2109                         case R_PPC_ADDR32:
2110                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2111                                     reloc_offset, relname, addend);
2112                             break;
2113                         case R_PPC_ADDR16_LO:
2114                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2115                                     reloc_offset, relname, addend);
2116                             break;
2117                         case R_PPC_ADDR16_HI:
2118                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2119                                     reloc_offset, relname, addend);
2120                             break;
2121                         case R_PPC_ADDR16_HA:
2122                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2123                                     reloc_offset, relname, addend);
2124                             break;
2125                         case R_PPC_REL24:
2126                             /* warning: must be at 32 MB distancy */
2127                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2128                                     reloc_offset, reloc_offset, relname, reloc_offset, addend);
2129                             break;
2130                         default:
2131                             error("unsupported powerpc relocation (%d)", type);
2132                         }
2133                     }
2134                 }
2135 #elif defined(CONFIG_FORMAT_MACH)
2136                 struct scattered_relocation_info *scarel;
2137                 struct relocation_info * rel;
2138                 char final_sym_name[256];
2139                 const char *sym_name;
2140                 const char *p;
2141                 int slide, sslide;
2142                 int i;
2143
2144                 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2145                     unsigned int offset, length, value = 0;
2146                     unsigned int type, pcrel, isym = 0;
2147                     unsigned int usesym = 0;
2148
2149                     if(R_SCATTERED & rel->r_address) {
2150                         scarel = (struct scattered_relocation_info*)rel;
2151                         offset = (unsigned int)scarel->r_address;
2152                         length = scarel->r_length;
2153                         pcrel = scarel->r_pcrel;
2154                         type = scarel->r_type;
2155                         value = scarel->r_value;
2156                     } else {
2157                         value = isym = rel->r_symbolnum;
2158                         usesym = (rel->r_extern);
2159                         offset = rel->r_address;
2160                         length = rel->r_length;
2161                         pcrel = rel->r_pcrel;
2162                         type = rel->r_type;
2163                     }
2164
2165                     slide = offset - start_offset;
2166
2167                     if (!(offset >= start_offset && offset < start_offset + size))
2168                         continue;  /* not in our range */
2169
2170                         sym_name = get_reloc_name(rel, &sslide);
2171
2172                         if(usesym && symtab[isym].n_type & N_STAB)
2173                             continue; /* don't handle STAB (debug sym) */
2174
2175                         if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2176                             int n;
2177                             n = strtol(p, NULL, 10);
2178                             fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2179                                     n, slide);
2180                             continue; /* Nothing more to do */
2181                         }
2182
2183                         if(!sym_name) {
2184                             fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2185                                     name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2186                             continue; /* dunno how to handle without final_sym_name */
2187                         }
2188
2189                         get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2190                                        sym_name);
2191                         switch(type) {
2192                         case PPC_RELOC_BR24:
2193                             if (!strstart(sym_name,"__op_gen_label",&p)) {
2194                                 fprintf(outfile, "{\n");
2195                                 fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2196                                 fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
2197                                         slide, slide, name, sslide);
2198                                 fprintf(outfile, "}\n");
2199                             } else {
2200                                 fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2201                                         slide, slide, final_sym_name, slide);
2202                             }
2203                             break;
2204                         case PPC_RELOC_HI16:
2205                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2206                                     slide, final_sym_name, sslide);
2207                             break;
2208                         case PPC_RELOC_LO16:
2209                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2210                                     slide, final_sym_name, sslide);
2211                             break;
2212                         case PPC_RELOC_HA16:
2213                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2214                                     slide, final_sym_name, sslide);
2215                             break;
2216                         default:
2217                             error("unsupported powerpc relocation (%d)", type);
2218                     }
2219                 }
2220 #else
2221 #error unsupport object format
2222 #endif
2223             }
2224 #elif defined(HOST_S390)
2225             {
2226                 char relname[256];
2227                 int type;
2228                 int addend;
2229                 int reloc_offset;
2230                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2231                     if (rel->r_offset >= start_offset &&
2232                         rel->r_offset < start_offset + copy_size) {
2233                         sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2234                         get_reloc_expr(relname, sizeof(relname), sym_name);
2235                         type = ELF32_R_TYPE(rel->r_info);
2236                         addend = rel->r_addend;
2237                         reloc_offset = rel->r_offset - start_offset;
2238                         switch(type) {
2239                         case R_390_32:
2240                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2241                                     reloc_offset, relname, addend);
2242                             break;
2243                         case R_390_16:
2244                             fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2245                                     reloc_offset, relname, addend);
2246                             break;
2247                         case R_390_8:
2248                             fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2249                                     reloc_offset, relname, addend);
2250                             break;
2251                         case R_390_PC32DBL:
2252                             if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2253                                 fprintf(outfile,
2254                                         "    *(uint32_t *)(gen_code_ptr + %d) += "
2255                                         "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2256                                         reloc_offset, name);
2257                             }
2258                             else
2259                                 fprintf(outfile,
2260                                         "    *(uint32_t *)(gen_code_ptr + %d) = "
2261                                         "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2262                                         reloc_offset, relname, addend, reloc_offset);
2263                             break;
2264                         default:
2265                             error("unsupported s390 relocation (%d)", type);
2266                         }
2267                     }
2268                 }
2269             }
2270 #elif defined(HOST_ALPHA)
2271             {
2272                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2273                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2274                         int type;
2275                         long reloc_offset;
2276
2277                         type = ELF64_R_TYPE(rel->r_info);
2278                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2279                         reloc_offset = rel->r_offset - start_offset;
2280                         switch (type) {
2281                         case R_ALPHA_GPDISP:
2282                             /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2283                                as an immediate instead of constructing it from the pv or ra.  */
2284                             fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2285                                     reloc_offset);
2286                             fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2287                                     reloc_offset + (int)rel->r_addend);
2288                             break;
2289                         case R_ALPHA_LITUSE:
2290                             /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2291                                now, since some called functions (libc) need pv to be set up.  */
2292                             break;
2293                         case R_ALPHA_HINT:
2294                             /* Branch target prediction hint. Ignore for now.  Should be already
2295                                correct for in-function jumps.  */
2296                             break;
2297                         case R_ALPHA_LITERAL:
2298                             /* Load a literal from the GOT relative to the gp.  Since there's only a
2299                                single gp, nothing is to be done.  */
2300                             break;
2301                         case R_ALPHA_GPRELHIGH:
2302                             /* Handle fake relocations against __op_param symbol.  Need to emit the
2303                                high part of the immediate value instead.  Other symbols need no
2304                                special treatment.  */
2305                             if (strstart(sym_name, "__op_param", &p))
2306                                 fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2307                                         reloc_offset, p);
2308                             break;
2309                         case R_ALPHA_GPRELLOW:
2310                             if (strstart(sym_name, "__op_param", &p))
2311                                 fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2312                                         reloc_offset, p);
2313                             break;
2314                         case R_ALPHA_BRSGP:
2315                             /* PC-relative jump. Tweak offset to skip the two instructions that try to
2316                                set up the gp from the pv.  */
2317                             fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2318                                     reloc_offset, sym_name, reloc_offset);
2319                             break;
2320                         default:
2321                             error("unsupported Alpha relocation (%d)", type);
2322                         }
2323                     }
2324                 }
2325             }
2326 #elif defined(HOST_IA64)
2327             {
2328                 unsigned long sym_idx;
2329                 long code_offset;
2330                 char relname[256];
2331                 int type;
2332                 long addend;
2333
2334                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2335                     sym_idx = ELF64_R_SYM(rel->r_info);
2336                     if (rel->r_offset < start_offset
2337                         || rel->r_offset >= start_offset + copy_size)
2338                         continue;
2339                     sym_name = (strtab + symtab[sym_idx].st_name);
2340                     code_offset = rel->r_offset - start_offset;
2341                     if (strstart(sym_name, "__op_jmp", &p)) {
2342                         int n;
2343                         n = strtol(p, NULL, 10);
2344                         /* __op_jmp relocations are done at
2345                            runtime to do translated block
2346                            chaining: the offset of the instruction
2347                            needs to be stored */
2348                         fprintf(outfile, "    jmp_offsets[%d] ="
2349                                 "%ld + (gen_code_ptr - gen_code_buf);\n",
2350                                 n, code_offset);
2351                         continue;
2352                     }
2353                     get_reloc_expr(relname, sizeof(relname), sym_name);
2354                     type = ELF64_R_TYPE(rel->r_info);
2355                     addend = rel->r_addend;
2356                     switch(type) {
2357                       case R_IA64_IMM64:
2358                           fprintf(outfile,
2359                                   "    ia64_imm64(gen_code_ptr + %ld, "
2360                                   "%s + %ld);\n",
2361                                   code_offset, relname, addend);
2362                           break;
2363                       case R_IA64_LTOFF22X:
2364                       case R_IA64_LTOFF22:
2365                           fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2366                                   " %s + %ld, %d);\n",
2367                                   code_offset, relname, addend,
2368                                   (type == R_IA64_LTOFF22X));
2369                           break;
2370                       case R_IA64_LDXMOV:
2371                           fprintf(outfile,
2372                                   "    ia64_ldxmov(gen_code_ptr + %ld,"
2373                                   " %s + %ld);\n", code_offset, relname, addend);
2374                           break;
2375
2376                       case R_IA64_PCREL21B:
2377                           if (strstart(sym_name, "__op_gen_label", NULL)) {
2378                               fprintf(outfile,
2379                                       "    ia64_imm21b(gen_code_ptr + %ld,"
2380                                       " (long) (%s + %ld -\n\t\t"
2381                                       "((long) gen_code_ptr + %ld)) >> 4);\n",
2382                                       code_offset, relname, addend,
2383                                       code_offset & ~0xfUL);
2384                           } else {
2385                               fprintf(outfile,
2386                                       "    IA64_PLT(gen_code_ptr + %ld, "
2387                                       "%d);\t/* %s + %ld */\n",
2388                                       code_offset,
2389                                       get_plt_index(sym_name, addend),
2390                                       sym_name, addend);
2391                           }
2392                           break;
2393                       default:
2394                           error("unsupported ia64 relocation (0x%x)",
2395                                 type);
2396                     }
2397                 }
2398                 fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2399                         copy_size - 16 + 2);
2400             }
2401 #elif defined(HOST_SPARC)
2402             {
2403                 char relname[256];
2404                 int type;
2405                 int addend;
2406                 int reloc_offset;
2407                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2408                     if (rel->r_offset >= start_offset &&
2409                         rel->r_offset < start_offset + copy_size) {
2410                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2411                         get_reloc_expr(relname, sizeof(relname), sym_name);
2412                         type = ELF32_R_TYPE(rel->r_info);
2413                         addend = rel->r_addend;
2414                         reloc_offset = rel->r_offset - start_offset;
2415                         switch(type) {
2416                         case R_SPARC_32:
2417                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2418                                     reloc_offset, relname, addend);
2419                             break;
2420                         case R_SPARC_HI22:
2421                             fprintf(outfile,
2422                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2423                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2424                                     " & ~0x3fffff) "
2425                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2426                                     reloc_offset, reloc_offset, relname, addend);
2427                             break;
2428                         case R_SPARC_LO10:
2429                             fprintf(outfile,
2430                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2431                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2432                                     " & ~0x3ff) "
2433                                     " | ((%s + %d) & 0x3ff);\n",
2434                                     reloc_offset, reloc_offset, relname, addend);
2435                             break;
2436                         case R_SPARC_WDISP30:
2437                             fprintf(outfile,
2438                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2439                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2440                                     " & ~0x3fffffff) "
2441                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2442                                     "    & 0x3fffffff);\n",
2443                                     reloc_offset, reloc_offset, relname, addend,
2444                                     reloc_offset);
2445                             break;
2446                         case R_SPARC_WDISP22:
2447                             fprintf(outfile,
2448                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2449                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2450                                     " & ~0x3fffff) "
2451                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2452                                     "    & 0x3fffff);\n",
2453                                     rel->r_offset - start_offset,
2454                                     rel->r_offset - start_offset,
2455                                     relname, addend,
2456                                     rel->r_offset - start_offset);
2457                             break;
2458                         default:
2459                             error("unsupported sparc relocation (%d)", type);
2460                         }
2461                     }
2462                 }
2463             }
2464 #elif defined(HOST_SPARC64)
2465             {
2466                 char relname[256];
2467                 int type;
2468                 int addend;
2469                 int reloc_offset;
2470                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2471                     if (rel->r_offset >= start_offset &&
2472                         rel->r_offset < start_offset + copy_size) {
2473                         sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2474                         get_reloc_expr(relname, sizeof(relname), sym_name);
2475                         type = ELF32_R_TYPE(rel->r_info);
2476                         addend = rel->r_addend;
2477                         reloc_offset = rel->r_offset - start_offset;
2478                         switch(type) {
2479                         case R_SPARC_32:
2480                             fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2481                                     reloc_offset, relname, addend);
2482                             break;
2483                         case R_SPARC_HI22:
2484                             fprintf(outfile,
2485                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2486                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2487                                     " & ~0x3fffff) "
2488                                     " | (((%s + %d) >> 10) & 0x3fffff);\n",
2489                                     reloc_offset, reloc_offset, relname, addend);
2490                             break;
2491                         case R_SPARC_LO10:
2492                             fprintf(outfile,
2493                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2494                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2495                                     " & ~0x3ff) "
2496                                     " | ((%s + %d) & 0x3ff);\n",
2497                                     reloc_offset, reloc_offset, relname, addend);
2498                             break;
2499                         case R_SPARC_OLO10:
2500                             addend += ELF64_R_TYPE_DATA (rel->r_info);
2501                             fprintf(outfile,
2502                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2503                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2504                                     " & ~0x3ff) "
2505                                     " | ((%s + %d) & 0x3ff);\n",
2506                                     reloc_offset, reloc_offset, relname, addend);
2507                             break;
2508                         case R_SPARC_WDISP30:
2509                             fprintf(outfile,
2510                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2511                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2512                                     " & ~0x3fffffff) "
2513                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2514                                     "    & 0x3fffffff);\n",
2515                                     reloc_offset, reloc_offset, relname, addend,
2516                                     reloc_offset);
2517                             break;
2518                         case R_SPARC_WDISP22:
2519                             fprintf(outfile,
2520                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2521                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2522                                     " & ~0x3fffff) "
2523                                     " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2524                                     "    & 0x3fffff);\n",
2525                                     reloc_offset, reloc_offset, relname, addend,
2526                                     reloc_offset);
2527                             break;
2528                         case R_SPARC_HH22:
2529                             fprintf(outfile,
2530                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2531                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2532                                     " & ~0x00000000) "
2533                                     " | (((%s + %d) >> 42) & 0x00000000);\n",
2534                                     reloc_offset, reloc_offset, relname, addend);
2535                              break;
2536
2537                         case R_SPARC_LM22:
2538                             fprintf(outfile,
2539                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2540                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2541                                     " & ~0x00000000) "
2542                                     " | (((%s + %d) >> 10) & 0x00000000);\n",
2543                                     reloc_offset, reloc_offset, relname, addend);
2544                             break;
2545
2546                         case R_SPARC_HM10:
2547                             fprintf(outfile,
2548                                     "    *(uint32_t *)(gen_code_ptr + %d) = "
2549                                     "((*(uint32_t *)(gen_code_ptr + %d)) "
2550                                     " & ~0x00000000) "
2551                                     " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2552                                     reloc_offset, reloc_offset, relname, addend);
2553                             break;
2554
2555                         default:
2556                             error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2557                         }
2558                     }
2559                 }
2560             }
2561 #elif defined(HOST_ARM)
2562             {
2563                 char relname[256];
2564                 int type;
2565                 int addend;
2566                 int reloc_offset;
2567                 uint32_t insn;
2568
2569                 insn = get32((uint32_t *)(p_start + 4));
2570                 /* If prologue ends in sub sp, sp, #const then assume
2571                    op has a stack frame and needs the frame pointer.  */
2572                 if ((insn & 0xffffff00) == 0xe24dd000) {
2573                     int i;
2574                     uint32_t opcode;
2575                     opcode = 0xe28db000; /* add fp, sp, #0.  */
2576 #if 0
2577 /* ??? Need to undo the extra stack adjustment at the end of the op.
2578    For now just leave the stack misaligned and hope it doesn't break anything
2579    too important.  */
2580                     if ((insn & 4) != 0) {
2581                         /* Preserve doubleword stack alignment.  */
2582                         fprintf(outfile,
2583                                 "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2584                                 insn + 4);
2585                         opcode -= 4;
2586                     }
2587 #endif
2588                     insn = get32((uint32_t *)(p_start - 4));
2589                     /* Calculate the size of the saved registers,
2590                        excluding pc.  */
2591                     for (i = 0; i < 15; i++) {
2592                         if (insn & (1 << i))
2593                             opcode += 4;
2594                     }
2595                     fprintf(outfile,
2596                             "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2597                 }
2598                 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2599                                   relocs, nb_relocs);
2600
2601                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2602                 if (rel->r_offset >= start_offset &&
2603                     rel->r_offset < start_offset + copy_size) {
2604                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2605                     /* the compiler leave some unnecessary references to the code */
2606                     if (sym_name[0] == '\0')
2607                         continue;
2608                     get_reloc_expr(relname, sizeof(relname), sym_name);
2609                     type = ELF32_R_TYPE(rel->r_info);
2610                     addend = get32((uint32_t *)(text + rel->r_offset));
2611                     reloc_offset = rel->r_offset - start_offset;
2612                     switch(type) {
2613                     case R_ARM_ABS32:
2614                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2615                                 reloc_offset, relname, addend);
2616                         break;
2617                     case R_ARM_PC24:
2618                     case R_ARM_JUMP24:
2619                     case R_ARM_CALL:
2620                         fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2621                                 reloc_offset, addend, relname);
2622                         break;
2623                     default:
2624                         error("unsupported arm relocation (%d)", type);
2625                     }
2626                 }
2627                 }
2628             }
2629 #elif defined(HOST_M68K)
2630             {
2631                 char relname[256];
2632                 int type;
2633                 int addend;
2634                 int reloc_offset;
2635                 Elf32_Sym *sym;
2636                 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2637                 if (rel->r_offset >= start_offset &&
2638                     rel->r_offset < start_offset + copy_size) {
2639                     sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2640                     sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2641                     get_reloc_expr(relname, sizeof(relname), sym_name);
2642                     type = ELF32_R_TYPE(rel->r_info);
2643                     addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2644                     reloc_offset = rel->r_offset - start_offset;
2645                     switch(type) {
2646                     case R_68K_32:
2647                         fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2648                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2649                                 reloc_offset, relname, addend );
2650                         break;
2651                     case R_68K_PC32:
2652                         fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2653                         fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2654                                 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2655                         break;
2656                     default:
2657                         error("unsupported m68k relocation (%d)", type);
2658                     }
2659                 }
2660                 }
2661             }
2662 #elif defined(HOST_HPPA)
2663             {
2664                 char relname[256];
2665                 int type, is_label;
2666                 int addend;
2667                 int reloc_offset;
2668                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2669                 if (rel->r_offset >= start_offset &&
2670                     rel->r_offset < start_offset + copy_size) {
2671                     sym_name = get_rel_sym_name(rel);
2672                     sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2673                     is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2674                     type = ELF32_R_TYPE(rel->r_info);
2675                     addend = rel->r_addend;
2676                     reloc_offset = rel->r_offset - start_offset;
2677
2678                     if (is_label) {
2679                         switch (type) {
2680                         case R_PARISC_PCREL17F:
2681                             fprintf(outfile,
2682 "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2683                                     reloc_offset, type, relname, addend);
2684                             break;
2685                         default:
2686                             error("unsupported hppa label relocation (%d)", type);
2687                         }
2688                     } else {
2689                         switch (type) {
2690                         case R_PARISC_DIR21L:
2691                             fprintf(outfile,
2692 "    hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2693                                     reloc_offset, relname, addend);
2694                             break;
2695                         case R_PARISC_DIR14R:
2696                             fprintf(outfile,
2697 "    hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2698                                     reloc_offset, relname, addend);
2699                             break;
2700                         case R_PARISC_PCREL17F:
2701                             if (strstart(sym_name, "__op_gen_label", NULL)) {
2702                                 fprintf(outfile,
2703 "    hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2704                                         reloc_offset, relname, addend);
2705                             } else {
2706                                 fprintf(outfile,
2707 "    HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2708                                         reloc_offset, relname);
2709                             }
2710                             break;
2711                         case R_PARISC_DPREL21L:
2712                             if (strstart(sym_name, "__op_param", &p))
2713                                 fprintf(outfile,
2714 "    hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2715                                         reloc_offset, p, addend);
2716                             else
2717                                 fprintf(outfile,
2718 "    hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2719                                         reloc_offset, relname, addend);
2720                             break;
2721                         case R_PARISC_DPREL14R:
2722                             if (strstart(sym_name, "__op_param", &p))
2723                                 fprintf(outfile,
2724 "    hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2725                                         reloc_offset, p, addend);
2726                             else
2727                                 fprintf(outfile,
2728 "    hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2729                                         reloc_offset, relname, addend);
2730                             break;
2731                         default:
2732                             error("unsupported hppa relocation (%d)", type);
2733                         }
2734                     }
2735                 }
2736                 }
2737             }
2738 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2739             {
2740                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2741                     if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2742                         char relname[256];
2743                         int type;
2744                         int addend;
2745                         int reloc_offset;
2746
2747                         sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2748                         /* the compiler leave some unnecessary references to the code */
2749                         if (sym_name[0] == '\0')
2750                             continue;
2751                         get_reloc_expr(relname, sizeof(relname), sym_name);
2752                         type = ELF32_R_TYPE(rel->r_info);
2753                         addend = get32((uint32_t *)(text + rel->r_offset));
2754                         reloc_offset = rel->r_offset - start_offset;
2755                         switch (type) {
2756                         case R_MIPS_26:
2757                             fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2758                                     rel->r_offset, sym_name);
2759                             fprintf(outfile,
2760                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2761                                     "(0x%x & ~0x3fffff) "
2762                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2763                                     "   & 0x3fffff);\n",
2764                                     reloc_offset, addend, addend, relname, reloc_offset);
2765                             break;
2766                         case R_MIPS_HI16:
2767                             fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2768                                     rel->r_offset, sym_name);
2769                             fprintf(outfile,
2770                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2771                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2772                                     " & ~0xffff) "
2773                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2774                                     reloc_offset, reloc_offset, relname);
2775                             break;
2776                         case R_MIPS_LO16:
2777                             fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2778                                     rel->r_offset, sym_name);
2779                             fprintf(outfile,
2780                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2781                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2782                                     " & ~0xffff) "
2783                                     " | (%s & 0xffff);\n",
2784                                     reloc_offset, reloc_offset, relname);
2785                             break;
2786                         case R_MIPS_PC16:
2787                             fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2788                                     rel->r_offset, sym_name);
2789                             fprintf(outfile,
2790                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2791                                     "(0x%x & ~0xffff) "
2792                                     "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2793                                     "   & 0xffff);\n",
2794                                     reloc_offset, addend, addend, relname, reloc_offset);
2795                             break;
2796                         case R_MIPS_GOT16:
2797                         case R_MIPS_CALL16:
2798                             fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2799                                     rel->r_offset, sym_name);
2800                             fprintf(outfile,
2801                                     "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2802                                     "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2803                                     " & ~0xffff) "
2804                                     " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2805                                     reloc_offset, reloc_offset, relname);
2806                             break;
2807                         default:
2808                             error("unsupported MIPS relocation (%d)", type);
2809                         }
2810                     }
2811                 }
2812             }
2813 #else
2814 #error unsupported CPU
2815 #endif
2816         fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2817         fprintf(outfile, "}\n");
2818         fprintf(outfile, "break;\n\n");
2819     } else {
2820         fprintf(outfile, "static inline void gen_%s(", name);
2821         if (nb_args == 0) {
2822             fprintf(outfile, "void");
2823         } else {
2824             for(i = 0; i < nb_args; i++) {
2825                 if (i != 0)
2826                     fprintf(outfile, ", ");
2827                 fprintf(outfile, "long param%d", i + 1);
2828             }
2829         }
2830         fprintf(outfile, ")\n");
2831         fprintf(outfile, "{\n");
2832         for(i = 0; i < nb_args; i++) {
2833             fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2834         }
2835         fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2836         fprintf(outfile, "}\n\n");
2837     }
2838 }
2839
2840 int gen_file(FILE *outfile, int out_type)
2841 {
2842     int i;
2843     EXE_SYM *sym;
2844
2845     if (out_type == OUT_INDEX_OP) {
2846         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2847             const char *name;
2848             name = get_sym_name(sym);
2849             if (strstart(name, OP_PREFIX, NULL)) {
2850                 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2851             }
2852         }
2853     } else if (out_type == OUT_GEN_OP) {
2854         /* generate gen_xxx functions */
2855         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2856             const char *name;
2857             name = get_sym_name(sym);
2858             if (strstart(name, OP_PREFIX, NULL)) {
2859 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2860                 if (sym->st_shndx != text_shndx)
2861                     error("invalid section for opcode (0x%x)", sym->st_shndx);
2862 #endif
2863                 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2864             }
2865         }
2866
2867     } else {
2868         /* generate big code generation switch */
2869
2870 #ifdef HOST_ARM
2871 #error broken
2872         /* We need to know the size of all the ops so we can figure out when
2873            to emit constant pools.  This must be consistent with opc.h.  */
2874 fprintf(outfile,
2875 "static const uint32_t arm_opc_size[] = {\n"
2876 "  0,\n" /* end */
2877 "  0,\n" /* nop */
2878 "  0,\n" /* nop1 */
2879 "  0,\n" /* nop2 */
2880 "  0,\n"); /* nop3 */
2881         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2882             const char *name;
2883             name = get_sym_name(sym);
2884             if (strstart(name, OP_PREFIX, NULL)) {
2885                 fprintf(outfile, "  %d,\n", sym->st_size);
2886             }
2887         }
2888 fprintf(outfile,
2889 "};\n");
2890 #endif
2891
2892 #ifdef HOST_ARM
2893 #error broken
2894 /* Arm is tricky because it uses constant pools for loading immediate values.
2895    We assume (and require) each function is code followed by a constant pool.
2896    All the ops are small so this should be ok.  For each op we figure
2897    out how much "spare" range we have in the load instructions.  This allows
2898    us to insert subsequent ops in between the op and the constant pool,
2899    eliminating the neeed to jump around the pool.
2900
2901    We currently generate:
2902
2903    [ For this example we assume merging would move op1_pool out of range.
2904      In practice we should be able to combine many ops before the offset
2905      limits are reached. ]
2906    op1_code;
2907    op2_code;
2908    goto op3;
2909    op2_pool;
2910    op1_pool;
2911 op3:
2912    op3_code;
2913    ret;
2914    op3_pool;
2915
2916    Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2917  */
2918 fprintf(outfile,
2919 "    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2920 "    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2921 "    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2922 /* Initialise the parmissible pool offset to an arbitary large value.  */
2923 "    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2924 #endif
2925 #ifdef HOST_IA64
2926 #error broken
2927     {
2928         long addend, not_first = 0;
2929         unsigned long sym_idx;
2930         int index, max_index;
2931         const char *sym_name;
2932         EXE_RELOC *rel;
2933
2934         max_index = -1;
2935         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2936             sym_idx = ELF64_R_SYM(rel->r_info);
2937             sym_name = (strtab + symtab[sym_idx].st_name);
2938             if (strstart(sym_name, "__op_gen_label", NULL))
2939                 continue;
2940             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2941                 continue;
2942
2943             addend = rel->r_addend;
2944             index = get_plt_index(sym_name, addend);
2945             if (index <= max_index)
2946                 continue;
2947             max_index = index;
2948             fprintf(outfile, "    extern void %s(void);\n", sym_name);
2949         }
2950
2951         fprintf(outfile,
2952                 "    struct ia64_fixup *plt_fixes = NULL, "
2953                 "*ltoff_fixes = NULL;\n"
2954                 "    static long plt_target[] = {\n\t");
2955
2956         max_index = -1;
2957         for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2958             sym_idx = ELF64_R_SYM(rel->r_info);
2959             sym_name = (strtab + symtab[sym_idx].st_name);
2960             if (strstart(sym_name, "__op_gen_label", NULL))
2961                 continue;
2962             if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2963                 continue;
2964
2965             addend = rel->r_addend;
2966             index = get_plt_index(sym_name, addend);
2967             if (index <= max_index)
2968                 continue;
2969             max_index = index;
2970
2971             if (not_first)
2972                 fprintf(outfile, ",\n\t");
2973             not_first = 1;
2974             if (addend)
2975                 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2976             else
2977                 fprintf(outfile, "(long) &%s", sym_name);
2978         }
2979         fprintf(outfile, "\n    };\n"
2980             "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2981     }
2982 #endif
2983
2984 #ifdef HOST_ARM
2985 #error broken
2986 /* Generate constant pool if needed */
2987 fprintf(outfile,
2988 "            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2989 "                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2990 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2991 "                last_gen_code_ptr = gen_code_ptr;\n"
2992 "                arm_ldr_ptr = arm_ldr_table;\n"
2993 "                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2994 "                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2995 "            }\n");
2996 #endif
2997
2998         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2999             const char *name;
3000             name = get_sym_name(sym);
3001             if (strstart(name, OP_PREFIX, NULL)) {
3002 #if 0
3003                 printf("%4d: %s pos=0x%08x len=%d\n",
3004                        i, name, sym->st_value, sym->st_size);
3005 #endif
3006 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
3007                 if (sym->st_shndx != text_shndx)
3008                     error("invalid section for opcode (0x%x)", sym->st_shndx);
3009 #endif
3010                 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
3011             }
3012         }
3013     }
3014
3015     return 0;
3016 }
3017
3018 void usage(void)
3019 {
3020     printf("dyngen (c) 2003 Fabrice Bellard\n"
3021            "usage: dyngen [-o outfile] [-c] objfile\n"
3022            "Generate a dynamic code generator from an object file\n"
3023            "-c     output enum of operations\n"
3024            "-g     output gen_op_xx() functions\n"
3025            );
3026     exit(1);
3027 }
3028
3029 int main(int argc, char **argv)
3030 {
3031     int c, out_type;
3032     const char *filename, *outfilename;
3033     FILE *outfile;
3034
3035     outfilename = "out.c";
3036     out_type = OUT_CODE;
3037     for(;;) {
3038         c = getopt(argc, argv, "ho:cg");
3039         if (c == -1)
3040             break;
3041         switch(c) {
3042         case 'h':
3043             usage();
3044             break;
3045         case 'o':
3046             outfilename = optarg;
3047             break;
3048         case 'c':
3049             out_type = OUT_INDEX_OP;
3050             break;
3051         case 'g':
3052             out_type = OUT_GEN_OP;
3053             break;
3054         }
3055     }
3056     if (optind >= argc)
3057         usage();
3058     filename = argv[optind];
3059     outfile = fopen(outfilename, "w");
3060     if (!outfile)
3061         error("could not open '%s'", outfilename);
3062
3063     load_object(filename);
3064     gen_file(outfile, out_type);
3065     fclose(outfile);
3066     return 0;
3067 }
This page took 0.189568 seconds and 4 git commands to generate.