Statistics
| Branch: | Revision:

root / dyngen.c @ 67b915a5

History | View | Annotate | Download (59.5 kB)

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
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  (at your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program; if not, write to the Free Software
21
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
 */
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <stdarg.h>
27
#include <inttypes.h>
28
#include <unistd.h>
29
#include <fcntl.h>
30

    
31
#include "config-host.h"
32

    
33
#if defined(_WIN32)
34
#define CONFIG_FORMAT_COFF
35
#else
36
#define CONFIG_FORMAT_ELF
37
#endif
38

    
39
#ifdef CONFIG_FORMAT_ELF
40

    
41
/* elf format definitions. We use these macros to test the CPU to
42
   allow cross compilation (this tool must be ran on the build
43
   platform) */
44
#if defined(HOST_I386)
45

    
46
#define ELF_CLASS        ELFCLASS32
47
#define ELF_ARCH        EM_386
48
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
49
#undef ELF_USES_RELOCA
50

    
51
#elif defined(HOST_AMD64)
52

    
53
#define ELF_CLASS        ELFCLASS64
54
#define ELF_ARCH        EM_X86_64
55
#define elf_check_arch(x) ((x) == EM_X86_64)
56
#define ELF_USES_RELOCA
57

    
58
#elif defined(HOST_PPC)
59

    
60
#define ELF_CLASS        ELFCLASS32
61
#define ELF_ARCH        EM_PPC
62
#define elf_check_arch(x) ((x) == EM_PPC)
63
#define ELF_USES_RELOCA
64

    
65
#elif defined(HOST_S390)
66

    
67
#define ELF_CLASS        ELFCLASS32
68
#define ELF_ARCH        EM_S390
69
#define elf_check_arch(x) ((x) == EM_S390)
70
#define ELF_USES_RELOCA
71

    
72
#elif defined(HOST_ALPHA)
73

    
74
#define ELF_CLASS        ELFCLASS64
75
#define ELF_ARCH        EM_ALPHA
76
#define elf_check_arch(x) ((x) == EM_ALPHA)
77
#define ELF_USES_RELOCA
78

    
79
#elif defined(HOST_IA64)
80

    
81
#define ELF_CLASS        ELFCLASS64
82
#define ELF_ARCH        EM_IA_64
83
#define elf_check_arch(x) ((x) == EM_IA_64)
84
#define ELF_USES_RELOCA
85

    
86
#elif defined(HOST_SPARC)
87

    
88
#define ELF_CLASS        ELFCLASS32
89
#define ELF_ARCH        EM_SPARC
90
#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
91
#define ELF_USES_RELOCA
92

    
93
#elif defined(HOST_SPARC64)
94

    
95
#define ELF_CLASS        ELFCLASS64
96
#define ELF_ARCH        EM_SPARCV9
97
#define elf_check_arch(x) ((x) == EM_SPARCV9)
98
#define ELF_USES_RELOCA
99

    
100
#elif defined(HOST_ARM)
101

    
102
#define ELF_CLASS        ELFCLASS32
103
#define ELF_ARCH        EM_ARM
104
#define elf_check_arch(x) ((x) == EM_ARM)
105
#define ELF_USES_RELOC
106

    
107
#elif defined(HOST_M68K)
108

    
109
#define ELF_CLASS        ELFCLASS32
110
#define ELF_ARCH        EM_68K
111
#define elf_check_arch(x) ((x) == EM_68K)
112
#define ELF_USES_RELOCA
113

    
114
#else
115
#error unsupported CPU - please update the code
116
#endif
117

    
118
#include "elf.h"
119

    
120
#if ELF_CLASS == ELFCLASS32
121
typedef int32_t host_long;
122
typedef uint32_t host_ulong;
123
#define swabls(x) swab32s(x)
124
#else
125
typedef int64_t host_long;
126
typedef uint64_t host_ulong;
127
#define swabls(x) swab64s(x)
128
#endif
129

    
130
#ifdef ELF_USES_RELOCA
131
#define SHT_RELOC SHT_RELA
132
#else
133
#define SHT_RELOC SHT_REL
134
#endif
135

    
136
#define EXE_RELOC ELF_RELOC
137
#define EXE_SYM ElfW(Sym)
138

    
139
#endif /* CONFIG_FORMAT_ELF */
140

    
141
#ifdef CONFIG_FORMAT_COFF
142

    
143
#include "a.out.h"
144

    
145
typedef int32_t host_long;
146
typedef uint32_t host_ulong;
147

    
148
#define FILENAMELEN 256
149

    
150
typedef struct coff_sym {
151
    struct external_syment *st_syment;
152
    char st_name[FILENAMELEN];
153
    uint32_t st_value;
154
    int  st_size;
155
    uint8_t st_type;
156
    uint8_t st_shndx;
157
} coff_Sym;
158

    
159
typedef struct coff_rel {
160
    struct external_reloc *r_reloc;
161
    int  r_offset;
162
    uint8_t r_type;
163
} coff_Rel;
164

    
165
#define EXE_RELOC struct coff_rel
166
#define EXE_SYM struct coff_sym
167

    
168
#endif /* CONFIG_FORMAT_COFF */
169

    
170
#include "bswap.h"
171

    
172
enum {
173
    OUT_GEN_OP,
174
    OUT_CODE,
175
    OUT_INDEX_OP,
176
};
177

    
178
/* all dynamically generated functions begin with this code */
179
#define OP_PREFIX "op_"
180

    
181
int do_swap;
182

    
183
void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
184
{
185
    va_list ap;
186
    va_start(ap, fmt);
187
    fprintf(stderr, "dyngen: ");
188
    vfprintf(stderr, fmt, ap);
189
    fprintf(stderr, "\n");
190
    va_end(ap);
191
    exit(1);
192
}
193

    
194
void *load_data(int fd, long offset, unsigned int size)
195
{
196
    char *data;
197

    
198
    data = malloc(size);
199
    if (!data)
200
        return NULL;
201
    lseek(fd, offset, SEEK_SET);
202
    if (read(fd, data, size) != size) {
203
        free(data);
204
        return NULL;
205
    }
206
    return data;
207
}
208

    
209
int strstart(const char *str, const char *val, const char **ptr)
210
{
211
    const char *p, *q;
212
    p = str;
213
    q = val;
214
    while (*q != '\0') {
215
        if (*p != *q)
216
            return 0;
217
        p++;
218
        q++;
219
    }
220
    if (ptr)
221
        *ptr = p;
222
    return 1;
223
}
224

    
225
void pstrcpy(char *buf, int buf_size, const char *str)
226
{
227
    int c;
228
    char *q = buf;
229

    
230
    if (buf_size <= 0)
231
        return;
232

    
233
    for(;;) {
234
        c = *str++;
235
        if (c == 0 || q >= buf + buf_size - 1)
236
            break;
237
        *q++ = c;
238
    }
239
    *q = '\0';
240
}
241

    
242
void swab16s(uint16_t *p)
243
{
244
    *p = bswap16(*p);
245
}
246

    
247
void swab32s(uint32_t *p)
248
{
249
    *p = bswap32(*p);
250
}
251

    
252
void swab64s(uint64_t *p)
253
{
254
    *p = bswap64(*p);
255
}
256

    
257
uint16_t get16(uint16_t *p)
258
{
259
    uint16_t val;
260
    val = *p;
261
    if (do_swap)
262
        val = bswap16(val);
263
    return val;
264
}
265

    
266
uint32_t get32(uint32_t *p)
267
{
268
    uint32_t val;
269
    val = *p;
270
    if (do_swap)
271
        val = bswap32(val);
272
    return val;
273
}
274

    
275
void put16(uint16_t *p, uint16_t val)
276
{
277
    if (do_swap)
278
        val = bswap16(val);
279
    *p = val;
280
}
281

    
282
void put32(uint32_t *p, uint32_t val)
283
{
284
    if (do_swap)
285
        val = bswap32(val);
286
    *p = val;
287
}
288

    
289
/* executable information */
290
EXE_SYM *symtab;
291
int nb_syms;
292
int text_shndx;
293
uint8_t *text;
294
EXE_RELOC *relocs;
295
int nb_relocs;
296

    
297
#ifdef CONFIG_FORMAT_ELF
298

    
299
/* ELF file info */
300
struct elf_shdr *shdr;
301
uint8_t **sdata;
302
struct elfhdr ehdr;
303
char *strtab;
304

    
305
int elf_must_swap(struct elfhdr *h)
306
{
307
  union {
308
      uint32_t i;
309
      uint8_t b[4];
310
  } swaptest;
311

    
312
  swaptest.i = 1;
313
  return (h->e_ident[EI_DATA] == ELFDATA2MSB) != 
314
      (swaptest.b[0] == 0);
315
}
316
  
317
void elf_swap_ehdr(struct elfhdr *h)
318
{
319
    swab16s(&h->e_type);                        /* Object file type */
320
    swab16s(&h->        e_machine);                /* Architecture */
321
    swab32s(&h->        e_version);                /* Object file version */
322
    swabls(&h->        e_entry);                /* Entry point virtual address */
323
    swabls(&h->        e_phoff);                /* Program header table file offset */
324
    swabls(&h->        e_shoff);                /* Section header table file offset */
325
    swab32s(&h->        e_flags);                /* Processor-specific flags */
326
    swab16s(&h->        e_ehsize);                /* ELF header size in bytes */
327
    swab16s(&h->        e_phentsize);                /* Program header table entry size */
328
    swab16s(&h->        e_phnum);                /* Program header table entry count */
329
    swab16s(&h->        e_shentsize);                /* Section header table entry size */
330
    swab16s(&h->        e_shnum);                /* Section header table entry count */
331
    swab16s(&h->        e_shstrndx);                /* Section header string table index */
332
}
333

    
334
void elf_swap_shdr(struct elf_shdr *h)
335
{
336
  swab32s(&h->        sh_name);                /* Section name (string tbl index) */
337
  swab32s(&h->        sh_type);                /* Section type */
338
  swabls(&h->        sh_flags);                /* Section flags */
339
  swabls(&h->        sh_addr);                /* Section virtual addr at execution */
340
  swabls(&h->        sh_offset);                /* Section file offset */
341
  swabls(&h->        sh_size);                /* Section size in bytes */
342
  swab32s(&h->        sh_link);                /* Link to another section */
343
  swab32s(&h->        sh_info);                /* Additional section information */
344
  swabls(&h->        sh_addralign);                /* Section alignment */
345
  swabls(&h->        sh_entsize);                /* Entry size if section holds table */
346
}
347

    
348
void elf_swap_phdr(struct elf_phdr *h)
349
{
350
    swab32s(&h->p_type);                        /* Segment type */
351
    swabls(&h->p_offset);                /* Segment file offset */
352
    swabls(&h->p_vaddr);                /* Segment virtual address */
353
    swabls(&h->p_paddr);                /* Segment physical address */
354
    swabls(&h->p_filesz);                /* Segment size in file */
355
    swabls(&h->p_memsz);                /* Segment size in memory */
356
    swab32s(&h->p_flags);                /* Segment flags */
357
    swabls(&h->p_align);                /* Segment alignment */
358
}
359

    
360
void elf_swap_rel(ELF_RELOC *rel)
361
{
362
    swabls(&rel->r_offset);
363
    swabls(&rel->r_info);
364
#ifdef ELF_USES_RELOCA
365
    swabls(&rel->r_addend);
366
#endif
367
}
368

    
369
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr, 
370
                                  const char *name)
