~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/recompiler/dyngen.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

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