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