371
{
372
    int i;
373
    const char *shname;
374
    struct elf_shdr *sec;
375

    
376
    for(i = 0; i < shnum; i++) {
377
        sec = &shdr[i];
378
        if (!sec->sh_name)
379
            continue;
380
        shname = shstr + sec->sh_name;
381
        if (!strcmp(shname, name))
382
            return sec;
383
    }
384
    return NULL;
385
}
386

    
387
int find_reloc(int sh_index)
388
{
389
    struct elf_shdr *sec;
390
    int i;
391

    
392
    for(i = 0; i < ehdr.e_shnum; i++) {
393
        sec = &shdr[i];
394
        if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index) 
395
            return i;
396
    }
397
    return 0;
398
}
399

    
400
static char *get_rel_sym_name(EXE_RELOC *rel)
401
{
402
    return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
403
}
404

    
405
static char *get_sym_name(EXE_SYM *sym)
406
{
407
    return strtab + sym->st_name;
408
}
409

    
410
/* load an elf object file */
411
int load_object(const char *filename)
412
{
413
    int fd;
414
    struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
415
    int i, j;
416
    ElfW(Sym) *sym;
417
    char *shstr;
418
    ELF_RELOC *rel;
419
    
420
    fd = open(filename, O_RDONLY);
421
    if (fd < 0) 
422
        error("can't open file '%s'", filename);
423
    
424
    /* Read ELF header.  */
425
    if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
426
        error("unable to read file header");
427

    
428
    /* Check ELF identification.  */
429
    if (ehdr.e_ident[EI_MAG0] != ELFMAG0
430
     || ehdr.e_ident[EI_MAG1] != ELFMAG1
431
     || ehdr.e_ident[EI_MAG2] != ELFMAG2
432
     || ehdr.e_ident[EI_MAG3] != ELFMAG3
433
     || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
434
        error("bad ELF header");
435
    }
436

    
437
    do_swap = elf_must_swap(&ehdr);
438
    if (do_swap)
439
        elf_swap_ehdr(&ehdr);
440
    if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
441
        error("Unsupported ELF class");
442
    if (ehdr.e_type != ET_REL)
443
        error("ELF object file expected");
444
    if (ehdr.e_version != EV_CURRENT)
445
        error("Invalid ELF version");
446
    if (!elf_check_arch(ehdr.e_machine))
447
        error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
448

    
449
    /* read section headers */
450
    shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
451
    if (do_swap) {
452
        for(i = 0; i < ehdr.e_shnum; i++) {
453
            elf_swap_shdr(&shdr[i]);
454
        }
455
    }
456

    
457
    /* read all section data */
458
    sdata = malloc(sizeof(void *) * ehdr.e_shnum);
459
    memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
460
    
461
    for(i = 0;i < ehdr.e_shnum; i++) {
462
        sec = &shdr[i];
463
        if (sec->sh_type != SHT_NOBITS)
464
            sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
465
    }
466

    
467
    sec = &shdr[ehdr.e_shstrndx];
468
    shstr = sdata[ehdr.e_shstrndx];
469

    
470
    /* swap relocations */
471
    for(i = 0; i < ehdr.e_shnum; i++) {
472
        sec = &shdr[i];
473
        if (sec->sh_type == SHT_RELOC) {
474
            nb_relocs = sec->sh_size / sec->sh_entsize;
475
            if (do_swap) {
476
                for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
477
                    elf_swap_rel(rel);
478
            }
479
        }
480
    }
481
    /* text section */
482

    
483
    text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
484
    if (!text_sec)
485
        error("could not find .text section");
486
    text_shndx = text_sec - shdr;
487
    text = sdata[text_shndx];
488

    
489
    /* find text relocations, if any */
490
    relocs = NULL;
491
    nb_relocs = 0;
492
    i = find_reloc(text_shndx);
493
    if (i != 0) {
494
        relocs = (ELF_RELOC *)sdata[i];
495
        nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
496
    }
497

    
498
    symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
499
    if (!symtab_sec)
500
        error("could not find .symtab section");
501
    strtab_sec = &shdr[symtab_sec->sh_link];
502

    
503
    symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
504
    strtab = sdata[symtab_sec->sh_link];
505
    
506
    nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
507
    if (do_swap) {
508
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
509
            swab32s(&sym->st_name);
510
            swabls(&sym->st_value);
511
            swabls(&sym->st_size);
512
            swab16s(&sym->st_shndx);
513
        }
514
    }
