File:  [Qemu by Fabrice Bellard] / qemu / dyngen.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:45:12 2018 UTC (23 months, 2 weeks ago) by root
Branches: qemu, MAIN
CVS tags: qemu0090, HEAD
qemu 0.9.0

    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: }

unix.superglobalmegacorp.com