VirtualBox

root/trunk/src/recompiler/dyngen.c

Revision 11982, 101.1 kB (checked in by vboxsync, 4 months ago)

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

  • Property svn:eol-style set to native
Line 
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
26 /*
27  * Sun GPL Disclaimer: For the avoidance of doubt, except that if any license choice
28  * other than GPL or LGPL is available it will apply instead, Sun elects to use only
29  * the General Public License version 2 (GPLv2) at this time for any software where
30  * a choice of GPL license versions is made available with the language indicating
31  * that GPLv2 or any later version may be used, or where a choice of which version
32  * of the GPL is applied is otherwise unspecified.
33  */
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdarg.h>
38 #include <inttypes.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41
42 #include "config-host.h"
43
44 /* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
45    compilation */
46 #if defined(CONFIG_WIN32)
47 #define CONFIG_FORMAT_COFF
48 #elif defined(CONFIG_DARWIN)
49 #define CONFIG_FORMAT_MACH
50 #elif defined(CONFIG_OS2)
51 #define CONFIG_FORMAT_AOUT
52 #else
53 #define CONFIG_FORMAT_ELF
54 #endif
55
56 #ifdef CONFIG_FORMAT_ELF
57
58 /* elf format definitions. We use these macros to test the CPU to
59    allow cross compilation (this tool must be ran on the build
60    platform) */
61 #if defined(HOST_I386)
62
63 #define ELF_CLASS       ELFCLASS32
64 #define ELF_ARCH        EM_386
65 #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
66 #undef ELF_USES_RELOCA
67
68 #elif defined(HOST_X86_64)
69
70 #define ELF_CLASS       ELFCLASS64
71 #define ELF_ARCH        EM_X86_64
72 #define elf_check_arch(x) ((x) == EM_X86_64)
73 #define ELF_USES_RELOCA
74
75 #elif defined(HOST_PPC)
76
77 #define ELF_CLASS       ELFCLASS32
78 #define ELF_ARCH        EM_PPC
79 #define elf_check_arch(x) ((x) == EM_PPC)
80 #define ELF_USES_RELOCA
81
82 #elif defined(HOST_S390)
83
84 #define ELF_CLASS       ELFCLASS32
85 #define ELF_ARCH        EM_S390
86 #define elf_check_arch(x) ((x) == EM_S390)
87 #define ELF_USES_RELOCA
88
89 #elif defined(HOST_ALPHA)
90
91 #define ELF_CLASS       ELFCLASS64
92 #define ELF_ARCH        EM_ALPHA
93 #define elf_check_arch(x) ((x) == EM_ALPHA)
94 #define ELF_USES_RELOCA
95
96 #elif defined(HOST_IA64)
97
98 #define ELF_CLASS       ELFCLASS64
99 #define ELF_ARCH        EM_IA_64
100 #define elf_check_arch(x) ((x) == EM_IA_64)
101 #define ELF_USES_RELOCA
102
103 #elif defined(HOST_SPARC)
104
105 #define ELF_CLASS       ELFCLASS32
106 #define ELF_ARCH        EM_SPARC
107 #define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
108 #define ELF_USES_RELOCA
109
110 #elif defined(HOST_SPARC64)
111
112 #define ELF_CLASS       ELFCLASS64
113 #define ELF_ARCH        EM_SPARCV9
114 #define elf_check_arch(x) ((x) == EM_SPARCV9)
115 #define ELF_USES_RELOCA
116
117 #elif defined(HOST_ARM)
118
119 #define ELF_CLASS       ELFCLASS32
120 #define ELF_ARCH        EM_ARM
121 #define elf_check_arch(x) ((x) == EM_ARM)
122 #define ELF_USES_RELOC
123
124 #elif defined(HOST_M68K)
125
126 #define ELF_CLASS       ELFCLASS32
127 #define ELF_ARCH        EM_68K
128 #define elf_check_arch(x) ((x) == EM_68K)
129 #define ELF_USES_RELOCA
130
131 #else
132 #error unsupported CPU - please update the code
133 #endif
134
135 #include "elf.h"
136
137 #if ELF_CLASS == ELFCLASS32
138 typedef int32_t host_long;
139 typedef uint32_t host_ulong;
140 #define swabls(x) swab32s(x)
141 #define swablss(x) swab32ss(x)
142 #else
143 typedef int64_t host_long;
144 typedef uint64_t host_ulong;
145 #define swabls(x) swab64s(x)
146 #define swablss(x) swab64ss(x)
147 #endif
148
149 #ifdef ELF_USES_RELOCA
150 #define SHT_RELOC SHT_RELA
151 #else
152 #define SHT_RELOC SHT_REL
153 #endif
154
155 #define EXE_RELOC ELF_RELOC
156 #define EXE_SYM ElfW(Sym)
157
158 #endif /* CONFIG_FORMAT_ELF */
159
160 #ifdef CONFIG_FORMAT_COFF
161
162 #include "a.out.h"
163
164 typedef int32_t host_long;
165 typedef uint32_t host_ulong;
166
167 #define FILENAMELEN 256
168
169 typedef struct coff_sym {
170     struct external_syment *st_syment;
171     char st_name[FILENAMELEN];
172     uint32_t st_value;
173     int  st_size;
174     uint8_t st_type;
175     uint8_t st_shndx;
176 } coff_Sym;
177
178 typedef struct coff_rel {
179     struct external_reloc *r_reloc;
180     int  r_offset;
181     uint8_t r_type;
182 } coff_Rel;
183
184 #define EXE_RELOC struct coff_rel
185 #define EXE_SYM struct coff_sym
186
187 #endif /* CONFIG_FORMAT_COFF */
188
189 #ifdef CONFIG_FORMAT_MACH
190
191 #include <mach-o/loader.h>
192 #include <mach-o/nlist.h>
193 #include <mach-o/reloc.h>
194 #if !defined(HOST_I386)
195 #include <mach-o/ppc/reloc.h>
196 #endif
197
198 # define check_mach_header(x) (x.magic == MH_MAGIC)
199 typedef int32_t host_long;
200 typedef uint32_t host_ulong;
201
202 struct nlist_extended
203 {
204    union {
205    char *n_name;
206    long  n_strx;
207    } n_un;
208    unsigned char n_type;
209    unsigned char n_sect;
210    short st_desc;
211    unsigned long st_value;
212    unsigned long st_size;
213 };
214
215 #define EXE_RELOC struct relocation_info
216 #define EXE_SYM struct nlist_extended
217 #if defined(HOST_I386)
218 # define r_offset r_address
219 #endif
220
221 #endif /* CONFIG_FORMAT_MACH */
222
223 #ifdef CONFIG_FORMAT_AOUT
224
225 #include "a_out.h"
226
227 typedef int32_t host_long;
228 typedef uint32_t host_ulong;
229
230 struct nlist_extended
231 {
232     union {
233       char *n_name;
234       struct nlist *n_next;
235       long n_strx;
236     } n_un;
237     unsigned char n_type;
238     char n_other;
239     short n_desc;
240     unsigned long st_value; /* n_value -> st_value */
241     unsigned long st_size;  /* added */
242 };
243
244 #define EXE_RELOC struct relocation_info
245 #define EXE_SYM struct nlist_extended
246 #define r_offset r_address
247
248 #endif /* CONFIG_FORMAT_AOUT */
249
250 #include "bswap.h"
251
252 enum {
253     OUT_GEN_OP,
254     OUT_CODE,
255     OUT_INDEX_OP
256 };
257
258 /* all dynamically generated functions begin with this code */
259 #define OP_PREFIX "op_"
260
261 int do_swap;
262
263 void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
264 {
265     va_list ap;
266     va_start(ap, fmt);
267     fprintf(stderr, "dyngen: ");
268     vfprintf(stderr, fmt, ap);
269     fprintf(stderr, "\n");
270     va_end(ap);
271     exit(1);
272 }
273
274 void *load_data(int fd, long offset, unsigned int size)
275 {
276     char *data;
277
278     data = malloc(size);
279     if (!data)
280         return NULL;
281     lseek(fd, offset, SEEK_SET);
282     if (read(fd, data, size) != size) {
283         free(data);
284         return NULL;
285     }
286     return data;
287 }
288
289 int strstart(const char *str, const char *val, const char **ptr)
290 {
291     const char *p, *q;
292     p = str;
293     q = val;
294     while (*q != '\0') {
295         if (*p != *q)
296             return 0;
297         p++;
298         q++;
299     }
300     if (ptr)
301         *ptr = p;
302     return 1;
303 }
304
305 void pstrcpy(char *buf, int buf_size, const char *str)
306 {
307     int c;
308     char *q = buf;
309
310     if (buf_size <= 0)
311         return;
312
313     for(;;) {
314         c = *str++;
315         if (c == 0 || q >= buf + buf_size - 1)
316             break;
317         *q++ = c;
318     }
319     *q = '\0';
320 }
321
322 void swab16s(uint16_t *p)
323 {
324     *p = bswap16(*p);
325 }
326
327 void swab32s(uint32_t *p)
328 {
329     *p = bswap32(*p);
330 }
331
332 void swab32ss(int32_t *p)
333 {
334     *p = bswap32(*p);
335 }
336
337 void swab64s(uint64_t *p)
338 {
339     *p = bswap64(*p);
340 }
341
342 void swab64ss(int64_t *p)
343 {
344     *p = bswap64(*p);
345 }
346
347 uint16_t get16(uint16_t *p)
348 {
349     uint16_t val;
350     val = *p;
351     if (do_swap)
352         val = bswap16(val);
353     return val;
354 }
355
356 uint32_t get32(uint32_t *p)
357 {
358     uint32_t val;
359     val = *p;
360     if (do_swap)
361         val = bswap32(val);
362     return val;
363 }
364
365 void put16(uint16_t *p, uint16_t val)
366 {
367     if (do_swap)
368         val = bswap16(val);
369     *p = val;
370 }
371
372 void put32(uint32_t *p, uint32_t val)
373 {
374     if (do_swap)
375         val = bswap32(val);
376     *p = val;
377 }
378
379 /* executable information */
380 EXE_SYM *symtab;
381 int nb_syms;
382 int text_shndx;
383 uint8_t *text;
384 EXE_RELOC *relocs;
385 int nb_relocs;
386
387 #ifdef CONFIG_FORMAT_ELF
388
389 /* ELF file info */
390 struct elf_shdr *shdr;
391 uint8_t **sdata;
392 struct elfhdr ehdr;
393 char *strtab;
394
395 int elf_must_swap(struct elfhdr *h)
396 {
397   union {
398       uint32_t i;
399       uint8_t b[4];
400   } swaptest;
401
402   swaptest.i = 1;
403   return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
404       (swaptest.b[0] == 0);
405 }
406  
407 void elf_swap_ehdr(struct elfhdr *h)
408 {
409     swab16s(&h->e_type);                        /* Object file type */
410     swab16s(&h->        e_machine);             /* Architecture */
411     swab32s(&h->        e_version);             /* Object file version */
412     swabls(&h-> e_entry);               /* Entry point virtual address */
413     swabls(&h-> e_phoff);               /* Program header table file offset */
414     swabls(&h-> e_shoff);               /* Section header table file offset */
415     swab32s(&h->        e_flags);               /* Processor-specific flags */
416     swab16s(&h->        e_ehsize);              /* ELF header size in bytes */
417     swab16s(&h->        e_phentsize);           /* Program header table entry size */
418     swab16s(&h->        e_phnum);               /* Program header table entry count */
419     swab16s(&h->        e_shentsize);           /* Section header table entry size */
420     swab16s(&h->        e_shnum);               /* Section header table entry count */
421     swab16s(&h->        e_shstrndx);            /* Section header string table index */
422 }
423
424 void elf_swap_shdr(struct elf_shdr *h)
425 {
426   swab32s(&h->  sh_name);               /* Section name (string tbl index) */
427   swab32s(&h->  sh_type);               /* Section type */
428   swabls(&h->   sh_flags);              /* Section flags */
429   swabls(&h->   sh_addr);               /* Section virtual addr at execution */
430   swabls(&h->   sh_offset);             /* Section file offset */
431   swabls(&h->   sh_size);               /* Section size in bytes */
432   swab32s(&h->  sh_link);               /* Link to another section */
433   swab32s(&h->  sh_info);               /* Additional section information */
434   swabls(&h->   sh_addralign);          /* Section alignment */
435   swabls(&h->   sh_entsize);            /* Entry size if section holds table */
436 }
437
438 void elf_swap_phdr(struct elf_phdr *h)
439 {
440     swab32s(&h->p_type);                        /* Segment type */
441     swabls(&h->p_offset);               /* Segment file offset */
442     swabls(&h->p_vaddr);                /* Segment virtual address */
443     swabls(&h->p_paddr);                /* Segment physical address */
444     swabls(&h->p_filesz);               /* Segment size in file */
445     swabls(&h->p_memsz);                /* Segment size in memory */
446     swab32s(&h->p_flags);               /* Segment flags */
447     swabls(&h->p_align);                /* Segment alignment */
448 }
449
450 void elf_swap_rel(ELF_RELOC *rel)
451 {
452     swabls(&rel->r_offset);
453     swabls(&rel->r_info);
454 #ifdef ELF_USES_RELOCA
455     swablss(&rel->r_addend);
456 #endif
457 }
458
459 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
460                                   const char *name)
461 {
462     int i;
463     const char *shname;
464     struct elf_shdr *sec;
465
466     for(i = 0; i < shnum; i++) {
467         sec = &shdr[i];
468         if (!sec->sh_name)
469             continue;
470         shname = shstr + sec->sh_name;
471         if (!strcmp(shname, name))
472             return sec;
473     }
474     return NULL;
475 }
476
477 int find_reloc(int sh_index)
478 {
479     struct elf_shdr *sec;
480     int i;
481
482     for(i = 0; i < ehdr.e_shnum; i++) {
483         sec = &shdr[i];
484         if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
485             return i;
486     }
487     return 0;
488 }
489
490 static host_ulong get_rel_offset(EXE_RELOC *rel)
491 {
492     return rel->r_offset;
493 }
494
495 static char *get_rel_sym_name(EXE_RELOC *rel)
496 {
497     return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
498 }
499
500 static char *get_sym_name(EXE_SYM *sym)
501 {
502     return strtab + sym->st_name;
503 }
504
505 /* load an elf object file */
506 int load_object(const char *filename)
507 {
508     int fd;
509     struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
510     int i, j;
511     ElfW(Sym) *sym;
512     char *shstr;
513     ELF_RELOC *rel;
514    
515     fd = open(filename, O_RDONLY
516 #ifdef O_BINARY
517               | O_BINARY
518 #endif
519               );
520     if (fd < 0)
521         error("can't open file '%s'", filename);
522    
523     /* Read ELF header.  */
524     if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
525         error("unable to read file header");
526
527     /* Check ELF identification.  */
528     if (ehdr.e_ident[EI_MAG0] != ELFMAG0
529      || ehdr.e_ident[EI_MAG1] != ELFMAG1
530      || ehdr.e_ident[EI_MAG2] != ELFMAG2
531      || ehdr.e_ident[EI_MAG3] != ELFMAG3
532      || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
533         error("bad ELF header");
534     }
535
536     do_swap = elf_must_swap(&ehdr);
537     if (do_swap)
538         elf_swap_ehdr(&ehdr);
539     if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
540         error("Unsupported ELF class (%#x)", ehdr.e_ident[EI_CLASS]);
541     if (ehdr.e_type != ET_REL)
542         error("ELF object file expected");
543     if (ehdr.e_version != EV_CURRENT)
544         error("Invalid ELF version");
545     if (!elf_check_arch(ehdr.e_machine))
546         error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
547
548     /* read section headers */
549     shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
550     if (do_swap) {
551         for(i = 0; i < ehdr.e_shnum; i++) {
552             elf_swap_shdr(&shdr[i]);
553         }
554     }
555
556     /* read all section data */
557     sdata = malloc(sizeof(void *) * ehdr.e_shnum);
558     memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
559    
560     for(i = 0;i < ehdr.e_shnum; i++) {
561         sec = &shdr[i];
562         if (sec->sh_type != SHT_NOBITS)
563             sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
564     }
565
566     sec = &shdr[ehdr.e_shstrndx];
567     shstr = (char *)sdata[ehdr.e_shstrndx];
568
569     /* swap relocations */
570     for(i = 0; i < ehdr.e_shnum; i++) {
571         sec = &shdr[i];
572         if (sec->sh_type == SHT_RELOC) {
573             nb_relocs = sec->sh_size / sec->sh_entsize;
574             if (do_swap) {
575                 for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
576                     elf_swap_rel(rel);
577             }
578         }
579     }
580     /* text section */
581
582     text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
583     if (!text_sec)
584         error("could not find .text section");
585     text_shndx = text_sec - shdr;
586     text = sdata[text_shndx];
587
588     /* find text relocations, if any */
589     relocs = NULL;
590     nb_relocs = 0;
591     i = find_reloc(text_shndx);
592     if (i != 0) {
593         relocs = (ELF_RELOC *)sdata[i];
594         nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
595     }
596
597     symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
598     if (!symtab_sec)
599         error("could not find .symtab section");
600     strtab_sec = &shdr[symtab_sec->sh_link];
601
602     symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
603     strtab = (char *)sdata[symtab_sec->sh_link];
604    
605     nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
606     if (do_swap) {
607         for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
608             swab32s(&sym->st_name);
609             swabls(&sym->st_value);
610             swabls(&sym->st_size);
611             swab16s(&sym->st_shndx);
612         }
613     }
614     close(fd);
615     return 0;
616 }
617
618 #endif /* CONFIG_FORMAT_ELF */
619
620 #ifdef CONFIG_FORMAT_COFF
621
622 /* COFF file info */
623 struct external_scnhdr *shdr;
624 uint8_t **sdata;
625 struct external_filehdr fhdr;
626 struct external_syment *coff_symtab;
627 char *strtab;
628 int coff_text_shndx, coff_data_shndx;
629
630 int data_shndx;
631
632 #define STRTAB_SIZE 4
633
634 #define DIR32   0x06
635 #define DISP32  0x14
636
637 #define T_FUNCTION  0x20
638 #define C_EXTERNAL  2
639
640 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
641 {
642     char *q;
643     int c, i, len;
644    
645     if (ext_sym->e.e.e_zeroes != 0) {
646         q = sym->st_name;
647         for(i = 0; i < 8; i++) {
648             c = ext_sym->e.e_name[i];
649             if (c == '\0')
650                 break;
651             *q++ = c;
652         }
653         *q = '\0';
654     } else {
655         pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
656     }
657
658     /* now convert the name to a C name (suppress the leading '_') */
659     if (sym->st_name[0] == '_') {
660         len = strlen(sym->st_name);
661         memmove(sym->st_name, sym->st_name + 1, len - 1);
662         sym->st_name[len - 1] = '\0';
663     }
664 }
665
666 char *name_for_dotdata(struct coff_rel *rel)
667 {
668         int i;
669         struct coff_sym *sym;
670         uint32_t text_data;
671
672         text_data = *(uint32_t *)(text + rel->r_offset);
673
674         for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
675                 if (sym->st_syment->e_scnum == data_shndx &&
676                     text_data >= sym->st_value &&
677                     text_data < sym->st_value + sym->st_size) {
678                    
679                     return sym->st_name;
680
681                 }
682         }
683         return NULL;
684 }
685
686 static char *get_sym_name(EXE_SYM *sym)
687 {
688     return sym->st_name;
689 }
690
691 static char *get_rel_sym_name(EXE_RELOC *rel)
692 {
693     char *name;
694     name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
695     if (!strcmp(name, ".data"))
696         name = name_for_dotdata(rel);
697     if (name[0] == '.')
698         return NULL;
699     return name;
700 }
701
702 static host_ulong get_rel_offset(EXE_RELOC *rel)
703 {
704     return rel->r_offset;
705 }
706
707 struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
708 {
709     int i;
710     const char *shname;
711     struct external_scnhdr *sec;
712
713     for(i = 0; i < shnum; i++) {
714         sec = &shdr[i];
715         if (!sec->s_name)
716             continue;
717         shname = sec->s_name;
718         if (!strcmp(shname, name))
719             return sec;
720     }
721     return NULL;
722 }
723
724 /* load a coff object file */
725 int load_object(const char *filename)
726 {
727     int fd;
728     struct external_scnhdr *sec, *text_sec, *data_sec;
729     int i;
730     struct external_syment *ext_sym;
731     struct external_reloc *coff_relocs;
732     struct external_reloc *ext_rel;
733     uint32_t *n_strtab;
734     EXE_SYM *sym;
735     EXE_RELOC *rel;
736        
737     fd = open(filename, O_RDONLY
738 #ifdef O_BINARY
739               | O_BINARY
740 #endif
741               );
742     if (fd < 0)
743         error("can't open file '%s'", filename);
744    
745     /* Read COFF header.  */
746     if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
747         error("unable to read file header");
748
749     /* Check COFF identification.  */
750     if (fhdr.f_magic != I386MAGIC) {
751         error("bad COFF header");
752     }
753     do_swap = 0;
754
755     /* read section headers */
756     shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
757        
758     /* read all section data */
759     sdata = malloc(sizeof(void *) * fhdr.f_nscns);
760     memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
761    
762     const char *p;
763     for(i = 0;i < fhdr.f_nscns; i++) {
764         sec = &shdr[i];
765         if (!strstart(sec->s_name,  ".bss", &p))
766             sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
767     }
768
769
770     /* text section */
771     text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
772     if (!text_sec)
773         error("could not find .text section");
774     coff_text_shndx = text_sec - shdr;
775     text = sdata[coff_text_shndx];
776
777     /* data section */
778     data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
779     if (!data_sec)
780         error("could not find .data section");
781     coff_data_shndx = data_sec - shdr;
782    
783     coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
784     for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
785         for(i=0;i<8;i++)
786             printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
787         printf("\n");
788     }
789
790
791     n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
792     strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
793    
794     nb_syms = fhdr.f_nsyms;
795
796     for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
797       if (strstart(ext_sym->e.e_name, ".text", NULL))
798                   text_shndx = ext_sym->e_scnum;
799           if (strstart(ext_sym->e.e_name, ".data", NULL))
800                   data_shndx = ext_sym->e_scnum;
801     }
802
803         /* set coff symbol */
804         symtab = malloc(sizeof(struct coff_sym) * nb_syms);
805
806         int aux_size, j;
807         for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
808                 memset(sym, 0, sizeof(*sym));
809                 sym->st_syment = ext_sym;
810                 sym_ent_name(ext_sym, sym);
811                 sym->st_value = ext_sym->e_value;
812
813                 aux_size = *(int8_t *)ext_sym->e_numaux;
814                 if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
815                         for (j = aux_size + 1; j < nb_syms - i; j++) {
816                                 if ((ext_sym + j)->e_scnum == text_shndx &&
817                                         (ext_sym + j)->e_type == T_FUNCTION ){
818                                         sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
819                                         break;
820                                 } else if (j == nb_syms - i - 1) {
821                                         sec = &shdr[coff_text_shndx];
822                                         sym->st_size = sec->s_size - ext_sym->e_value;
823                                         break;
824                                 }
825                         }
826                 } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
827                         for (j = aux_size + 1; j < nb_syms - i; j++) {
828                                 if ((ext_sym + j)->e_scnum == data_shndx) {
829                                         sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
830                                         break;
831                                 } else if (j == nb_syms - i - 1) {
832                                         sec = &shdr[coff_data_shndx];
833                                         sym->st_size = sec->s_size - ext_sym->e_value;
834                                         break;
835                                 }
836                         }
837                 } else {
838                         sym->st_size = 0;
839                 }
840                
841                 sym->st_type = ext_sym->e_type;
842                 sym->st_shndx = ext_sym->e_scnum;
843         }
844
845                
846     /* find text relocations, if any */
847     sec = &shdr[coff_text_shndx];
848     coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
849     nb_relocs = sec->s_nreloc;
850
851     /* set coff relocation */
852     relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
853     for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
854          i++, ext_rel++, rel++) {
855         memset(rel, 0, sizeof(*rel));
856         rel->r_reloc = ext_rel;
857         rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
858         rel->r_type = *(uint16_t *)ext_rel->r_type;
859     }
860     return 0;
861 }
862
863 #endif /* CONFIG_FORMAT_COFF */
864
865 #ifdef CONFIG_FORMAT_MACH
866
867 /* File Header */
868 struct mach_header      mach_hdr;
869
870 /* commands */
871 struct segment_command  *segment = 0;
872 struct dysymtab_command *dysymtabcmd = 0;
873 struct symtab_command   *symtabcmd = 0;
874
875 /* section */
876 struct section  *section_hdr;
877 struct section *text_sec_hdr;
878 uint8_t         **sdata;
879
880 /* relocs */
881 struct relocation_info *relocs;
882        
883 /* symbols */
884 EXE_SYM                 *symtab;
885 struct nlist    *symtab_std;
886 char                    *strtab;
887
888 /* indirect symbols */
889 uint32_t        *tocdylib;
890
891 /* Utility functions */
892
893 static inline char *find_str_by_index(int index)
894 {
895     return strtab+index;
896 }
897
898 /* Used by dyngen common code */
899 static char *get_sym_name(EXE_SYM *sym)
900 {
901         char *name = find_str_by_index(sym->n_un.n_strx);
902        
903         if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
904                 return "debug";
905                        
906         if(!name)
907                 return name;
908         if(name[0]=='_')
909                 return name + 1;
910         else
911                 return name;
912 }
913
914 /* find a section index given its segname, sectname */
915 static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
916                                   const char *sectname)
917 {
918     int i;
919     struct section *sec = section_hdr;
920
921     for(i = 0; i < shnum; i++, sec++) {
922         if (!sec->segname || !sec->sectname)
923             continue;
924         if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
925             return i;
926     }
927     return -1;
928 }
929
930 /* find a section header given its segname, sectname */
931 struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
932                                   const char *sectname)
933 {
934     int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
935         if(index == -1)
936                 return NULL;
937         return section_hdr+index;
938 }
939
940