515
    close(fd);
516
    return 0;
517
}
518

    
519
#endif /* CONFIG_FORMAT_ELF */
520

    
521
#ifdef CONFIG_FORMAT_COFF
522

    
523
/* COFF file info */
524
struct external_scnhdr *shdr;
525
uint8_t **sdata;
526
struct external_filehdr fhdr;
527
struct external_syment *coff_symtab;
528
char *strtab;
529
int coff_text_shndx, coff_data_shndx;
530

    
531
int data_shndx;
532

    
533
#define STRTAB_SIZE 4
534

    
535
#define DIR32   0x06
536
#define DISP32  0x14
537

    
538
#define T_FUNCTION  0x20
539
#define C_EXTERNAL  2
540

    
541
void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
542
{
543
    char *q;
544
    int c, i, len;
545
    
546
    if (ext_sym->e.e.e_zeroes != 0) {
547
        q = sym->st_name;
548
        for(i = 0; i < 8; i++) {
549
            c = ext_sym->e.e_name[i];
550
            if (c == '\0')
551
                break;
552
            *q++ = c;
553
        }
554
        *q = '\0';
555
    } else {
556
        pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
557
    }
558

    
559
    /* now convert the name to a C name (suppress the leading '_') */
560
    if (sym->st_name[0] == '_') {
561
        len = strlen(sym->st_name);
562
        memmove(sym->st_name, sym->st_name + 1, len - 1);
563
        sym->st_name[len - 1] = '\0';
564
    }
565
}
566

    
567
char *name_for_dotdata(struct coff_rel *rel)
568
{
569
        int i;
570
        struct coff_sym *sym;
571
        uint32_t text_data;
572

    
573
        text_data = *(uint32_t *)(text + rel->r_offset);
574

    
575
        for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
576
                if (sym->st_syment->e_scnum == data_shndx &&
577
                    text_data >= sym->st_value &&
578
                    text_data < sym->st_value + sym->st_size) {
579
                    
580
                    return sym->st_name;
581

    
582
                }
583
        }
584
        return NULL;
585
}
586

    
587
static char *get_sym_name(EXE_SYM *sym)
588
{
589
    return sym->st_name;
590
}
591

    
592
static char *get_rel_sym_name(EXE_RELOC *rel)
593
{
594
    char *name;
595
    name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
596
    if (!strcmp(name, ".data"))
597
        name = name_for_dotdata(rel);
598
    return name;
599
}
600

    
601
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
602
{
603
    int i;
604
    const char *shname;
605
    struct external_scnhdr *sec;
606

    
607
    for(i = 0; i < shnum; i++) {
608
        sec = &shdr[i];
609
        if (!sec->s_name)
610
            continue;
611
        shname = sec->s_name;
612
        if (!strcmp(shname, name))
613
            return sec;
614
    }
615
    return NULL;
616
}
617

    
618
/* load a coff object file */
619
int load_object(const char *filename)
620
{
621
    int fd;
622
    struct external_scnhdr *sec, *text_sec, *data_sec;
623
    int i;
624
    struct external_syment *ext_sym;
625
    struct external_reloc *coff_relocs;
626
    struct external_reloc *ext_rel;
627
    uint32_t *n_strtab;
628
    EXE_SYM *sym;
629
    EXE_RELOC *rel;
630
        
631
    fd = open(filename, O_RDONLY 
632
#ifdef _WIN32
633
              | O_BINARY
634
#endif
635
              );
636
    if (fd < 0) 
637
        error("can't open file '%s'", filename);
638
    
639
    /* Read COFF header.  */
640
    if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
641
        error("unable to read file header");
642

    
643
    /* Check COFF identification.  */
644
    if (fhdr.f_magic != I386MAGIC) {
645
        error("bad COFF header");
646
    }
647
    do_swap = 0;
648

    
649
    /* read section headers */
650
    shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
651
        
652
    /* read all section data */
653
    sdata = malloc(sizeof(void *) * fhdr.f_nscns);
654
    memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
655
    
656
    const char *p;
657
    for(i = 0;i < fhdr.f_nscns; i++) {
658
        sec = &shdr[i];
659
        if (!strstart(sec->s_name,  ".bss", &p))
660
            sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
661
    }
662

    
663

    
664
    /* text section */
665
    text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
666
    if (!text_sec)
667
        error("could not find .text section");
668
    coff_text_shndx = text_sec - shdr;
669
    text = sdata[coff_text_shndx];
670

    
671
    /* data section */
672
    data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
673
    if (!data_sec)
674
        error("could not find .data section");
675
    coff_data_shndx = data_sec - shdr;
676
    
677
    coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
678
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
679
        for(i=0;i<8;i++)
680
            printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
681
        printf("\n");
682
    }
683

    
684

    
685
    n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
686
    strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab); 
687
    
688
    nb_syms = fhdr.f_nsyms;
689

    
690
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
691
      if (strstart(ext_sym->e.e_name, ".text", NULL))
692
                  text_shndx = ext_sym->e_scnum;
693
          if (strstart(ext_sym->e.e_name, ".data", NULL))
694
                  data_shndx = ext_sym->e_scnum;
695
    }
696

    
697
        /* set coff symbol */
698
        symtab = malloc(sizeof(struct coff_sym) * nb_syms);
699

    
700
        int aux_size, j;
701
        for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
702
                memset(sym, 0, sizeof(*sym));
703
                sym->st_syment = ext_sym;
704
                sym_ent_name(ext_sym, sym);
705
                sym->st_value = ext_sym->e_value;
706

    
707
                aux_size = *(int8_t *)ext_sym->e_numaux;
708
                if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
709
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
710
                                if ((ext_sym + j)->e_scnum == text_shndx &&
711
                                        (ext_sym + j)->e_type == T_FUNCTION ){
712
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
713
                                        break;
714
                                } else if (j == nb_syms - i - 1) {
715
                                        sec = &shdr[coff_text_shndx];
716
                                        sym->st_size = sec->s_size - ext_sym->e_value;
717
                                        break;
718
                                }
719
                        }
720
                } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
721
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
722
                                if ((ext_sym + j)->e_scnum == data_shndx) {
723
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
724
                                        break;
725
                                } else if (j == nb_syms - i - 1) {
726
                                        sec = &shdr[coff_data_shndx];
727
                                        sym->st_size = sec->s_size - ext_sym->e_value;
728
                                        break;
729
                                }
730
                        }
731
                } else {
732
                        sym->st_size = 0;
733
                }
734
                
735
                sym->st_type = ext_sym->e_type;
736
                sym->st_shndx = ext_sym->e_scnum;
737
        }
738

    
739
                
740
    /* find text relocations, if any */
741
    sec = &shdr[coff_text_shndx];
742
    coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
743
    nb_relocs = sec->s_nreloc;
744

    
745
    /* set coff relocation */
746
    relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
747
    for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs; 
748
         i++, ext_rel++, rel++) {
749
        memset(rel, 0, sizeof(*rel));
750
        rel->r_reloc = ext_rel;
751
        rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
752
        rel->r_type = *(uint16_t *)ext_rel->r_type;
753
    }
754
    return 0;
755
}
756

    
757
#endif /* CONFIG_FORMAT_COFF */
758

    
759
#ifdef HOST_ARM
760

    
761
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
762
                      FILE *outfile, uint8_t *p_start, uint8_t *p_end,
763
                      ELF_RELOC *relocs, int nb_relocs)
764
{
765
    uint8_t *p;
766
    uint32_t insn;
767
    int offset, min_offset, pc_offset, data_size;
768
    uint8_t data_allocated[1024];
769
    unsigned int data_index;
770
    
771
    memset(data_allocated, 0, sizeof(data_allocated));
772
    
773
    p = p_start;
774
    min_offset = p_end - p_start;
775
    while (p < p_start + min_offset) {
776
        insn = get32((uint32_t *)p);
777
        if ((insn & 0x0d5f0000) == 0x051f0000) {
778
            /* ldr reg, [pc, #im] */
779
            offset = insn & 0xfff;
780
            if (!(insn & 0x00800000))
781
                        offset = -offset;
782
            if ((offset & 3) !=0)
783
                error("%s:%04x: ldr pc offset must be 32 bit aligned", 
784
                      name, start_offset + p - p_start);
785
            pc_offset = p - p_start + offset + 8;
786
            if (pc_offset <= (p - p_start) || 
787
                pc_offset >= (p_end - p_start))
788
                error("%s:%04x: ldr pc offset must point inside the function code", 
789
                      name, start_offset + p - p_start);
790
            if (pc_offset < min_offset)
791
                min_offset = pc_offset;
792
            if (outfile) {
793
                /* ldr position */
794
                fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", 
795
                        p - p_start);
796
                /* ldr data index */
797
                data_index = ((p_end - p_start) - pc_offset - 4) >> 2;
798
                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n", 
799
                        data_index);
800
                fprintf(outfile, "    arm_ldr_ptr++;\n");
801
                if (data_index >= sizeof(data_allocated))
802
                    error("%s: too many data", name);
803
                if (!data_allocated[data_index]) {
804
                    ELF_RELOC *rel;
805
                    int i, addend, type;
806
                    const char *sym_name, *p;
807
                    char relname[1024];
808

    
809
                    data_allocated[data_index] = 1;
810

    
811
                    /* data value */
812
                    addend = get32((uint32_t *)(p_start + pc_offset));
813
                    relname[0] = '\0';
814
                    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
815
                        if (rel->r_offset == (pc_offset + start_offset)) {
816
                            sym_name = get_rel_sym_name(rel);
817
                            /* the compiler leave some unnecessary references to the code */
818
                            if (strstart(sym_name, "__op_param", &p)) {
819
                                snprintf(relname, sizeof(relname), "param%s", p);
820
                            } else {
821
                                snprintf(relname, sizeof(relname), "(long)(&%s)", sym_name);
822
                            }
823
                            type = ELF32_R_TYPE(rel->r_info);
824
                            if (type != R_ARM_ABS32)
825
                                error("%s: unsupported data relocation", name);
826
                            break;
827
                        }
828
                    }
829
                    fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
830
                            data_index, addend);
831
                    if (relname[0] != '\0')
832
                        fprintf(outfile, " + %s", relname);
833
                    fprintf(outfile, ";\n");
834
                }
835
            }
836
        }
837
        p += 4;
838
    }
839
    data_size = (p_end - p_start) - min_offset;
840
    if (data_size > 0 && outfile) {
841
        fprintf(outfile, "    arm_data_ptr += %d;\n", data_size >> 2);
842
    }
843

    
844
    /* the last instruction must be a mov pc, lr */
845
    if (p == p_start)
846
        goto arm_ret_error;
847
    p -= 4;
848
    insn = get32((uint32_t *)p);
849
    if ((insn & 0xffff0000) != 0xe91b0000) {
850
    arm_ret_error:
851
        if (!outfile)
852
            printf("%s: invalid epilog\n", name);
853
    }
854
    return p - p_start;            
855
}
856
#endif
857

    
858

    
859
#define MAX_ARGS 3
860

    
861
/* generate op code */
862
void gen_code(const char *name, host_ulong offset, host_ulong size, 
863
              FILE *outfile, int gen_switch)
864
{
865
    int copy_size = 0;
866
    uint8_t *p_start, *p_end;
867
    host_ulong start_offset;
868
    int nb_args, i, n;
869
    uint8_t args_present[MAX_ARGS];
870
    const char *sym_name, *p;
871
    EXE_RELOC *rel;
872

    
873
    /* Compute exact size excluding prologue and epilogue instructions.
874
     * Increment start_offset to skip epilogue instructions, then compute
875
     * copy_size the indicate the size of the remaining instructions (in
876
     * bytes).
877
     */
878
    p_start = text + offset;
879
    p_end = p_start + size;
880
    start_offset = offset;
881
#if defined(HOST_I386) || defined(HOST_AMD64)
882
#ifdef CONFIG_FORMAT_COFF
883
    {
884
        uint8_t *p;
885
        p = p_end - 1;
886
        if (p == p_start)
887
            error("empty code for %s", name);
888
        while (*p != 0xc3) {
889
            p--;
890
            if (p <= p_start)
891
                error("ret or jmp expected at the end of %s", name);
892
        }
893
        copy_size = p - p_start;
894
    }
895
#else
896
    {
897
        int len;
898
        len = p_end - p_start;
899
        if (len == 0)
900
            error("empty code for %s", name);
901
        if (p_end[-1] == 0xc3) {
902
            len--;
903
        } else {
904
            error("ret or jmp expected at the end of %s", name);
905
        }
906
        copy_size = len;
907
    }
908
#endif    
909
#elif defined(HOST_PPC)
910
    {
911
        uint8_t *p;
912
        p = (void *)(p_end - 4);
913
        if (p == p_start)
914
            error("empty code for %s", name);
915
        if (get32((uint32_t *)p) != 0x4e800020)
916
            error("blr expected at the end of %s", name);
917
        copy_size = p - p_start;
918
    }
919
#elif defined(HOST_S390)
920
    {
921
        uint8_t *p;
922
        p = (void *)(p_end - 2);
923
        if (p == p_start)
924
            error("empty code for %s", name);
925
        if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
926
            error("br %%r14 expected at the end of %s", name);
927
        copy_size = p - p_start;
928
    }
929
#elif defined(HOST_ALPHA)
930
    {
931
        uint8_t *p;
932
        p = p_end - 4;
933
#if 0
934
        /* XXX: check why it occurs */
935
        if (p == p_start)
936
            error("empty code for %s", name);
937
#endif
938
        if (get32((uint32_t *)p) != 0x6bfa8001)
939
            error("ret expected at the end of %s", name);
940
        copy_size = p - p_start;            
941
    }
942
#elif defined(HOST_IA64)
943
    {
944
        uint8_t *p;
945
        p = (void *)(p_end - 4);
946
        if (p == p_start)
947
            error("empty code for %s", name);
948
        /* br.ret.sptk.many b0;; */
949
        /* 08 00 84 00 */
950
        if (get32((uint32_t *)p) != 0x00840008)
951
            error("br.ret.sptk.many b0;; expected at the end of %s", name);
952
        copy_size = p - p_start;
953
    }
954
#elif defined(HOST_SPARC)
955
    {
956
        uint32_t start_insn, end_insn1, end_insn2;
957
        uint8_t *p;
958
        p = (void *)(p_end - 8);
959
        if (p <= p_start)
960
            error("empty code for %s", name);
961
        start_insn = get32((uint32_t *)(p_start + 0x0));
962
        end_insn1 = get32((uint32_t *)(p + 0x0));
963
        end_insn2 = get32((uint32_t *)(p + 0x4));
964
        if ((start_insn & ~0x1fff) == 0x9de3a000) {
965
            p_start += 0x4;
966
            start_offset += 0x4;
967
            if ((int)(start_insn | ~0x1fff) < -128)
968
                error("Found bogus save at the start of %s", name);
969
            if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
970
                error("ret; restore; not found at end of %s", name);
971
        } else {
972
            error("No save at the beginning of %s", name);
973
        }
974
#if 0
975
        /* Skip a preceeding nop, if present.  */
976
        if (p > p_start) {
977
            skip_insn = get32((uint32_t *)(p - 0x4));
978
            if (skip_insn == 0x01000000)
979
                p -= 4;
980
        }
981
#endif
982
        copy_size = p - p_start;
983
    }
984
#elif defined(HOST_SPARC64)
985
    {
986
        uint32_t start_insn, end_insn1, end_insn2, skip_insn;
987
        uint8_t *p;
988
        p = (void *)(p_end - 8);
989
        if (p <= p_start)
990
            error("empty code for %s", name);
991
        start_insn = get32((uint32_t *)(p_start + 0x0));
992
        end_insn1 = get32((uint32_t *)(p + 0x0));
993
        end_insn2 = get32((uint32_t *)(p + 0x4));
994
        if ((start_insn & ~0x1fff) == 0x9de3a000) {
995
            p_start += 0x4;
996
            start_offset += 0x4;
997
            if ((int)(start_insn | ~0x1fff) < -256)
998
                error("Found bogus save at the start of %s", name);
999
            if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
1000
                error("ret; restore; not found at end of %s", name);
1001
        } else {
1002
            error("No save at the beginning of %s", name);
1003
        }
1004
        
1005
        /* Skip a preceeding nop, if present.  */
1006
        if (p > p_start) {
1007
            skip_insn = get32((uint32_t *)(p - 0x4));
1008
            if (skip_insn == 0x01000000)
1009
                p -= 4;
1010
        }
1011
        
1012
        copy_size = p - p_start;
1013
    }
1014
#elif defined(HOST_ARM)
1015
    {
1016
        if ((p_end - p_start) <= 16)
1017
            error("%s: function too small", name);
1018
        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1019
            (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1020
            get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1021
            error("%s: invalid prolog", name);
1022
        p_start += 12;
1023
        start_offset += 12;
1024
        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, 
1025
                                      relocs, nb_relocs);
1026
    }
1027
#elif defined(HOST_M68K)
1028
    {
1029
        uint8_t *p;
1030
        p = (void *)(p_end - 2);
1031
        if (p == p_start)
1032
            error("empty code for %s", name);
1033
        // remove NOP's, probably added for alignment
1034
        while ((get16((uint16_t *)p) == 0x4e71) &&
1035
               (p>p_start)) 
1036
            p -= 2;
1037
        if (get16((uint16_t *)p) != 0x4e75)
1038
            error("rts expected at the end of %s", name);
1039
        copy_size = p - p_start;
1040
    }
1041
#else
1042
#error unsupported CPU
1043
#endif
1044

    
1045
    /* compute the number of arguments by looking at the relocations */
1046
    for(i = 0;i < MAX_ARGS; i++)
1047
        args_present[i] = 0;
1048

    
1049
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1050
        if (rel->r_offset >= start_offset &&
1051
            rel->r_offset < start_offset + (p_end - p_start)) {
1052
            sym_name = get_rel_sym_name(rel);
1053
            if (strstart(sym_name, "__op_param", &p)) {
1054
                n = strtoul(p, NULL, 10);
1055
                if (n > MAX_ARGS)
1056
                    error("too many arguments in %s", name);
1057
                args_present[n - 1] = 1;
1058
            }
1059
        }
1060
    }
1061
    
1062
    nb_args = 0;
1063
    while (nb_args < MAX_ARGS && args_present[nb_args])
1064
        nb_args++;
1065
    for(i = nb_args; i < MAX_ARGS; i++) {
1066
        if (args_present[i])
1067
            error("inconsistent argument numbering in %s", name);
1068
    }
1069

    
1070
    if (gen_switch == 2) {
1071
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1072
    } else if (gen_switch == 1) {
1073

    
1074
        /* output C code */
1075
        fprintf(outfile, "case INDEX_%s: {\n", name);
1076
        if (nb_args > 0) {
1077
            fprintf(outfile, "    long ");
1078
            for(i = 0; i < nb_args; i++) {
1079
                if (i != 0)
1080
                    fprintf(outfile, ", ");
1081
                fprintf(outfile, "param%d", i + 1);
1082
            }
1083
            fprintf(outfile, ";\n");
1084
        }
1085
        fprintf(outfile, "    extern void %s();\n", name);
1086

    
1087
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1088
            if (rel->r_offset >= start_offset &&
1089
                rel->r_offset < start_offset + (p_end - p_start)) {
1090
                sym_name = get_rel_sym_name(rel);
1091
                if (*sym_name && 
1092
                    !strstart(sym_name, "__op_param", NULL) &&
1093
                    !strstart(sym_name, "__op_jmp", NULL)) {
1094
#if defined(HOST_SPARC)
1095
                    if (sym_name[0] == '.') {
1096
                        fprintf(outfile,
1097
                                "extern char __dot_%s __asm__(\"%s\");\n",
1098
                                sym_name+1, sym_name);
1099
                        continue;
1100
                    }
1101
#endif
1102
                    fprintf(outfile, "extern char %s;\n", sym_name);
1103
                }
1104
            }
1105
        }
1106

    
1107
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size);
1108

    
1109
        /* emit code offset information */
1110
        {
1111
            EXE_SYM *sym;
1112
            const char *sym_name, *p;
1113
            unsigned long val;
1114
            int n;
1115

    
1116
            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1117
                sym_name = get_sym_name(sym);
1118
                if (strstart(sym_name, "__op_label", &p)) {
1119
                    uint8_t *ptr;
1120
                    unsigned long offset;
1121
                    
1122
                    /* test if the variable refers to a label inside
1123
                       the code we are generating */
1124
#ifdef CONFIG_FORMAT_COFF
1125
                    if (sym->st_shndx == text_shndx) {
1126
                        ptr = sdata[coff_text_shndx];
1127
                    } else if (sym->st_shndx == data_shndx) {
1128
                        ptr = sdata[coff_data_shndx];
1129
                    } else {
1130
                        ptr = NULL;
1131
                    }
1132
#else
1133
                    ptr = sdata[sym->st_shndx];
1134
#endif
1135
                    if (!ptr)
1136
                        error("__op_labelN in invalid section");
1137
                    offset = sym->st_value;
1138
                    val = *(unsigned long *)(ptr + offset);
1139
#ifdef ELF_USES_RELOCA
1140
                    {
1141
                        int reloc_shndx, nb_relocs1, j;
1142

    
1143
                        /* try to find a matching relocation */
1144
                        reloc_shndx = find_reloc(sym->st_shndx);
1145
                        if (reloc_shndx) {
1146
                            nb_relocs1 = shdr[reloc_shndx].sh_size / 
1147
                                shdr[reloc_shndx].sh_entsize;
1148
                            rel = (ELF_RELOC *)sdata[reloc_shndx];
1149
                            for(j = 0; j < nb_relocs1; j++) {
1150
                                if (rel->r_offset == offset) {
1151
                                    val = rel->r_addend;
1152
                                    break;
1153
                                }
1154
                                rel++;
1155
                            }
1156
                        }
1157
                    }
1158
#endif                    
1159

    
1160
                    if (val >= start_offset && val < start_offset + copy_size) {
1161
                        n = strtol(p, NULL, 10);
1162
                        fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset);
1163
                    }
1164
                }
1165
            }
1166
        }
1167

    
1168
        /* load parameres in variables */
1169
        for(i = 0; i < nb_args; i++) {
1170
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1171
        }
1172

    
1173
        /* patch relocations */
1174
#if defined(HOST_I386)
1175
            {
1176
                char name[256];
1177
                int type;
1178
                int addend;
1179
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1180
                if (rel->r_offset >= start_offset &&
1181
                    rel->r_offset < start_offset + copy_size) {
1182
                    sym_name = get_rel_sym_name(rel);
1183
                    if (strstart(sym_name, "__op_jmp", &p)) {
1184
                        int n;
1185
                        n = strtol(p, NULL, 10);
1186
                        /* __op_jmp relocations are done at
1187
                           runtime to do translated block
1188
                           chaining: the offset of the instruction
1189
                           needs to be stored */
1190
                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1191
                                n, rel->r_offset - start_offset);
1192
                        continue;
1193
                    }
1194
                        
1195
                    if (strstart(sym_name, "__op_param", &p)) {
1196
                        snprintf(name, sizeof(name), "param%s", p);
1197
                    } else {
1198
                        snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1199
                    }
1200
                    addend = get32((uint32_t *)(text + rel->r_offset));
1201
#ifdef CONFIG_FORMAT_ELF
1202
                    type = ELF32_R_TYPE(rel->r_info);
1203
                    switch(type) {
1204
                    case R_386_32:
1205
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1206
                                rel->r_offset - start_offset, name, addend);
1207
                        break;
1208
                    case R_386_PC32:
1209
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", 
1210
                                rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
1211
                        break;
1212
                    default:
1213
                        error("unsupported i386 relocation (%d)", type);
1214
                    }
1215
#elif defined(CONFIG_FORMAT_COFF)
1216
                    type = rel->r_type;
1217
                    switch(type) {
1218
                    case DIR32:
1219
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1220
                                rel->r_offset - start_offset, name, addend);
1221
                        break;
1222
                    case DISP32:
1223
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n", 
1224
                                rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
1225
                        break;
1226
                    default:
1227
                        error("unsupported i386 relocation (%d)", type);
1228
                    }
1229
#else
1230
#error unsupport object format
1231
#endif
1232
                }
1233
                }
1234
            }
1235
#elif defined(HOST_AMD64)
1236
            {
1237
                char name[256];
1238
                int type;
1239
                int addend;
1240
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1241
                if (rel->r_offset >= start_offset &&
1242
                    rel->r_offset < start_offset + copy_size) {
1243
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1244
                    if (strstart(sym_name, "__op_param", &p)) {
1245
                        snprintf(name, sizeof(name), "param%s", p);
1246
                    } else {
1247
                        snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1248
                    }
1249
                    type = ELF32_R_TYPE(rel->r_info);
1250
                    addend = rel->r_addend;
1251
                    switch(type) {
1252
                    case R_X86_64_32:
1253
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n", 
1254
                                rel->r_offset - start_offset, name, addend);
1255
                        break;
1256
                    case R_X86_64_32S:
1257
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", 
1258
                                rel->r_offset - start_offset, name, addend);
1259
                        break;
1260
                    case R_X86_64_PC32:
1261
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", 
1262
                                rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
1263
                        break;
1264
                    default:
1265
                        error("unsupported AMD64 relocation (%d)", type);
1266
                    }
1267
                }
1268
                }
1269
            }
1270
#elif defined(HOST_PPC)
1271
            {
1272
                char name[256];
1273
                int type;
1274
                int addend;
1275
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1276
                    if (rel->r_offset >= start_offset &&
1277
                        rel->r_offset < start_offset + copy_size) {
1278
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1279
                        if (strstart(sym_name, "__op_jmp", &p)) {
1280
                            int n;
1281
                            n = strtol(p, NULL, 10);
1282
                            /* __op_jmp relocations are done at
1283
                               runtime to do translated block
1284
                               chaining: the offset of the instruction
1285
                               needs to be stored */
1286
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1287
                                    n, rel->r_offset - start_offset);
1288
                            continue;
1289
                        }
1290
                        
1291
                        if (strstart(sym_name, "__op_param", &p)) {
1292
                            snprintf(name, sizeof(name), "param%s", p);
1293
                        } else {
1294
                            snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1295
                        }
1296
                        type = ELF32_R_TYPE(rel->r_info);
1297
                        addend = rel->r_addend;
1298
                        switch(type) {
1299
                        case R_PPC_ADDR32:
1300
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1301
                                    rel->r_offset - start_offset, name, addend);
1302
                            break;
1303
                        case R_PPC_ADDR16_LO:
1304
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", 
1305
                                    rel->r_offset - start_offset, name, addend);
1306
                            break;
1307
                        case R_PPC_ADDR16_HI:
1308
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", 
1309
                                    rel->r_offset - start_offset, name, addend);
1310
                            break;
1311
                        case R_PPC_ADDR16_HA:
1312
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", 
1313
                                    rel->r_offset - start_offset, name, addend);
1314
                            break;
1315
                        case R_PPC_REL24:
1316
                            /* warning: must be at 32 MB distancy */
1317
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", 
1318
                                    rel->r_offset - start_offset, rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
1319
                            break;
1320
                        default:
1321
                            error("unsupported powerpc relocation (%d)", type);
1322
                        }
1323
                    }
1324
                }
1325
            }
1326
#elif defined(HOST_S390)
1327
            {
1328
                char name[256];
1329
                int type;
1330
                int addend;
1331
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1332
                    if (rel->r_offset >= start_offset &&
1333
                        rel->r_offset < start_offset + copy_size) {
1334
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1335
                        if (strstart(sym_name, "__op_param", &p)) {
1336
                            snprintf(name, sizeof(name), "param%s", p);
1337
                        } else {
1338
                            snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1339
                        }
1340
                        type = ELF32_R_TYPE(rel->r_info);
1341
                        addend = rel->r_addend;
1342
                        switch(type) {
1343
                        case R_390_32:
1344
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1345
                                    rel->r_offset - start_offset, name, addend);
1346
                            break;
1347
                        case R_390_16:
1348
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1349
                                    rel->r_offset - start_offset, name, addend);
1350
                            break;
1351
                        case R_390_8:
1352
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1353
                                    rel->r_offset - start_offset, name, addend);
1354
                            break;
1355
                        default:
1356
                            error("unsupported s390 relocation (%d)", type);
1357
                        }
1358
                    }
1359
                }
1360
            }
1361
#elif defined(HOST_ALPHA)
1362
            {
1363
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1364
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
1365
                        int type;
1366

    
1367
                        type = ELF64_R_TYPE(rel->r_info);
1368
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
1369
                        switch (type) {
1370
                        case R_ALPHA_GPDISP:
1371
                            /* The gp is just 32 bit, and never changes, so it's easiest to emit it
1372
                               as an immediate instead of constructing it from the pv or ra.  */
1373
                            fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
1374
                                    rel->r_offset - start_offset);
1375
                            fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
1376
                                    rel->r_offset - start_offset + rel->r_addend);
1377
                            break;
1378
                        case R_ALPHA_LITUSE:
1379
                            /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
1380
                               now, since some called functions (libc) need pv to be set up.  */
1381
                            break;
1382
                        case R_ALPHA_HINT:
1383
                            /* Branch target prediction hint. Ignore for now.  Should be already
1384
                               correct for in-function jumps.  */
1385
                            break;
1386
                        case R_ALPHA_LITERAL:
1387
                            /* Load a literal from the GOT relative to the gp.  Since there's only a
1388
                               single gp, nothing is to be done.  */
1389
                            break;
1390
                        case R_ALPHA_GPRELHIGH:
1391
                            /* Handle fake relocations against __op_param symbol.  Need to emit the
1392
                               high part of the immediate value instead.  Other symbols need no
1393
                               special treatment.  */
1394
                            if (strstart(sym_name, "__op_param", &p))
1395
                                fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
1396
                                        rel->r_offset - start_offset, p);
1397
                            break;
1398
                        case R_ALPHA_GPRELLOW:
1399
                            if (strstart(sym_name, "__op_param", &p))
1400
                                fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
1401
                                        rel->r_offset - start_offset, p);
1402
                            break;
1403
                        case R_ALPHA_BRSGP:
1404
                            /* PC-relative jump. Tweak offset to skip the two instructions that try to
1405
                               set up the gp from the pv.  */
1406
                            fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
1407
                                    rel->r_offset - start_offset, sym_name, rel->r_offset - start_offset);
1408
                            break;
1409
                        default:
1410
                            error("unsupported Alpha relocation (%d)", type);
1411
                        }
1412
                    }
1413
                }
1414
            }
1415
#elif defined(HOST_IA64)
1416
            {
1417
                char name[256];
1418
                int type;
1419
                int addend;
1420
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1421
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
1422
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
1423
                        if (strstart(sym_name, "__op_param", &p)) {
1424
                            snprintf(name, sizeof(name), "param%s", p);
1425
                        } else {
1426
                            snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1427
                        }
1428
                        type = ELF64_R_TYPE(rel->r_info);
1429
                        addend = rel->r_addend;
1430
                        switch(type) {
1431
                        case R_IA64_LTOFF22:
1432
                            error("must implemnt R_IA64_LTOFF22 relocation");
1433
                        case R_IA64_PCREL21B:
1434
                            error("must implemnt R_IA64_PCREL21B relocation");
1435
                        default:
1436
                            error("unsupported ia64 relocation (%d)", type);
1437
                        }
1438
                    }
1439
                }
1440
            }
1441
#elif defined(HOST_SPARC)
1442
            {
1443
                char name[256];
1444
                int type;
1445
                int addend;
1446
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1447
                    if (rel->r_offset >= start_offset &&
1448
                        rel->r_offset < start_offset + copy_size) {
1449
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
1450
                        if (strstart(sym_name, "__op_param", &p)) {
1451
                            snprintf(name, sizeof(name), "param%s", p);
1452
                        } else {
1453
                                if (sym_name[0] == '.')
1454
                                        snprintf(name, sizeof(name),
1455
                                                 "(long)(&__dot_%s)",
1456
                                                 sym_name + 1);
1457
                                else
1458
                                        snprintf(name, sizeof(name),
1459
                                                 "(long)(&%s)", sym_name);
1460
                        }
1461
                        type = ELF32_R_TYPE(rel->r_info);
1462
                        addend = rel->r_addend;
1463
                        switch(type) {
1464
                        case R_SPARC_32:
1465
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1466
                                    rel->r_offset - start_offset, name, addend);
1467
                            break;
1468
                        case R_SPARC_HI22:
1469
                            fprintf(outfile,
1470
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
1471
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
1472
                                    " & ~0x3fffff) "
1473
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
1474
                                    rel->r_offset - start_offset,
1475
                                    rel->r_offset - start_offset,
1476
                                    name, addend);
1477
                            break;
1478
                        case R_SPARC_LO10:
1479
                            fprintf(outfile,
1480
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
1481
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
1482
                                    " & ~0x3ff) "
1483
                                    " | ((%s + %d) & 0x3ff);\n",
1484
                                    rel->r_offset - start_offset,
1485
                                    rel->r_offset - start_offset,
1486
                                    name, addend);
1487
                            break;
1488
                        case R_SPARC_WDISP30:
1489
                            fprintf(outfile,
1490
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
1491
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
1492
                                    " & ~0x3fffffff) "
1493
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
1494
                                    "    & 0x3fffffff);\n",
1495
                                    rel->r_offset - start_offset,
1496
                                    rel->r_offset - start_offset,
1497
                                    name, addend,
1498
                                    rel->r_offset - start_offset);
1499
                            break;
1500
                        default:
1501
                            error("unsupported sparc relocation (%d)", type);
1502
                        }
1503
                    }
1504
                }
1505
            }
1506
#elif defined(HOST_SPARC64)
1507
            {
1508
                char name[256];
1509
                int type;
1510
                int addend;
1511
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1512
                    if (rel->r_offset >= start_offset &&
1513
                        rel->r_offset < start_offset + copy_size) {
1514
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
1515
                        if (strstart(sym_name, "__op_param", &p)) {
1516
                            snprintf(name, sizeof(name), "param%s", p);
1517
                        } else {
1518
                            snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1519
                        }
1520
                        type = ELF64_R_TYPE(rel->r_info);
1521
                        addend = rel->r_addend;
1522
                        switch(type) {
1523
                        case R_SPARC_32:
1524
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1525
                                    rel->r_offset - start_offset, name, addend);
1526
                            break;
1527
                        case R_SPARC_HI22:
1528
                            fprintf(outfile,
1529
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
1530
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
1531
                                    " & ~0x3fffff) "
1532
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
1533
                                    rel->r_offset - start_offset,
1534
                                    rel->r_offset - start_offset,
1535
                                    name, addend);
1536
                            break;
1537
                        case R_SPARC_LO10:
1538
                            fprintf(outfile,
1539
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
1540
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
1541
                                    " & ~0x3ff) "
1542
                                    " | ((%s + %d) & 0x3ff);\n",
1543
                                    rel->r_offset - start_offset,
1544
                                    rel->r_offset - start_offset,
1545
                                    name, addend);
1546
                            break;
1547
                        case R_SPARC_WDISP30:
1548
                            fprintf(outfile,
1549
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
1550
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
1551
                                    " & ~0x3fffffff) "
1552
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
1553
                                    "    & 0x3fffffff);\n",
1554
                                    rel->r_offset - start_offset,
1555
                                    rel->r_offset - start_offset,
1556
                                    name, addend,
1557
                                    rel->r_offset - start_offset);
1558
                            break;
1559
                        default:
1560
                            error("unsupported sparc64 relocation (%d)", type);
1561
                        }
1562
                    }
1563
                }
1564
            }
1565
#elif defined(HOST_ARM)
1566
            {
1567
                char name[256];
1568
                int type;
1569
                int addend;
1570

    
1571
                arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
1572
                                  relocs, nb_relocs);
1573

    
1574
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1575
                if (rel->r_offset >= start_offset &&
1576
                    rel->r_offset < start_offset + copy_size) {
1577
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1578
                    /* the compiler leave some unnecessary references to the code */
1579
                    if (sym_name[0] == '\0')
1580
                        continue;
1581
                    if (strstart(sym_name, "__op_param", &p)) {
1582
                        snprintf(name, sizeof(name), "param%s", p);
1583
                    } else {
1584
                        snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1585
                    }
1586
                    type = ELF32_R_TYPE(rel->r_info);
1587
                    addend = get32((uint32_t *)(text + rel->r_offset));
1588
                    switch(type) {
1589
                    case R_ARM_ABS32:
1590
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1591
                                rel->r_offset - start_offset, name, addend);
1592
                        break;
1593
                    case R_ARM_PC24:
1594
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n", 
1595
                                rel->r_offset - start_offset, addend, name);
1596
                        break;
1597
                    default:
1598
                        error("unsupported arm relocation (%d)", type);
1599
                    }
1600
                }
1601
                }
1602
            }
1603
#elif defined(HOST_M68K)
1604
            {
1605
                char name[256];
1606
                int type;
1607
                int addend;
1608
                Elf32_Sym *sym;
1609
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1610
                if (rel->r_offset >= start_offset &&
1611
                    rel->r_offset < start_offset + copy_size) {
1612
                    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
1613
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1614
                    if (strstart(sym_name, "__op_param", &p)) {
1615
                        snprintf(name, sizeof(name), "param%s", p);
1616
                    } else {
1617
                        snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1618
                    }
1619
                    type = ELF32_R_TYPE(rel->r_info);
1620
                    addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
1621
                    switch(type) {
1622
                    case R_68K_32:
1623
                        fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
1624
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n", 
1625
                                rel->r_offset - start_offset, name, addend );
1626
                        break;
1627
                    case R_68K_PC32:
1628
                        fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
1629
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n", 
1630
                                rel->r_offset - start_offset, name, rel->r_offset - start_offset, /*sym->st_value+*/ addend);
1631
                        break;
1632
                    default:
1633
                        error("unsupported m68k relocation (%d)", type);
1634
                    }
1635
                }
1636
                }
1637
            }
1638
#else
1639
#error unsupported CPU
1640
#endif
1641
        fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
1642
        fprintf(outfile, "}\n");
1643
        fprintf(outfile, "break;\n\n");
1644
    } else {
1645
        fprintf(outfile, "static inline void gen_%s(", name);
1646
        if (nb_args == 0) {
1647
            fprintf(outfile, "void");
1648
        } else {
1649
            for(i = 0; i < nb_args; i++) {
1650
                if (i != 0)
1651
                    fprintf(outfile, ", ");
1652
                fprintf(outfile, "long param%d", i + 1);
1653
            }
1654
        }
1655
        fprintf(outfile, ")\n");
1656
        fprintf(outfile, "{\n");
1657
        for(i = 0; i < nb_args; i++) {
1658
            fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
1659
        }
1660
        fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
1661
        fprintf(outfile, "}\n\n");
1662
    }
1663
}
1664

    
1665
int gen_file(FILE *outfile, int out_type)
1666
{
1667
    int i;
1668
    EXE_SYM *sym;
1669

    
1670
    if (out_type == OUT_INDEX_OP) {
1671
        fprintf(outfile, "DEF(end, 0, 0)\n");
1672
        fprintf(outfile, "DEF(nop, 0, 0)\n");
1673
        fprintf(outfile, "DEF(nop1, 1, 0)\n");
1674
        fprintf(outfile, "DEF(nop2, 2, 0)\n");
1675
        fprintf(outfile, "DEF(nop3, 3, 0)\n");
1676
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1677
            const char *name, *p;
1678
            name = get_sym_name(sym);
1679
            if (strstart(name, OP_PREFIX, &p)) {
1680
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
1681
            }
1682
        }
1683
    } else if (out_type == OUT_GEN_OP) {
1684
        /* generate gen_xxx functions */
1685

    
1686
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1687
            const char *name;
1688
            name = get_sym_name(sym);
1689
            if (strstart(name, OP_PREFIX, NULL)) {
1690
                if (sym->st_shndx != text_shndx)
1691
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
1692
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
1693
            }
1694
        }
1695
        
1696
    } else {
1697
        /* generate big code generation switch */
1698
fprintf(outfile,
1699
"int dyngen_code(uint8_t *gen_code_buf,\n"
1700
"                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
1701
"                const uint16_t *opc_buf, const uint32_t *opparam_buf)\n"
1702
"{\n"
1703
"    uint8_t *gen_code_ptr;\n"
1704
"    const uint16_t *opc_ptr;\n"
1705
"    const uint32_t *opparam_ptr;\n");
1706

    
1707
#ifdef HOST_ARM
1708
fprintf(outfile,
1709
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
1710
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
1711
"    uint32_t *arm_data_ptr = arm_data_table;\n");
1712
#endif
1713

    
1714
fprintf(outfile,
1715
"\n"
1716
"    gen_code_ptr = gen_code_buf;\n"
1717
"    opc_ptr = opc_buf;\n"
1718
"    opparam_ptr = opparam_buf;\n");
1719

    
1720
        /* Generate prologue, if needed. */ 
1721

    
1722
fprintf(outfile,
1723
"    for(;;) {\n"
1724
"        switch(*opc_ptr++) {\n"
1725
);
1726

    
1727
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1728
            const char *name;
1729
            name = get_sym_name(sym);
1730
            if (strstart(name, OP_PREFIX, NULL)) {
1731
#if 0
1732
                printf("%4d: %s pos=0x%08x len=%d\n", 
1733
                       i, name, sym->st_value, sym->st_size);
1734
#endif
1735
                if (sym->st_shndx != text_shndx)
1736
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
1737
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
1738
            }
1739
        }
1740

    
1741
fprintf(outfile,
1742
"        case INDEX_op_nop:\n"
1743
"            break;\n"
1744
"        case INDEX_op_nop1:\n"
1745
"            opparam_ptr++;\n"
1746
"            break;\n"
1747
"        case INDEX_op_nop2:\n"
1748
"            opparam_ptr += 2;\n"
1749
"            break;\n"
1750
"        case INDEX_op_nop3:\n"
1751
"            opparam_ptr += 3;\n"
1752
"            break;\n"
1753
"        default:\n"
1754
"            goto the_end;\n"
1755
"        }\n");
1756

    
1757
#ifdef HOST_ARM
1758
/* generate constant table if needed */
1759
fprintf(outfile,
1760
"        if ((gen_code_ptr - last_gen_code_ptr) >= (MAX_FRAG_SIZE - MAX_OP_SIZE)) {\n"
1761
"            gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 1);\n"
1762
"            last_gen_code_ptr = gen_code_ptr;\n"
1763
"            arm_ldr_ptr = arm_ldr_table;\n"
1764
"            arm_data_ptr = arm_data_table;\n"
1765
"        }\n");         
1766
#endif
1767

    
1768

    
1769
fprintf(outfile,
1770
"    }\n"
1771
" the_end:\n"
1772
);
1773

    
1774
/* generate some code patching */ 
1775
#ifdef HOST_ARM
1776
fprintf(outfile, "gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 0);\n");
1777
#endif
1778
    /* flush instruction cache */
1779
    fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
1780

    
1781
    fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n");
1782
    fprintf(outfile, "}\n\n");
1783

    
1784
    }
1785

    
1786
    return 0;
1787
}
1788

    
1789
void usage(void)
1790
{
1791
    printf("dyngen (c) 2003 Fabrice Bellard\n"
1792
           "usage: dyngen [-o outfile] [-c] objfile\n"
1793
           "Generate a dynamic code generator from an object file\n"
1794
           "-c     output enum of operations\n"
1795
           "-g     output gen_op_xx() functions\n"
1796
           );
1797
    exit(1);
1798
}
1799

    
1800
int main(int argc, char **argv)
1801
{
1802
    int c, out_type;
1803
    const char *filename, *outfilename;
1804
    FILE *outfile;
1805

    
1806
    outfilename = "out.c";
1807
    out_type = OUT_CODE;
1808
    for(;;) {
1809
        c = getopt(argc, argv, "ho:cg");
1810
        if (c == -1)
1811
            break;
1812
        switch(c) {
1813
        case 'h':
1814
            usage();
1815
            break;
1816
        case 'o':
1817
            outfilename = optarg;
1818
            break;
1819
        case 'c':
1820
            out_type = OUT_INDEX_OP;
1821
            break;
1822
        case 'g':
1823
            out_type = OUT_GEN_OP;
1824
            break;
1825
        }
1826
    }
1827
    if (optind >= argc)
1828
        usage();
1829
    filename = argv[optind];
1830
    outfile = fopen(outfilename, "w");
1831
    if (!outfile)
1832
        error("could not open '%s'", outfilename);
1833

    
1834
    load_object(filename);
1835
    gen_file(outfile, out_type);
1836
    fclose(outfile);
1837
    return 0;
1838
}