Statistics
| Branch: | Revision:

root / dyngen.c @ f54b3f92

History | View | Annotate | Download (100.8 kB)

1
/*
2
 *  Generic Dynamic compiler generator
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *
6
 *  The COFF object format support was extracted from Kazu's QEMU port
7
 *  to Win32.
8
 *
9
 *  Mach-O Support by Matt Reda and Pierre d'Herbemont
10
 *
11
 *  This program is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  This program is distributed in the hope that it will be useful,
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 *  GNU General Public License for more details.
20
 *
21
 *  You should have received a copy of the GNU General Public License
22
 *  along with this program; if not, write to the Free Software
23
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
 */
25
#include <stdlib.h>
26
#include <stdio.h>
27
#include <string.h>
28
#include <stdarg.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <fcntl.h>
32

    
33
#include "config-host.h"
34

    
35
/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross
36
   compilation */
37
#if defined(CONFIG_WIN32)
38
#define CONFIG_FORMAT_COFF
39
#elif defined(CONFIG_DARWIN)
40
#define CONFIG_FORMAT_MACH
41
#else
42
#define CONFIG_FORMAT_ELF
43
#endif
44

    
45
#ifdef CONFIG_FORMAT_ELF
46

    
47
/* elf format definitions. We use these macros to test the CPU to
48
   allow cross compilation (this tool must be ran on the build
49
   platform) */
50
#if defined(HOST_I386)
51

    
52
#define ELF_CLASS        ELFCLASS32
53
#define ELF_ARCH        EM_386
54
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
55
#undef ELF_USES_RELOCA
56

    
57
#elif defined(HOST_X86_64)
58

    
59
#define ELF_CLASS        ELFCLASS64
60
#define ELF_ARCH        EM_X86_64
61
#define elf_check_arch(x) ((x) == EM_X86_64)
62
#define ELF_USES_RELOCA
63

    
64
#elif defined(HOST_PPC)
65

    
66
#define ELF_CLASS        ELFCLASS32
67
#define ELF_ARCH        EM_PPC
68
#define elf_check_arch(x) ((x) == EM_PPC)
69
#define ELF_USES_RELOCA
70

    
71
#elif defined(HOST_S390)
72

    
73
#define ELF_CLASS        ELFCLASS32
74
#define ELF_ARCH        EM_S390
75
#define elf_check_arch(x) ((x) == EM_S390)
76
#define ELF_USES_RELOCA
77

    
78
#elif defined(HOST_ALPHA)
79

    
80
#define ELF_CLASS        ELFCLASS64
81
#define ELF_ARCH        EM_ALPHA
82
#define elf_check_arch(x) ((x) == EM_ALPHA)
83
#define ELF_USES_RELOCA
84

    
85
#elif defined(HOST_IA64)
86

    
87
#define ELF_CLASS        ELFCLASS64
88
#define ELF_ARCH        EM_IA_64
89
#define elf_check_arch(x) ((x) == EM_IA_64)
90
#define ELF_USES_RELOCA
91

    
92
#elif defined(HOST_SPARC)
93

    
94
#define ELF_CLASS        ELFCLASS32
95
#define ELF_ARCH        EM_SPARC
96
#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
97
#define ELF_USES_RELOCA
98

    
99
#elif defined(HOST_SPARC64)
100

    
101
#define ELF_CLASS        ELFCLASS64
102
#define ELF_ARCH        EM_SPARCV9
103
#define elf_check_arch(x) ((x) == EM_SPARCV9)
104
#define ELF_USES_RELOCA
105

    
106
#elif defined(HOST_ARM)
107

    
108
#define ELF_CLASS        ELFCLASS32
109
#define ELF_ARCH        EM_ARM
110
#define elf_check_arch(x) ((x) == EM_ARM)
111
#define ELF_USES_RELOC
112

    
113
#elif defined(HOST_M68K)
114

    
115
#define ELF_CLASS        ELFCLASS32
116
#define ELF_ARCH        EM_68K
117
#define elf_check_arch(x) ((x) == EM_68K)
118
#define ELF_USES_RELOCA
119

    
120
#elif defined(HOST_HPPA)
121

    
122
#define ELF_CLASS   ELFCLASS32
123
#define ELF_ARCH    EM_PARISC
124
#define elf_check_arch(x) ((x) == EM_PARISC)
125
#define ELF_USES_RELOCA
126

    
127
#elif defined(HOST_MIPS)
128

    
129
#define ELF_CLASS        ELFCLASS32
130
#define ELF_ARCH        EM_MIPS
131
#define elf_check_arch(x) ((x) == EM_MIPS)
132
#define ELF_USES_RELOC
133

    
134
#elif defined(HOST_MIPS64)
135

    
136
/* Assume n32 ABI here, which is ELF32. */
137
#define ELF_CLASS        ELFCLASS32
138
#define ELF_ARCH        EM_MIPS
139
#define elf_check_arch(x) ((x) == EM_MIPS)
140
#define ELF_USES_RELOCA
141

    
142
#else
143
#error unsupported CPU - please update the code
144
#endif
145

    
146
#include "elf.h"
147

    
148
#if ELF_CLASS == ELFCLASS32
149
typedef int32_t host_long;
150
typedef uint32_t host_ulong;
151
#define swabls(x) swab32s(x)
152
#define swablss(x) swab32ss(x)
153
#else
154
typedef int64_t host_long;
155
typedef uint64_t host_ulong;
156
#define swabls(x) swab64s(x)
157
#define swablss(x) swab64ss(x)
158
#endif
159

    
160
#ifdef ELF_USES_RELOCA
161
#define SHT_RELOC SHT_RELA
162
#else
163
#define SHT_RELOC SHT_REL
164
#endif
165

    
166
#define EXE_RELOC ELF_RELOC
167
#define EXE_SYM ElfW(Sym)
168

    
169
#endif /* CONFIG_FORMAT_ELF */
170

    
171
#ifdef CONFIG_FORMAT_COFF
172

    
173
typedef int32_t host_long;
174
typedef uint32_t host_ulong;
175

    
176
#include "a.out.h"
177

    
178
#define FILENAMELEN 256
179

    
180
typedef struct coff_sym {
181
    struct external_syment *st_syment;
182
    char st_name[FILENAMELEN];
183
    uint32_t st_value;
184
    int  st_size;
185
    uint8_t st_type;
186
    uint8_t st_shndx;
187
} coff_Sym;
188

    
189
typedef struct coff_rel {
190
    struct external_reloc *r_reloc;
191
    int  r_offset;
192
    uint8_t r_type;
193
} coff_Rel;
194

    
195
#define EXE_RELOC struct coff_rel
196
#define EXE_SYM struct coff_sym
197

    
198
#endif /* CONFIG_FORMAT_COFF */
199

    
200
#ifdef CONFIG_FORMAT_MACH
201

    
202
#include <mach-o/loader.h>
203
#include <mach-o/nlist.h>
204
#include <mach-o/reloc.h>
205
#include <mach-o/ppc/reloc.h>
206

    
207
# define check_mach_header(x) (x.magic == MH_MAGIC)
208
typedef int32_t host_long;
209
typedef uint32_t host_ulong;
210

    
211
struct nlist_extended
212
{
213
   union {
214
   char *n_name;
215
   long  n_strx;
216
   } n_un;
217
   unsigned char n_type;
218
   unsigned char n_sect;
219
   short st_desc;
220
   unsigned long st_value;
221
   unsigned long st_size;
222
};
223

    
224
#define EXE_RELOC struct relocation_info
225
#define EXE_SYM struct nlist_extended
226

    
227
#endif /* CONFIG_FORMAT_MACH */
228

    
229
#include "bswap.h"
230

    
231
enum {
232
    OUT_GEN_OP,
233
    OUT_CODE,
234
    OUT_INDEX_OP,
235
};
236

    
237
/* all dynamically generated functions begin with this code */
238
#define OP_PREFIX "op_"
239

    
240
int do_swap;
241

    
242
static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
243
{
244
    va_list ap;
245
    va_start(ap, fmt);
246
    fprintf(stderr, "dyngen: ");
247
    vfprintf(stderr, fmt, ap);
248
    fprintf(stderr, "\n");
249
    va_end(ap);
250
    exit(1);
251
}
252

    
253
static void *load_data(int fd, long offset, unsigned int size)
254
{
255
    char *data;
256

    
257
    data = malloc(size);
258
    if (!data)
259
        return NULL;
260
    lseek(fd, offset, SEEK_SET);
261
    if (read(fd, data, size) != size) {
262
        free(data);
263
        return NULL;
264
    }
265
    return data;
266
}
267

    
268
int strstart(const char *str, const char *val, const char **ptr)
269
{
270
    const char *p, *q;
271
    p = str;
272
    q = val;
273
    while (*q != '\0') {
274
        if (*p != *q)
275
            return 0;
276
        p++;
277
        q++;
278
    }
279
    if (ptr)
280
        *ptr = p;
281
    return 1;
282
}
283

    
284
void pstrcpy(char *buf, int buf_size, const char *str)
285
{
286
    int c;
287
    char *q = buf;
288

    
289
    if (buf_size <= 0)
290
        return;
291

    
292
    for(;;) {
293
        c = *str++;
294
        if (c == 0 || q >= buf + buf_size - 1)
295
            break;
296
        *q++ = c;
297
    }
298
    *q = '\0';
299
}
300

    
301
void swab16s(uint16_t *p)
302
{
303
    *p = bswap16(*p);
304
}
305

    
306
void swab32s(uint32_t *p)
307
{
308
    *p = bswap32(*p);
309
}
310

    
311
void swab32ss(int32_t *p)
312
{
313
    *p = bswap32(*p);
314
}
315

    
316
void swab64s(uint64_t *p)
317
{
318
    *p = bswap64(*p);
319
}
320

    
321
void swab64ss(int64_t *p)
322
{
323
    *p = bswap64(*p);
324
}
325

    
326
uint16_t get16(uint16_t *p)
327
{
328
    uint16_t val;
329
    val = *p;
330
    if (do_swap)
331
        val = bswap16(val);
332
    return val;
333
}
334

    
335
uint32_t get32(uint32_t *p)
336
{
337
    uint32_t val;
338
    val = *p;
339
    if (do_swap)
340
        val = bswap32(val);
341
    return val;
342
}
343

    
344
void put16(uint16_t *p, uint16_t val)
345
{
346
    if (do_swap)
347
        val = bswap16(val);
348
    *p = val;
349
}
350

    
351
void put32(uint32_t *p, uint32_t val)
352
{
353
    if (do_swap)
354
        val = bswap32(val);
355
    *p = val;
356
}
357

    
358
/* executable information */
359
EXE_SYM *symtab;
360
int nb_syms;
361
int text_shndx;
362
uint8_t *text;
363
EXE_RELOC *relocs;
364
int nb_relocs;
365

    
366
#ifdef CONFIG_FORMAT_ELF
367

    
368
/* ELF file info */
369
struct elf_shdr *shdr;
370
uint8_t **sdata;
371
struct elfhdr ehdr;
372
char *strtab;
373

    
374
int elf_must_swap(struct elfhdr *h)
375
{
376
  union {
377
      uint32_t i;
378
      uint8_t b[4];
379
  } swaptest;
380

    
381
  swaptest.i = 1;
382
  return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
383
      (swaptest.b[0] == 0);
384
}
385

    
386
void elf_swap_ehdr(struct elfhdr *h)
387
{
388
    swab16s(&h->e_type);                        /* Object file type */
389
    swab16s(&h->        e_machine);                /* Architecture */
390
    swab32s(&h->        e_version);                /* Object file version */
391
    swabls(&h->        e_entry);                /* Entry point virtual address */
392
    swabls(&h->        e_phoff);                /* Program header table file offset */
393
    swabls(&h->        e_shoff);                /* Section header table file offset */
394
    swab32s(&h->        e_flags);                /* Processor-specific flags */
395
    swab16s(&h->        e_ehsize);                /* ELF header size in bytes */
396
    swab16s(&h->        e_phentsize);                /* Program header table entry size */
397
    swab16s(&h->        e_phnum);                /* Program header table entry count */
398
    swab16s(&h->        e_shentsize);                /* Section header table entry size */
399
    swab16s(&h->        e_shnum);                /* Section header table entry count */
400
    swab16s(&h->        e_shstrndx);                /* Section header string table index */
401
}
402

    
403
void elf_swap_shdr(struct elf_shdr *h)
404
{
405
  swab32s(&h->        sh_name);                /* Section name (string tbl index) */
406
  swab32s(&h->        sh_type);                /* Section type */
407
  swabls(&h->        sh_flags);                /* Section flags */
408
  swabls(&h->        sh_addr);                /* Section virtual addr at execution */
409
  swabls(&h->        sh_offset);                /* Section file offset */
410
  swabls(&h->        sh_size);                /* Section size in bytes */
411
  swab32s(&h->        sh_link);                /* Link to another section */
412
  swab32s(&h->        sh_info);                /* Additional section information */
413
  swabls(&h->        sh_addralign);                /* Section alignment */
414
  swabls(&h->        sh_entsize);                /* Entry size if section holds table */
415
}
416

    
417
void elf_swap_phdr(struct elf_phdr *h)
418
{
419
    swab32s(&h->p_type);                        /* Segment type */
420
    swabls(&h->p_offset);                /* Segment file offset */
421
    swabls(&h->p_vaddr);                /* Segment virtual address */
422
    swabls(&h->p_paddr);                /* Segment physical address */
423
    swabls(&h->p_filesz);                /* Segment size in file */
424
    swabls(&h->p_memsz);                /* Segment size in memory */
425
    swab32s(&h->p_flags);                /* Segment flags */
426
    swabls(&h->p_align);                /* Segment alignment */
427
}
428

    
429
void elf_swap_rel(ELF_RELOC *rel)
430
{
431
    swabls(&rel->r_offset);
432
    swabls(&rel->r_info);
433
#ifdef ELF_USES_RELOCA
434
    swablss(&rel->r_addend);
435
#endif
436
}
437

    
438
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
439
                                  const char *name)
440
{
441
    int i;
442
    const char *shname;
443
    struct elf_shdr *sec;
444

    
445
    for(i = 0; i < shnum; i++) {
446
        sec = &shdr[i];
447
        if (!sec->sh_name)
448
            continue;
449
        shname = shstr + sec->sh_name;
450
        if (!strcmp(shname, name))
451
            return sec;
452
    }
453
    return NULL;
454
}
455

    
456
int find_reloc(int sh_index)
457
{
458
    struct elf_shdr *sec;
459
    int i;
460

    
461
    for(i = 0; i < ehdr.e_shnum; i++) {
462
        sec = &shdr[i];
463
        if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
464
            return i;
465
    }
466
    return 0;
467
}
468

    
469
static host_ulong get_rel_offset(EXE_RELOC *rel)
470
{
471
    return rel->r_offset;
472
}
473

    
474
static char *get_rel_sym_name(EXE_RELOC *rel)
475
{
476
    return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
477
}
478

    
479
static char *get_sym_name(EXE_SYM *sym)
480
{
481
    return strtab + sym->st_name;
482
}
483

    
484
/* load an elf object file */
485
int load_object(const char *filename)
486
{
487
    int fd;
488
    struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
489
    int i, j;
490
    ElfW(Sym) *sym;
491
    char *shstr;
492
    ELF_RELOC *rel;
493

    
494
    fd = open(filename, O_RDONLY);
495
    if (fd < 0)
496
        error("can't open file '%s'", filename);
497

    
498
    /* Read ELF header.  */
499
    if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
500
        error("unable to read file header");
501

    
502
    /* Check ELF identification.  */
503
    if (ehdr.e_ident[EI_MAG0] != ELFMAG0
504
     || ehdr.e_ident[EI_MAG1] != ELFMAG1
505
     || ehdr.e_ident[EI_MAG2] != ELFMAG2
506
     || ehdr.e_ident[EI_MAG3] != ELFMAG3
507
     || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
508
        error("bad ELF header");
509
    }
510

    
511
    do_swap = elf_must_swap(&ehdr);
512
    if (do_swap)
513
        elf_swap_ehdr(&ehdr);
514
    if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
515
        error("Unsupported ELF class");
516
    if (ehdr.e_type != ET_REL)
517
        error("ELF object file expected");
518
    if (ehdr.e_version != EV_CURRENT)
519
        error("Invalid ELF version");
520
    if (!elf_check_arch(ehdr.e_machine))
521
        error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
522

    
523
    /* read section headers */
524
    shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
525
    if (do_swap) {
526
        for(i = 0; i < ehdr.e_shnum; i++) {
527
            elf_swap_shdr(&shdr[i]);
528
        }
529
    }
530

    
531
    /* read all section data */
532
    sdata = malloc(sizeof(void *) * ehdr.e_shnum);
533
    memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
534

    
535
    for(i = 0;i < ehdr.e_shnum; i++) {
536
        sec = &shdr[i];
537
        if (sec->sh_type != SHT_NOBITS)
538
            sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
539
    }
540

    
541
    sec = &shdr[ehdr.e_shstrndx];
542
    shstr = (char *)sdata[ehdr.e_shstrndx];
543

    
544
    /* swap relocations */
545
    for(i = 0; i < ehdr.e_shnum; i++) {
546
        sec = &shdr[i];
547
        if (sec->sh_type == SHT_RELOC) {
548
            nb_relocs = sec->sh_size / sec->sh_entsize;
549
            if (do_swap) {
550
                for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
551
                    elf_swap_rel(rel);
552
            }
553
        }
554
    }
555
    /* text section */
556

    
557
    text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
558
    if (!text_sec)
559
        error("could not find .text section");
560
    text_shndx = text_sec - shdr;
561
    text = sdata[text_shndx];
562

    
563
    /* find text relocations, if any */
564
    relocs = NULL;
565
    nb_relocs = 0;
566
    i = find_reloc(text_shndx);
567
    if (i != 0) {
568
        relocs = (ELF_RELOC *)sdata[i];
569
        nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
570
    }
571

    
572
    symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
573
    if (!symtab_sec)
574
        error("could not find .symtab section");
575
    strtab_sec = &shdr[symtab_sec->sh_link];
576

    
577
    symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
578
    strtab = (char *)sdata[symtab_sec->sh_link];
579

    
580
    nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
581
    if (do_swap) {
582
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
583
            swab32s(&sym->st_name);
584
            swabls(&sym->st_value);
585
            swabls(&sym->st_size);
586
            swab16s(&sym->st_shndx);
587
        }
588
    }
589
    close(fd);
590
    return 0;
591
}
592

    
593
#endif /* CONFIG_FORMAT_ELF */
594

    
595
#ifdef CONFIG_FORMAT_COFF
596

    
597
/* COFF file info */
598
struct external_scnhdr *shdr;
599
uint8_t **sdata;
600
struct external_filehdr fhdr;
601
struct external_syment *coff_symtab;
602
char *strtab;
603
int coff_text_shndx, coff_data_shndx;
604

    
605
int data_shndx;
606

    
607
#define STRTAB_SIZE 4
608

    
609
#define DIR32   0x06
610
#define DISP32  0x14
611

    
612
#define T_FUNCTION  0x20
613
#define C_EXTERNAL  2
614

    
615
void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
616
{
617
    char *q;
618
    int c, i, len;
619

    
620
    if (ext_sym->e.e.e_zeroes != 0) {
621
        q = sym->st_name;
622
        for(i = 0; i < 8; i++) {
623
            c = ext_sym->e.e_name[i];
624
            if (c == '\0')
625
                break;
626
            *q++ = c;
627
        }
628
        *q = '\0';
629
    } else {
630
        pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
631
    }
632

    
633
    /* now convert the name to a C name (suppress the leading '_') */
634
    if (sym->st_name[0] == '_') {
635
        len = strlen(sym->st_name);
636
        memmove(sym->st_name, sym->st_name + 1, len - 1);
637
        sym->st_name[len - 1] = '\0';
638
    }
639
}
640

    
641
char *name_for_dotdata(struct coff_rel *rel)
642
{
643
        int i;
644
        struct coff_sym *sym;
645
        uint32_t text_data;
646

    
647
        text_data = *(uint32_t *)(text + rel->r_offset);
648

    
649
        for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
650
                if (sym->st_syment->e_scnum == data_shndx &&
651
                    text_data >= sym->st_value &&
652
                    text_data < sym->st_value + sym->st_size) {
653

    
654
                    return sym->st_name;
655

    
656
                }
657
        }
658
        return NULL;
659
}
660

    
661
static char *get_sym_name(EXE_SYM *sym)
662
{
663
    return sym->st_name;
664
}
665

    
666
static char *get_rel_sym_name(EXE_RELOC *rel)
667
{
668
    char *name;
669
    name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
670
    if (!strcmp(name, ".data"))
671
        name = name_for_dotdata(rel);
672
    if (name[0] == '.')
673
        return NULL;
674
    return name;
675
}
676

    
677
static host_ulong get_rel_offset(EXE_RELOC *rel)
678
{
679
    return rel->r_offset;
680
}
681

    
682
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
683
{
684
    int i;
685
    const char *shname;
686
    struct external_scnhdr *sec;
687

    
688
    for(i = 0; i < shnum; i++) {
689
        sec = &shdr[i];
690
        if (!sec->s_name)
691
            continue;
692
        shname = sec->s_name;
693
        if (!strcmp(shname, name))
694
            return sec;
695
    }
696
    return NULL;
697
}
698

    
699
/* load a coff object file */
700
int load_object(const char *filename)
701
{
702
    int fd;
703
    struct external_scnhdr *sec, *text_sec, *data_sec;
704
    int i;
705
    struct external_syment *ext_sym;
706
    struct external_reloc *coff_relocs;
707
    struct external_reloc *ext_rel;
708
    uint32_t *n_strtab;
709
    EXE_SYM *sym;
710
    EXE_RELOC *rel;
711
    const char *p;
712
    int aux_size, j;
713

    
714
    fd = open(filename, O_RDONLY
715
#ifdef _WIN32
716
              | O_BINARY
717
#endif
718
              );
719
    if (fd < 0)
720
        error("can't open file '%s'", filename);
721

    
722
    /* Read COFF header.  */
723
    if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
724
        error("unable to read file header");
725

    
726
    /* Check COFF identification.  */
727
    if (fhdr.f_magic != I386MAGIC) {
728
        error("bad COFF header");
729
    }
730
    do_swap = 0;
731

    
732
    /* read section headers */
733
    shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
734

    
735
    /* read all section data */
736
    sdata = malloc(sizeof(void *) * fhdr.f_nscns);
737
    memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
738

    
739
    for(i = 0;i < fhdr.f_nscns; i++) {
740
        sec = &shdr[i];
741
        if (!strstart(sec->s_name,  ".bss", &p))
742
            sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
743
    }
744

    
745

    
746
    /* text section */
747
    text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
748
    if (!text_sec)
749
        error("could not find .text section");
750
    coff_text_shndx = text_sec - shdr;
751
    text = sdata[coff_text_shndx];
752

    
753
    /* data section */
754
    data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
755
    if (!data_sec)
756
        error("could not find .data section");
757
    coff_data_shndx = data_sec - shdr;
758

    
759
    coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
760
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
761
        for(i=0;i<8;i++)
762
            printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
763
        printf("\n");
764
    }
765

    
766

    
767
    n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
768
    strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
769

    
770
    nb_syms = fhdr.f_nsyms;
771

    
772
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
773
      if (strstart(ext_sym->e.e_name, ".text", NULL))
774
                  text_shndx = ext_sym->e_scnum;
775
          if (strstart(ext_sym->e.e_name, ".data", NULL))
776
                  data_shndx = ext_sym->e_scnum;
777
    }
778

    
779
        /* set coff symbol */
780
        symtab = malloc(sizeof(struct coff_sym) * nb_syms);
781

    
782
        for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
783
                memset(sym, 0, sizeof(*sym));
784
                sym->st_syment = ext_sym;
785
                sym_ent_name(ext_sym, sym);
786
                sym->st_value = ext_sym->e_value;
787

    
788
                aux_size = *(int8_t *)ext_sym->e_numaux;
789
                if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
790
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
791
                                if ((ext_sym + j)->e_scnum == text_shndx &&
792
                                        (ext_sym + j)->e_type == T_FUNCTION ){
793
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
794
                                        break;
795
                                } else if (j == nb_syms - i - 1) {
796
                                        sec = &shdr[coff_text_shndx];
797
                                        sym->st_size = sec->s_size - ext_sym->e_value;
798
                                        break;
799
                                }
800
                        }
801
                } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
802
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
803
                                if ((ext_sym + j)->e_scnum == data_shndx) {
804
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
805
                                        break;
806
                                } else if (j == nb_syms - i - 1) {
807
                                        sec = &shdr[coff_data_shndx];
808
                                        sym->st_size = sec->s_size - ext_sym->e_value;
809
                                        break;
810
                                }
811
                        }
812
                } else {
813
                        sym->st_size = 0;
814
                }
815

    
816
                sym->st_type = ext_sym->e_type;
817
                sym->st_shndx = ext_sym->e_scnum;
818
        }
819

    
820

    
821
    /* find text relocations, if any */
822
    sec = &shdr[coff_text_shndx];
823
    coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
824
    nb_relocs = sec->s_nreloc;
825

    
826
    /* set coff relocation */
827
    relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
828
    for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
829
         i++, ext_rel++, rel++) {
830
        memset(rel, 0, sizeof(*rel));
831
        rel->r_reloc = ext_rel;
832
        rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
833
        rel->r_type = *(uint16_t *)ext_rel->r_type;
834
    }
835
    return 0;
836
}
837

    
838
#endif /* CONFIG_FORMAT_COFF */
839

    
840
#ifdef CONFIG_FORMAT_MACH
841

    
842
/* File Header */
843
struct mach_header         mach_hdr;
844

    
845
/* commands */
846
struct segment_command         *segment = 0;
847
struct dysymtab_command *dysymtabcmd = 0;
848
struct symtab_command         *symtabcmd = 0;
849

    
850
/* section */
851
struct section         *section_hdr;
852
struct section *text_sec_hdr;
853
uint8_t         **sdata;
854

    
855
/* relocs */
856
struct relocation_info *relocs;
857

    
858
/* symbols */
859
EXE_SYM                        *symtab;
860
struct nlist         *symtab_std;
861
char                        *strtab;
862

    
863
/* indirect symbols */
864
uint32_t         *tocdylib;
865

    
866
/* Utility functions */
867

    
868
static inline char *find_str_by_index(int index)
869
{
870
    return strtab+index;
871
}
872

    
873
/* Used by dyngen common code */
874
static char *get_sym_name(EXE_SYM *sym)
875
{
876
        char *name = find_str_by_index(sym->n_un.n_strx);
877

    
878
        if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
879
                return "debug";
880

    
881
        if(!name)
882
                return name;
883
        if(name[0]=='_')
884
                return name + 1;
885
        else
886
                return name;
887
}
888

    
889
/* find a section index given its segname, sectname */
890
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
891
                                  const char *sectname)
892
{
893
    int i;
894
    struct section *sec = section_hdr;
895

    
896
    for(i = 0; i < shnum; i++, sec++) {
897
        if (!sec->segname || !sec->sectname)
898
            continue;
899
        if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
900
            return i;
901
    }
902
    return -1;
903
}
904

    
905
/* find a section header given its segname, sectname */
906
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
907
                                  const char *sectname)
908
{
909
    int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
910
        if(index == -1)
911
                return NULL;
912
        return section_hdr+index;
913
}
914

    
915

    
916
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
917
{
918
    struct scattered_relocation_info * scarel;
919

    
920
    if(R_SCATTERED & rel->r_address) {
921
        scarel = (struct scattered_relocation_info*)rel;
922
        if(scarel->r_type != PPC_RELOC_PAIR)
923
            error("fetch_next_pair_value: looking for a pair which was not found (1)");
924
        *value = scarel->r_value;
925
    } else {
926
                if(rel->r_type != PPC_RELOC_PAIR)
927
                        error("fetch_next_pair_value: looking for a pair which was not found (2)");
928
                *value = rel->r_address;
929
        }
930
}
931

    
932
/* find a sym name given its value, in a section number */
933
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
934
{
935
        int i, ret = -1;
936

    
937
        for( i = 0 ; i < nb_syms; i++ )
938
        {
939
            if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
940
                         (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
941
                {
942
                        if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
943
                                ret = i;
944
                }
945
        }
946
        if( ret < 0 ) {
947
                *offset = 0;
948
                return 0;
949
        } else {
950
                *offset = value - symtab[ret].st_value;
951
                return get_sym_name(&symtab[ret]);
952
        }
953
}
954

    
955
/*
956
 *  Find symbol name given a (virtual) address, and a section which is of type
957
 *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
958
 */
959
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
960
{
961
    unsigned int tocindex, symindex, size;
962
    const char *name = 0;
963

    
964
    /* Sanity check */
965
    if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
966
        return (char*)0;
967

    
968
        if( sec_hdr->flags & S_SYMBOL_STUBS ){
969
                size = sec_hdr->reserved2;
970
                if(size == 0)
971
                    error("size = 0");
972

    
973
        }
974
        else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
975
                    sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
976
                size = sizeof(unsigned long);
977
        else
978
                return 0;
979

    
980
    /* Compute our index in toc */
981
        tocindex = (address - sec_hdr->addr)/size;
982
        symindex = tocdylib[sec_hdr->reserved1 + tocindex];
983

    
984
        name = get_sym_name(&symtab[symindex]);
985

    
986
    return name;
987
}
988

    
989
static const char * find_reloc_name_given_its_address(int address)
990
{
991
    unsigned int i;
992
    for(i = 0; i < segment->nsects ; i++)
993
    {
994
        const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
995
        if((long)name != -1)
996
            return name;
997
    }
998
    return 0;
999
}
1000

    
1001
static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
1002
{
1003
        char * name = 0;
1004
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1005
        int sectnum = rel->r_symbolnum;
1006
        int sectoffset;
1007
        int other_half=0;
1008

    
1009
        /* init the slide value */
1010
        *sslide = 0;
1011

    
1012
        if(R_SCATTERED & rel->r_address)
1013
                return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1014

    
1015
        if(rel->r_extern)
1016
        {
1017
                /* ignore debug sym */
1018
                if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1019
                        return 0;
1020
                return get_sym_name(&symtab[rel->r_symbolnum]);
1021
        }
1022

    
1023
        /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1024
        sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1025

    
1026
        if(sectnum==0xffffff)
1027
                return 0;
1028

    
1029
        /* Sanity Check */
1030
        if(sectnum > segment->nsects)
1031
                error("sectnum > segment->nsects");
1032

    
1033
        switch(rel->r_type)
1034
        {
1035
                case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1036
                        break;
1037
                case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1038
                        break;
1039
                case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1040
                        break;
1041
                case PPC_RELOC_BR24:
1042
                        sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1043
                        if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1044
                        break;
1045
                default:
1046
                        error("switch(rel->type) not found");
1047
        }
1048

    
1049
        if(rel->r_pcrel)
1050
                sectoffset += rel->r_address;
1051

    
1052
        if (rel->r_type == PPC_RELOC_BR24)
1053
                name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1054

    
1055
        /* search it in the full symbol list, if not found */
1056
        if(!name)
1057
                name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1058

    
1059
        return name;
1060
}
1061

    
1062
/* Used by dyngen common code */
1063
static const char * get_rel_sym_name(EXE_RELOC * rel)
1064
{
1065
        int sslide;
1066
        return get_reloc_name( rel, &sslide);
1067
}
1068

    
1069
/* Used by dyngen common code */
1070
static host_ulong get_rel_offset(EXE_RELOC *rel)
1071
{
1072
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1073
    if(R_SCATTERED & rel->r_address)
1074
                return sca_rel->r_address;
1075
        else
1076
                return rel->r_address;
1077
}
1078

    
1079
/* load a mach-o object file */
1080
int load_object(const char *filename)
1081
{
1082
        int fd;
1083
        unsigned int offset_to_segment = 0;
1084
    unsigned int offset_to_dysymtab = 0;
1085
    unsigned int offset_to_symtab = 0;
1086
    struct load_command lc;
1087
    unsigned int i, j;
1088
        EXE_SYM *sym;
1089
        struct nlist *syment;
1090

    
1091
        fd = open(filename, O_RDONLY);
1092
    if (fd < 0)
1093
        error("can't open file '%s'", filename);
1094

    
1095
    /* Read Mach header.  */
1096
    if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1097
        error("unable to read file header");
1098

    
1099
    /* Check Mach identification.  */
1100
    if (!check_mach_header(mach_hdr)) {
1101
        error("bad Mach header");
1102
    }
1103

    
1104
    if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1105
        error("Unsupported CPU");
1106

    
1107
    if (mach_hdr.filetype != MH_OBJECT)
1108
        error("Unsupported Mach Object");
1109

    
1110
    /* read segment headers */
1111
    for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1112
    {
1113
        if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1114
            error("unable to read load_command");
1115
        if(lc.cmd == LC_SEGMENT)
1116
        {
1117
            offset_to_segment = j;
1118
            lseek(fd, offset_to_segment, SEEK_SET);
1119
            segment = malloc(sizeof(struct segment_command));
1120
            if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1121
                error("unable to read LC_SEGMENT");
1122
        }
1123
        if(lc.cmd == LC_DYSYMTAB)
1124
        {
1125
            offset_to_dysymtab = j;
1126
            lseek(fd, offset_to_dysymtab, SEEK_SET);
1127
            dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1128
            if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1129
                error("unable to read LC_DYSYMTAB");
1130
        }
1131
        if(lc.cmd == LC_SYMTAB)
1132
        {
1133
            offset_to_symtab = j;
1134
            lseek(fd, offset_to_symtab, SEEK_SET);
1135
            symtabcmd = malloc(sizeof(struct symtab_command));
1136
            if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1137
                error("unable to read LC_SYMTAB");
1138
        }
1139
        j+=lc.cmdsize;
1140

    
1141
        lseek(fd, j, SEEK_SET);
1142
    }
1143

    
1144
    if(!segment)
1145
        error("unable to find LC_SEGMENT");
1146

    
1147
    /* read section headers */
1148
    section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1149

    
1150
    /* read all section data */
1151
    sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1152
    memset(sdata, 0, sizeof(void *) * segment->nsects);
1153

    
1154
        /* Load the data in section data */
1155
        for(i = 0; i < segment->nsects; i++) {
1156
        sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1157
    }
1158

    
1159
    /* text section */
1160
        text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1161
        i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1162
        if (i == -1 || !text_sec_hdr)
1163
        error("could not find __TEXT,__text section");
1164
    text = sdata[i];
1165

    
1166
    /* Make sure dysym was loaded */
1167
    if(!(int)dysymtabcmd)
1168
        error("could not find __DYSYMTAB segment");
1169

    
1170
    /* read the table of content of the indirect sym */
1171
    tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1172

    
1173
    /* Make sure symtab was loaded  */
1174
    if(!(int)symtabcmd)
1175
        error("could not find __SYMTAB segment");
1176
    nb_syms = symtabcmd->nsyms;
1177

    
1178
    symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1179
    strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1180

    
1181
        symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1182

    
1183
        /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1184
        for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1185
        struct nlist *sym_follow, *sym_next = 0;
1186
        unsigned int j;
1187
                memset(sym, 0, sizeof(*sym));
1188

    
1189
                if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1190
            continue;
1191

    
1192
                memcpy(sym, syment, sizeof(*syment));
1193

    
1194
                /* Find the following symbol in order to get the current symbol size */
1195
        for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1196
            if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1197
                continue;
1198
            if(!sym_next) {
1199
                sym_next = sym_follow;
1200
                continue;
1201
            }
1202
            if(!(sym_next->n_value > sym_follow->n_value))
1203
                continue;
1204
            sym_next = sym_follow;
1205
        }
1206
                if(sym_next)
1207
            sym->st_size = sym_next->n_value - sym->st_value;
1208
                else
1209
            sym->st_size = text_sec_hdr->size - sym->st_value;
1210
        }
1211

    
1212
    /* Find Reloc */
1213
    relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1214
    nb_relocs = text_sec_hdr->nreloc;
1215

    
1216
        close(fd);
1217
        return 0;
1218
}
1219

    
1220
#endif /* CONFIG_FORMAT_MACH */
1221

    
1222
/* return true if the expression is a label reference */
1223
int get_reloc_expr(char *name, int name_size, const char *sym_name)
1224
{
1225
    const char *p;
1226

    
1227
    if (strstart(sym_name, "__op_param", &p)) {
1228
        snprintf(name, name_size, "param%s", p);
1229
    } else if (strstart(sym_name, "__op_gen_label", &p)) {
1230
        snprintf(name, name_size, "param%s", p);
1231
        return 1;
1232
    } else {
1233
#if defined(HOST_SPARC) || defined(HOST_HPPA)
1234
        if (sym_name[0] == '.')
1235
            snprintf(name, name_size,
1236
                     "(long)(&__dot_%s)",
1237
                     sym_name + 1);
1238
        else
1239
#endif
1240
            snprintf(name, name_size, "(long)(&%s)", sym_name);
1241
    }
1242
    return 0;
1243
}
1244

    
1245
#ifdef HOST_IA64
1246

    
1247
#define PLT_ENTRY_SIZE        16        /* 1 bundle containing "brl" */
1248

    
1249
struct plt_entry {
1250
    struct plt_entry *next;
1251
    const char *name;
1252
    unsigned long addend;
1253
} *plt_list;
1254

    
1255
static int
1256
get_plt_index (const char *name, unsigned long addend)
1257
{
1258
    struct plt_entry *plt, *prev= NULL;
1259
    int index = 0;
1260

    
1261
    /* see if we already have an entry for this target: */
1262
    for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1263
        if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1264
            return index;
1265

    
1266
    /* nope; create a new PLT entry: */
1267

    
1268
    plt = malloc(sizeof(*plt));
1269
    if (!plt) {
1270
        perror("malloc");
1271
        exit(1);
1272
    }
1273
    memset(plt, 0, sizeof(*plt));
1274
    plt->name = strdup(name);
1275
    plt->addend = addend;
1276

    
1277
    /* append to plt-list: */
1278
    if (prev)
1279
        prev->next = plt;
1280
    else
1281
        plt_list = plt;
1282
    return index;
1283
}
1284

    
1285
#endif
1286

    
1287
#ifdef HOST_ARM
1288

    
1289
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1290
                      FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1291
                      ELF_RELOC *relocs, int nb_relocs)
1292
{
1293
    uint8_t *p;
1294
    uint32_t insn;
1295
    int offset, min_offset, pc_offset, data_size, spare, max_pool;
1296
    uint8_t data_allocated[1024];
1297
    unsigned int data_index;
1298
    int type;
1299

    
1300
    memset(data_allocated, 0, sizeof(data_allocated));
1301

    
1302
    p = p_start;
1303
    min_offset = p_end - p_start;
1304
    spare = 0x7fffffff;
1305
    while (p < p_start + min_offset) {
1306
        insn = get32((uint32_t *)p);
1307
        /* TODO: Armv5e ldrd.  */
1308
        /* TODO: VFP load.  */
1309
        if ((insn & 0x0d5f0000) == 0x051f0000) {
1310
            /* ldr reg, [pc, #im] */
1311
            offset = insn & 0xfff;
1312
            if (!(insn & 0x00800000))
1313
                offset = -offset;
1314
            max_pool = 4096;
1315
            type = 0;
1316
        } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1317
            /* FPA ldf.  */
1318
            offset = (insn & 0xff) << 2;
1319
            if (!(insn & 0x00800000))
1320
                offset = -offset;
1321
            max_pool = 1024;
1322
            type = 1;
1323
        } else if ((insn & 0x0fff0000) == 0x028f0000) {
1324
            /* Some gcc load a doubleword immediate with
1325
               add regN, pc, #imm
1326
               ldmia regN, {regN, regM}
1327
               Hope and pray the compiler never generates somethin like
1328
               add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1329
            int r;
1330

    
1331
            r = (insn & 0xf00) >> 7;
1332
            offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1333
            max_pool = 1024;
1334
            type = 2;
1335
        } else {
1336
            max_pool = 0;
1337
            type = -1;
1338
        }
1339
        if (type >= 0) {
1340
            /* PC-relative load needs fixing up.  */
1341
            if (spare > max_pool - offset)
1342
                spare = max_pool - offset;
1343
            if ((offset & 3) !=0)
1344
                error("%s:%04x: pc offset must be 32 bit aligned",
1345
                      name, start_offset + p - p_start);
1346
            if (offset < 0)
1347
                error("%s:%04x: Embedded literal value",
1348
                      name, start_offset + p - p_start);
1349
            pc_offset = p - p_start + offset + 8;
1350
            if (pc_offset <= (p - p_start) ||
1351
                pc_offset >= (p_end - p_start))
1352
                error("%s:%04x: pc offset must point inside the function code",
1353
                      name, start_offset + p - p_start);
1354
            if (pc_offset < min_offset)
1355
                min_offset = pc_offset;
1356
            if (outfile) {
1357
                /* The intruction position */
1358
                fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1359
                        p - p_start);
1360
                /* The position of the constant pool data.  */
1361
                data_index = ((p_end - p_start) - pc_offset) >> 2;
1362
                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1363
                        data_index);
1364
                fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
1365
                fprintf(outfile, "    arm_ldr_ptr++;\n");
1366
            }
1367
        }
1368
        p += 4;
1369
    }
1370

    
1371
    /* Copy and relocate the constant pool data.  */
1372
    data_size = (p_end - p_start) - min_offset;
1373
    if (data_size > 0 && outfile) {
1374
        spare += min_offset;
1375
        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1376
        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1377
        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1378
                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
1379
                         spare, spare);
1380

    
1381
        data_index = 0;
1382
        for (pc_offset = min_offset;
1383
             pc_offset < p_end - p_start;
1384
             pc_offset += 4) {
1385

    
1386
            ELF_RELOC *rel;
1387
            int i, addend, type;
1388
            const char *sym_name;
1389
            char relname[1024];
1390

    
1391
            /* data value */
1392
            addend = get32((uint32_t *)(p_start + pc_offset));
1393
            relname[0] = '\0';
1394
            for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1395
                if (rel->r_offset == (pc_offset + start_offset)) {
1396
                    sym_name = get_rel_sym_name(rel);
1397
                    /* the compiler leave some unnecessary references to the code */
1398
                    get_reloc_expr(relname, sizeof(relname), sym_name);
1399
                    type = ELF32_R_TYPE(rel->r_info);
1400
                    if (type != R_ARM_ABS32)
1401
                        error("%s: unsupported data relocation", name);
1402
                    break;
1403
                }
1404
            }
1405
            fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1406
                    data_index, addend);
1407
            if (relname[0] != '\0')
1408
                fprintf(outfile, " + %s", relname);
1409
            fprintf(outfile, ";\n");
1410

    
1411
            data_index++;
1412
        }
1413
    }
1414

    
1415
    if (p == p_start)
1416
        goto arm_ret_error;
1417
    p -= 4;
1418
    insn = get32((uint32_t *)p);
1419
    /* The last instruction must be an ldm instruction.  There are several
1420
       forms generated by gcc:
1421
        ldmib sp, {..., pc}  (implies a sp adjustment of +4)
1422
        ldmia sp, {..., pc}
1423
        ldmea fp, {..., pc} */
1424
    if ((insn & 0xffff8000) == 0xe99d8000) {
1425
        if (outfile) {
1426
            fprintf(outfile,
1427
                    "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1428
                    p - p_start);
1429
        }
1430
        p += 4;
1431
    } else if ((insn & 0xffff8000) != 0xe89d8000
1432
        && (insn & 0xffff8000) != 0xe91b8000) {
1433
    arm_ret_error:
1434
        if (!outfile)
1435
            printf("%s: invalid epilog\n", name);
1436
    }
1437
    return p - p_start;
1438
}
1439
#endif
1440

    
1441

    
1442
#define MAX_ARGS 3
1443

    
1444
/* generate op code */
1445
void gen_code(const char *name, host_ulong offset, host_ulong size,
1446
              FILE *outfile, int gen_switch)
1447
{
1448
    int copy_size = 0;
1449
    uint8_t *p_start, *p_end;
1450
    host_ulong start_offset;
1451
    int nb_args, i, n;
1452
    uint8_t args_present[MAX_ARGS];
1453
    const char *sym_name, *p;
1454
    EXE_RELOC *rel;
1455

    
1456
    /* Compute exact size excluding prologue and epilogue instructions.
1457
     * Increment start_offset to skip epilogue instructions, then compute
1458
     * copy_size the indicate the size of the remaining instructions (in
1459
     * bytes).
1460
     */
1461
    p_start = text + offset;
1462
    p_end = p_start + size;
1463
    start_offset = offset;
1464
#if defined(HOST_I386) || defined(HOST_X86_64)
1465
#ifdef CONFIG_FORMAT_COFF
1466
    {
1467
        uint8_t *p;
1468
        p = p_end - 1;
1469
        if (p == p_start)
1470
            error("empty code for %s", name);
1471
        while (*p != 0xc3) {
1472
            p--;
1473
            if (p <= p_start)
1474
                error("ret or jmp expected at the end of %s", name);
1475
        }
1476
        copy_size = p - p_start;
1477
    }
1478
#else
1479
    {
1480
        int len;
1481
        len = p_end - p_start;
1482
        if (len == 0)
1483
            error("empty code for %s", name);
1484
        if (p_end[-1] == 0xc3) {
1485
            len--;
1486
        } else {
1487
            error("ret or jmp expected at the end of %s", name);
1488
        }
1489
        copy_size = len;
1490
    }
1491
#endif
1492
#elif defined(HOST_PPC)
1493
    {
1494
        uint8_t *p;
1495
        p = (void *)(p_end - 4);
1496
        if (p == p_start)
1497
            error("empty code for %s", name);
1498
        if (get32((uint32_t *)p) != 0x4e800020)
1499
            error("blr expected at the end of %s", name);
1500
        copy_size = p - p_start;
1501
    }
1502
#elif defined(HOST_S390)
1503
    {
1504
        uint8_t *p;
1505
        p = (void *)(p_end - 2);
1506
        if (p == p_start)
1507
            error("empty code for %s", name);
1508
        if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1509
            error("br expected at the end of %s", name);
1510
        copy_size = p - p_start;
1511
    }
1512
#elif defined(HOST_ALPHA)
1513
    {
1514
        uint8_t *p;
1515
        p = p_end - 4;
1516
#if 0
1517
        /* XXX: check why it occurs */
1518
        if (p == p_start)
1519
            error("empty code for %s", name);
1520
#endif
1521
        if (get32((uint32_t *)p) != 0x6bfa8001)
1522
            error("ret expected at the end of %s", name);
1523
        copy_size = p - p_start;
1524
    }
1525
#elif defined(HOST_IA64)
1526
    {
1527
        uint8_t *p;
1528
        p = (void *)(p_end - 4);
1529
        if (p == p_start)
1530
            error("empty code for %s", name);
1531
        /* br.ret.sptk.many b0;; */
1532
        /* 08 00 84 00 */
1533
        if (get32((uint32_t *)p) != 0x00840008)
1534
            error("br.ret.sptk.many b0;; expected at the end of %s", name);
1535
        copy_size = p_end - p_start;
1536
    }
1537
#elif defined(HOST_SPARC)
1538
    {
1539
#define INSN_SAVE       0x9de3a000
1540
#define INSN_RET        0x81c7e008
1541
#define INSN_RETL       0x81c3e008
1542
#define INSN_RESTORE    0x81e80000
1543
#define INSN_RETURN     0x81cfe008
1544
#define INSN_NOP        0x01000000
1545
#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1546
#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1547

    
1548
        uint32_t start_insn, end_insn1, end_insn2;
1549
        uint8_t *p;
1550
        p = (void *)(p_end - 8);
1551
        if (p <= p_start)
1552
            error("empty code for %s", name);
1553
        start_insn = get32((uint32_t *)(p_start + 0x0));
1554
        end_insn1 = get32((uint32_t *)(p + 0x0));
1555
        end_insn2 = get32((uint32_t *)(p + 0x4));
1556
        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1557
            (start_insn & ~0x1fff) == INSN_ADD_SP) {
1558
            p_start += 0x4;
1559
            start_offset += 0x4;
1560
            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1561
                /* SPARC v7: ret; restore; */ ;
1562
            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1563
                /* SPARC v9: return; nop; */ ;
1564
            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1565
                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1566
            else
1567

    
1568
                error("ret; restore; not found at end of %s", name);
1569
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1570
            ;
1571
        } else {
1572
            error("No save at the beginning of %s", name);
1573
        }
1574
#if 0
1575
        /* Skip a preceeding nop, if present.  */
1576
        if (p > p_start) {
1577
            skip_insn = get32((uint32_t *)(p - 0x4));
1578
            if (skip_insn == INSN_NOP)
1579
                p -= 4;
1580
        }
1581
#endif
1582
        copy_size = p - p_start;
1583
    }
1584
#elif defined(HOST_SPARC64)
1585
    {
1586
#define INSN_SAVE       0x9de3a000
1587
#define INSN_RET        0x81c7e008
1588
#define INSN_RETL       0x81c3e008
1589
#define INSN_RESTORE    0x81e80000
1590
#define INSN_RETURN     0x81cfe008
1591
#define INSN_NOP        0x01000000
1592
#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1593
#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1594

    
1595
        uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1596
        uint8_t *p;
1597
        p = (void *)(p_end - 8);
1598
#if 0
1599
        /* XXX: check why it occurs */
1600
        if (p <= p_start)
1601
            error("empty code for %s", name);
1602
#endif
1603
        start_insn = get32((uint32_t *)(p_start + 0x0));
1604
        end_insn1 = get32((uint32_t *)(p + 0x0));
1605
        end_insn2 = get32((uint32_t *)(p + 0x4));
1606
        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1607
            (start_insn & ~0x1fff) == INSN_ADD_SP) {
1608
            p_start += 0x4;
1609
            start_offset += 0x4;
1610
            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1611
                /* SPARC v7: ret; restore; */ ;
1612
            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1613
                /* SPARC v9: return; nop; */ ;
1614
            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1615
                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1616
            else
1617

    
1618
                error("ret; restore; not found at end of %s", name);
1619
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1620
            ;
1621
        } else {
1622
            error("No save at the beginning of %s", name);
1623
        }
1624

    
1625
#if 0
1626
        /* Skip a preceeding nop, if present.  */
1627
        if (p > p_start) {
1628
            skip_insn = get32((uint32_t *)(p - 0x4));
1629
            if (skip_insn == 0x01000000)
1630
                p -= 4;
1631
        }
1632
#endif
1633

    
1634
        copy_size = p - p_start;
1635
    }
1636
#elif defined(HOST_ARM)
1637
    {
1638
        uint32_t insn;
1639

    
1640
        if ((p_end - p_start) <= 16)
1641
            error("%s: function too small", name);
1642
        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1643
            (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1644
            get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1645
            error("%s: invalid prolog", name);
1646
        p_start += 12;
1647
        start_offset += 12;
1648
        insn = get32((uint32_t *)p_start);
1649
        if ((insn & 0xffffff00) == 0xe24dd000) {
1650
            /* Stack adjustment.  Assume op uses the frame pointer.  */
1651
            p_start -= 4;
1652
            start_offset -= 4;
1653
        }
1654
        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1655
                                      relocs, nb_relocs);
1656
    }
1657
#elif defined(HOST_M68K)
1658
    {
1659
        uint8_t *p;
1660
        p = (void *)(p_end - 2);
1661
        if (p == p_start)
1662
            error("empty code for %s", name);
1663
        // remove NOP's, probably added for alignment
1664
        while ((get16((uint16_t *)p) == 0x4e71) &&
1665
               (p>p_start))
1666
            p -= 2;
1667
        if (get16((uint16_t *)p) != 0x4e75)
1668
            error("rts expected at the end of %s", name);
1669
        copy_size = p - p_start;
1670
    }
1671
#elif defined(HOST_HPPA)
1672
    {
1673
        uint8_t *p;
1674
        p = p_start;
1675
        while (p < p_end) {
1676
            uint32_t insn = get32((uint32_t *)p);
1677
            if (insn == 0x6bc23fd9 ||                /* stw rp,-14(sp) */
1678
                insn == 0x08030241 ||                /* copy r3,r1 */
1679
                insn == 0x081e0243 ||                /* copy sp,r3 */
1680
                (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1681
                (insn & 0xffffc000) == 0x6fc10000)   /* stwm r1,x(sp) */
1682
                p += 4;
1683
            else
1684
                break;
1685
        }
1686
        start_offset += p - p_start;
1687
        p_start = p;
1688
        p = p_end - 4;
1689

    
1690
        while (p > p_start) {
1691
            uint32_t insn = get32((uint32_t *)p);
1692
            if ((insn & 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */
1693
                (insn & 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */
1694
                (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1695
                insn == 0x48623fd9 ||                /* ldw -14(r3),rp */
1696
                insn == 0xe840c000 ||                /* bv r0(rp) */
1697
                insn == 0xe840c002)                  /* bv,n r0(rp) */
1698
                p -= 4;
1699
            else
1700
                break;
1701
        }
1702
        p += 4;
1703
        if (p <= p_start)
1704
            error("empty code for %s", name);
1705

    
1706
        copy_size = p - p_start;
1707
    }
1708
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1709
    {
1710
#define INSN_RETURN     0x03e00008
1711
#define INSN_NOP        0x00000000
1712

    
1713
        uint8_t *p = p_end;
1714

    
1715
        if (p < (p_start + 0x8)) {
1716
            error("empty code for %s", name);
1717
        } else {
1718
            uint32_t end_insn1, end_insn2;
1719

    
1720
            p -= 0x8;
1721
            end_insn1 = get32((uint32_t *)(p + 0x0));
1722
            end_insn2 = get32((uint32_t *)(p + 0x4));
1723
            if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1724
                error("jr ra not found at end of %s", name);
1725
        }
1726
        copy_size = p - p_start;
1727
    }
1728
#else
1729
#error unsupported CPU
1730
#endif
1731

    
1732
    /* compute the number of arguments by looking at the relocations */
1733
    for(i = 0;i < MAX_ARGS; i++)
1734
        args_present[i] = 0;
1735

    
1736
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1737
        host_ulong offset = get_rel_offset(rel);
1738
        if (offset >= start_offset &&
1739
            offset < start_offset + (p_end - p_start)) {
1740
            sym_name = get_rel_sym_name(rel);
1741
            if(!sym_name)
1742
                continue;
1743
            if (strstart(sym_name, "__op_param", &p) ||
1744
                strstart(sym_name, "__op_gen_label", &p)) {
1745
                n = strtoul(p, NULL, 10);
1746
                if (n > MAX_ARGS)
1747
                    error("too many arguments in %s", name);
1748
                args_present[n - 1] = 1;
1749
            }
1750
        }
1751
    }
1752

    
1753
    nb_args = 0;
1754
    while (nb_args < MAX_ARGS && args_present[nb_args])
1755
        nb_args++;
1756
    for(i = nb_args; i < MAX_ARGS; i++) {
1757
        if (args_present[i])
1758
            error("inconsistent argument numbering in %s", name);
1759
    }
1760

    
1761
    if (gen_switch == 2) {
1762
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1763
    } else if (gen_switch == 1) {
1764

    
1765
        /* output C code */
1766
        fprintf(outfile, "case INDEX_%s: {\n", name);
1767
        if (nb_args > 0) {
1768
            fprintf(outfile, "    long ");
1769
            for(i = 0; i < nb_args; i++) {
1770
                if (i != 0)
1771
                    fprintf(outfile, ", ");
1772
                fprintf(outfile, "param%d", i + 1);
1773
            }
1774
            fprintf(outfile, ";\n");
1775
        }
1776
#if defined(HOST_IA64)
1777
        fprintf(outfile, "    extern char %s;\n", name);
1778
#else
1779
        fprintf(outfile, "    extern void %s();\n", name);
1780
#endif
1781

    
1782
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1783
            host_ulong offset = get_rel_offset(rel);
1784
            if (offset >= start_offset &&
1785
                offset < start_offset + (p_end - p_start)) {
1786
                sym_name = get_rel_sym_name(rel);
1787
                if(!sym_name)
1788
                    continue;
1789
                if (*sym_name &&
1790
                    !strstart(sym_name, "__op_param", NULL) &&
1791
                    !strstart(sym_name, "__op_jmp", NULL) &&
1792
                    !strstart(sym_name, "__op_gen_label", NULL)) {
1793
#if defined(HOST_SPARC) || defined(HOST_HPPA)
1794
                    if (sym_name[0] == '.') {
1795
                        fprintf(outfile,
1796
                                "extern char __dot_%s __asm__(\"%s\");\n",
1797
                                sym_name+1, sym_name);
1798
                        continue;
1799
                    }
1800
#endif
1801
#if defined(__APPLE__)
1802
                    /* Set __attribute((unused)) on darwin because we
1803
                       want to avoid warning when we don't use the symbol.  */
1804
                    fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1805
#elif defined(HOST_IA64)
1806
                        if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1807
                                /*
1808
                                 * PCREL21 br.call targets generally
1809
                                 * are out of range and need to go
1810
                                 * through an "import stub".
1811
                                 */
1812
                                fprintf(outfile, "    extern char %s;\n",
1813
                                        sym_name);
1814
#else
1815
                    fprintf(outfile, "extern char %s;\n", sym_name);
1816
#endif
1817
                }
1818
            }
1819
        }
1820

    
1821
#ifdef __hppa__
1822
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1823
                                        name, (int)(start_offset - offset), copy_size);
1824
#else
1825
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1826
                                        name, (int)(start_offset - offset), copy_size);
1827
#endif
1828

    
1829
        /* emit code offset information */
1830
        {
1831
            EXE_SYM *sym;
1832
            const char *sym_name, *p;
1833
            host_ulong val;
1834
            int n;
1835

    
1836
            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1837
                sym_name = get_sym_name(sym);
1838
                if (strstart(sym_name, "__op_label", &p)) {
1839
                    uint8_t *ptr;
1840
                    unsigned long offset;
1841

    
1842
                    /* test if the variable refers to a label inside
1843
                       the code we are generating */
1844
#ifdef CONFIG_FORMAT_COFF
1845
                    if (sym->st_shndx == text_shndx) {
1846
                        ptr = sdata[coff_text_shndx];
1847
                    } else if (sym->st_shndx == data_shndx) {
1848
                        ptr = sdata[coff_data_shndx];
1849
                    } else {
1850
                        ptr = NULL;
1851
                    }
1852
#elif defined(CONFIG_FORMAT_MACH)
1853
                    if(!sym->n_sect)
1854
                        continue;
1855
                    ptr = sdata[sym->n_sect-1];
1856
#else
1857
                    ptr = sdata[sym->st_shndx];
1858
#endif
1859
                    if (!ptr)
1860
                        error("__op_labelN in invalid section");
1861
                    offset = sym->st_value;
1862
#ifdef CONFIG_FORMAT_MACH
1863
                    offset -= section_hdr[sym->n_sect-1].addr;
1864
#endif
1865
                    val = *(host_ulong *)(ptr + offset);
1866
#ifdef ELF_USES_RELOCA
1867
                    {
1868
                        int reloc_shndx, nb_relocs1, j;
1869

    
1870
                        /* try to find a matching relocation */
1871
                        reloc_shndx = find_reloc(sym->st_shndx);
1872
                        if (reloc_shndx) {
1873
                            nb_relocs1 = shdr[reloc_shndx].sh_size /
1874
                                shdr[reloc_shndx].sh_entsize;
1875
                            rel = (ELF_RELOC *)sdata[reloc_shndx];
1876
                            for(j = 0; j < nb_relocs1; j++) {
1877
                                if (rel->r_offset == offset) {
1878
                                    val = rel->r_addend;
1879
                                    break;
1880
                                }
1881
                                rel++;
1882
                            }
1883
                        }
1884
                    }
1885
#endif
1886
                    if (val >= start_offset && val <= start_offset + copy_size) {
1887
                        n = strtol(p, NULL, 10);
1888
                        fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1889
                    }
1890
                }
1891
            }
1892
        }
1893

    
1894
        /* load parameters in variables */
1895
        for(i = 0; i < nb_args; i++) {
1896
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1897
        }
1898

    
1899
        /* patch relocations */
1900
#if defined(HOST_I386)
1901
            {
1902
                char relname[256];
1903
                int type, is_label;
1904
                int addend;
1905
                int reloc_offset;
1906
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1907
                if (rel->r_offset >= start_offset &&
1908
                    rel->r_offset < start_offset + copy_size) {
1909
                    sym_name = get_rel_sym_name(rel);
1910
                    if (!sym_name)
1911
                        continue;
1912
                    reloc_offset = rel->r_offset - start_offset;
1913
                    if (strstart(sym_name, "__op_jmp", &p)) {
1914
                        int n;
1915
                        n = strtol(p, NULL, 10);
1916
                        /* __op_jmp relocations are done at
1917
                           runtime to do translated block
1918
                           chaining: the offset of the instruction
1919
                           needs to be stored */
1920
                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1921
                                n, reloc_offset);
1922
                        continue;
1923
                    }
1924

    
1925
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1926
                    addend = get32((uint32_t *)(text + rel->r_offset));
1927
#ifdef CONFIG_FORMAT_ELF
1928
                    type = ELF32_R_TYPE(rel->r_info);
1929
                    if (is_label) {
1930
                        switch(type) {
1931
                        case R_386_32:
1932
                        case R_386_PC32:
1933
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1934
                                    reloc_offset, type, relname, addend);
1935
                            break;
1936
                        default:
1937
                            error("unsupported i386 relocation (%d)", type);
1938
                        }
1939
                    } else {
1940
                        switch(type) {
1941
                        case R_386_32:
1942
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1943
                                    reloc_offset, relname, addend);
1944
                            break;
1945
                        case R_386_PC32:
1946
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1947
                                    reloc_offset, relname, reloc_offset, addend);
1948
                            break;
1949
                        default:
1950
                            error("unsupported i386 relocation (%d)", type);
1951
                        }
1952
                    }
1953
#elif defined(CONFIG_FORMAT_COFF)
1954
                    {
1955
                        char *temp_name;
1956
                        int j;
1957
                        EXE_SYM *sym;
1958
                        temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1959
                        if (!strcmp(temp_name, ".data")) {
1960
                            for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1961
                                if (strstart(sym->st_name, sym_name, NULL)) {
1962
                                    addend -= sym->st_value;
1963
                                }
1964
                            }
1965
                        }
1966
                    }
1967
                    type = rel->r_type;
1968
                    if (is_label) {
1969
/* TCG uses elf relocation constants */
1970
#define R_386_32        1
1971
#define R_386_PC32        2
1972
                        switch(type) {
1973
                        case DIR32:
1974
                            type = R_386_32;
1975
                            goto do_reloc;
1976
                        case DISP32:
1977
                            type = R_386_PC32;
1978
                            addend -= 4;
1979
                        do_reloc:
1980
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1981
                                    reloc_offset, type, relname, addend);
1982
                            break;
1983
                        default:
1984
                            error("unsupported i386 relocation (%d)", type);
1985
                        }
1986
                    } else {
1987
                        switch(type) {
1988
                        case DIR32:
1989
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1990
                                    reloc_offset, relname, addend);
1991
                            break;
1992
                        case DISP32:
1993
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1994
                                    reloc_offset, relname, reloc_offset, addend);
1995
                            break;
1996
                        default:
1997
                            error("unsupported i386 relocation (%d)", type);
1998
                        }
1999
                    }
2000
#else
2001
#error unsupport object format
2002
#endif
2003
                }
2004
                }
2005
            }
2006
#elif defined(HOST_X86_64)
2007
            {
2008
                char relname[256];
2009
                int type, is_label;
2010
                int addend;
2011
                int reloc_offset;
2012
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2013
                if (rel->r_offset >= start_offset &&
2014
                    rel->r_offset < start_offset + copy_size) {
2015
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2016
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2017
                    type = ELF32_R_TYPE(rel->r_info);
2018
                    addend = rel->r_addend;
2019
                    reloc_offset = rel->r_offset - start_offset;
2020
                    if (is_label) {
2021
                        switch(type) {
2022
                        case R_X86_64_32:
2023
                        case R_X86_64_32S:
2024
                        case R_X86_64_PC32:
2025
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2026
                                    reloc_offset, type, relname, addend);
2027
                            break;
2028
                        default:
2029
                            error("unsupported X86_64 relocation (%d)", type);
2030
                        }
2031
                    } else {
2032
                        switch(type) {
2033
                        case R_X86_64_32:
2034
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2035
                                    reloc_offset, relname, addend);
2036
                            break;
2037
                        case R_X86_64_32S:
2038
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2039
                                    reloc_offset, relname, addend);
2040
                            break;
2041
                        case R_X86_64_PC32:
2042
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2043
                                    reloc_offset, relname, reloc_offset, addend);
2044
                            break;
2045
                        default:
2046
                            error("unsupported X86_64 relocation (%d)", type);
2047
                        }
2048
                    }
2049
                }
2050
                }
2051
            }
2052
#elif defined(HOST_PPC)
2053
            {
2054
#ifdef CONFIG_FORMAT_ELF
2055
                char relname[256];
2056
                int type;
2057
                int addend;
2058
                int reloc_offset;
2059
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2060
                    if (rel->r_offset >= start_offset &&
2061
                        rel->r_offset < start_offset + copy_size) {
2062
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2063
                        reloc_offset = rel->r_offset - start_offset;
2064
                        if (strstart(sym_name, "__op_jmp", &p)) {
2065
                            int n;
2066
                            n = strtol(p, NULL, 10);
2067
                            /* __op_jmp relocations are done at
2068
                               runtime to do translated block
2069
                               chaining: the offset of the instruction
2070
                               needs to be stored */
2071
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2072
                                    n, reloc_offset);
2073
                            continue;
2074
                        }
2075

    
2076
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2077
                        type = ELF32_R_TYPE(rel->r_info);
2078
                        addend = rel->r_addend;
2079
                        switch(type) {
2080
                        case R_PPC_ADDR32:
2081
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2082
                                    reloc_offset, relname, addend);
2083
                            break;
2084
                        case R_PPC_ADDR16_LO:
2085
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2086
                                    reloc_offset, relname, addend);
2087
                            break;
2088
                        case R_PPC_ADDR16_HI:
2089
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2090
                                    reloc_offset, relname, addend);
2091
                            break;
2092
                        case R_PPC_ADDR16_HA:
2093
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2094
                                    reloc_offset, relname, addend);
2095
                            break;
2096
                        case R_PPC_REL24:
2097
                            /* warning: must be at 32 MB distancy */
2098
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2099
                                    reloc_offset, reloc_offset, relname, reloc_offset, addend);
2100
                            break;
2101
                        default:
2102
                            error("unsupported powerpc relocation (%d)", type);
2103
                        }
2104
                    }
2105
                }
2106
#elif defined(CONFIG_FORMAT_MACH)
2107
                struct scattered_relocation_info *scarel;
2108
                struct relocation_info * rel;
2109
                char final_sym_name[256];
2110
                const char *sym_name;
2111
                const char *p;
2112
                int slide, sslide;
2113
                int i;
2114

    
2115
                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2116
                    unsigned int offset, length, value = 0;
2117
                    unsigned int type, pcrel, isym = 0;
2118
                    unsigned int usesym = 0;
2119

    
2120
                    if(R_SCATTERED & rel->r_address) {
2121
                        scarel = (struct scattered_relocation_info*)rel;
2122
                        offset = (unsigned int)scarel->r_address;
2123
                        length = scarel->r_length;
2124
                        pcrel = scarel->r_pcrel;
2125
                        type = scarel->r_type;
2126
                        value = scarel->r_value;
2127
                    } else {
2128
                        value = isym = rel->r_symbolnum;
2129
                        usesym = (rel->r_extern);
2130
                        offset = rel->r_address;
2131
                        length = rel->r_length;
2132
                        pcrel = rel->r_pcrel;
2133
                        type = rel->r_type;
2134
                    }
2135

    
2136
                    slide = offset - start_offset;
2137

    
2138
                    if (!(offset >= start_offset && offset < start_offset + size))
2139
                        continue;  /* not in our range */
2140

    
2141
                        sym_name = get_reloc_name(rel, &sslide);
2142

    
2143
                        if(usesym && symtab[isym].n_type & N_STAB)
2144
                            continue; /* don't handle STAB (debug sym) */
2145

    
2146
                        if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2147
                            int n;
2148
                            n = strtol(p, NULL, 10);
2149
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2150
                                    n, slide);
2151
                            continue; /* Nothing more to do */
2152
                        }
2153

    
2154
                        if(!sym_name) {
2155
                            fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2156
                                    name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2157
                            continue; /* dunno how to handle without final_sym_name */
2158
                        }
2159

    
2160
                        get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2161
                                       sym_name);
2162
                        switch(type) {
2163
                        case PPC_RELOC_BR24:
2164
                            if (!strstart(sym_name,"__op_gen_label",&p)) {
2165
                                fprintf(outfile, "{\n");
2166
                                fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2167
                                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",
2168
                                        slide, slide, name, sslide);
2169
                                fprintf(outfile, "}\n");
2170
                            } else {
2171
                                fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2172
                                        slide, slide, final_sym_name, slide);
2173
                            }
2174
                            break;
2175
                        case PPC_RELOC_HI16:
2176
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2177
                                    slide, final_sym_name, sslide);
2178
                            break;
2179
                        case PPC_RELOC_LO16:
2180
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2181
                                    slide, final_sym_name, sslide);
2182
                            break;
2183
                        case PPC_RELOC_HA16:
2184
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2185
                                    slide, final_sym_name, sslide);
2186
                            break;
2187
                        default:
2188
                            error("unsupported powerpc relocation (%d)", type);
2189
                    }
2190
                }
2191
#else
2192
#error unsupport object format
2193
#endif
2194
            }
2195
#elif defined(HOST_S390)
2196
            {
2197
                char relname[256];
2198
                int type;
2199
                int addend;
2200
                int reloc_offset;
2201
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2202
                    if (rel->r_offset >= start_offset &&
2203
                        rel->r_offset < start_offset + copy_size) {
2204
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2205
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2206
                        type = ELF32_R_TYPE(rel->r_info);
2207
                        addend = rel->r_addend;
2208
                        reloc_offset = rel->r_offset - start_offset;
2209
                        switch(type) {
2210
                        case R_390_32:
2211
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2212
                                    reloc_offset, relname, addend);
2213
                            break;
2214
                        case R_390_16:
2215
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2216
                                    reloc_offset, relname, addend);
2217
                            break;
2218
                        case R_390_8:
2219
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2220
                                    reloc_offset, relname, addend);
2221
                            break;
2222
                        case R_390_PC32DBL:
2223
                            if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2224
                                fprintf(outfile,
2225
                                        "    *(uint32_t *)(gen_code_ptr + %d) += "
2226
                                        "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2227
                                        reloc_offset, name);
2228
                            }
2229
                            else
2230
                                fprintf(outfile,
2231
                                        "    *(uint32_t *)(gen_code_ptr + %d) = "
2232
                                        "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2233
                                        reloc_offset, relname, addend, reloc_offset);
2234
                            break;
2235
                        default:
2236
                            error("unsupported s390 relocation (%d)", type);
2237
                        }
2238
                    }
2239
                }
2240
            }
2241
#elif defined(HOST_ALPHA)
2242
            {
2243
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2244
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2245
                        int type;
2246
                        long reloc_offset;
2247

    
2248
                        type = ELF64_R_TYPE(rel->r_info);
2249
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2250
                        reloc_offset = rel->r_offset - start_offset;
2251
                        switch (type) {
2252
                        case R_ALPHA_GPDISP:
2253
                            /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2254
                               as an immediate instead of constructing it from the pv or ra.  */
2255
                            fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2256
                                    reloc_offset);
2257
                            fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2258
                                    reloc_offset + (int)rel->r_addend);
2259
                            break;
2260
                        case R_ALPHA_LITUSE:
2261
                            /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2262
                               now, since some called functions (libc) need pv to be set up.  */
2263
                            break;
2264
                        case R_ALPHA_HINT:
2265
                            /* Branch target prediction hint. Ignore for now.  Should be already
2266
                               correct for in-function jumps.  */
2267
                            break;
2268
                        case R_ALPHA_LITERAL:
2269
                            /* Load a literal from the GOT relative to the gp.  Since there's only a
2270
                               single gp, nothing is to be done.  */
2271
                            break;
2272
                        case R_ALPHA_GPRELHIGH:
2273
                            /* Handle fake relocations against __op_param symbol.  Need to emit the
2274
                               high part of the immediate value instead.  Other symbols need no
2275
                               special treatment.  */
2276
                            if (strstart(sym_name, "__op_param", &p))
2277
                                fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2278
                                        reloc_offset, p);
2279
                            break;
2280
                        case R_ALPHA_GPRELLOW:
2281
                            if (strstart(sym_name, "__op_param", &p))
2282
                                fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2283
                                        reloc_offset, p);
2284
                            break;
2285
                        case R_ALPHA_BRSGP:
2286
                            /* PC-relative jump. Tweak offset to skip the two instructions that try to
2287
                               set up the gp from the pv.  */
2288
                            fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2289
                                    reloc_offset, sym_name, reloc_offset);
2290
                            break;
2291
                        default:
2292
                            error("unsupported Alpha relocation (%d)", type);
2293
                        }
2294
                    }
2295
                }
2296
            }
2297
#elif defined(HOST_IA64)
2298
            {
2299
                unsigned long sym_idx;
2300
                long code_offset;
2301
                char relname[256];
2302
                int type;
2303
                long addend;
2304

    
2305
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2306
                    sym_idx = ELF64_R_SYM(rel->r_info);
2307
                    if (rel->r_offset < start_offset
2308
                        || rel->r_offset >= start_offset + copy_size)
2309
                        continue;
2310
                    sym_name = (strtab + symtab[sym_idx].st_name);
2311
                    code_offset = rel->r_offset - start_offset;
2312
                    if (strstart(sym_name, "__op_jmp", &p)) {
2313
                        int n;
2314
                        n = strtol(p, NULL, 10);
2315
                        /* __op_jmp relocations are done at
2316
                           runtime to do translated block
2317
                           chaining: the offset of the instruction
2318
                           needs to be stored */
2319
                        fprintf(outfile, "    jmp_offsets[%d] ="
2320
                                "%ld + (gen_code_ptr - gen_code_buf);\n",
2321
                                n, code_offset);
2322
                        continue;
2323
                    }
2324
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2325
                    type = ELF64_R_TYPE(rel->r_info);
2326
                    addend = rel->r_addend;
2327
                    switch(type) {
2328
                      case R_IA64_IMM64:
2329
                          fprintf(outfile,
2330
                                  "    ia64_imm64(gen_code_ptr + %ld, "
2331
                                  "%s + %ld);\n",
2332
                                  code_offset, relname, addend);
2333
                          break;
2334
                      case R_IA64_LTOFF22X:
2335
                      case R_IA64_LTOFF22:
2336
                          fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2337
                                  " %s + %ld, %d);\n",
2338
                                  code_offset, relname, addend,
2339
                                  (type == R_IA64_LTOFF22X));
2340
                          break;
2341
                      case R_IA64_LDXMOV:
2342
                          fprintf(outfile,
2343
                                  "    ia64_ldxmov(gen_code_ptr + %ld,"
2344
                                  " %s + %ld);\n", code_offset, relname, addend);
2345
                          break;
2346

    
2347
                      case R_IA64_PCREL21B:
2348
                          if (strstart(sym_name, "__op_gen_label", NULL)) {
2349
                              fprintf(outfile,
2350
                                      "    ia64_imm21b(gen_code_ptr + %ld,"
2351
                                      " (long) (%s + %ld -\n\t\t"
2352
                                      "((long) gen_code_ptr + %ld)) >> 4);\n",
2353
                                      code_offset, relname, addend,
2354
                                      code_offset & ~0xfUL);
2355
                          } else {
2356
                              fprintf(outfile,
2357
                                      "    IA64_PLT(gen_code_ptr + %ld, "
2358
                                      "%d);\t/* %s + %ld */\n",
2359
                                      code_offset,
2360
                                      get_plt_index(sym_name, addend),
2361
                                      sym_name, addend);
2362
                          }
2363
                          break;
2364
                      default:
2365
                          error("unsupported ia64 relocation (0x%x)",
2366
                                type);
2367
                    }
2368
                }
2369
                fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2370
                        copy_size - 16 + 2);
2371
            }
2372
#elif defined(HOST_SPARC)
2373
            {
2374
                char relname[256];
2375
                int type;
2376
                int addend;
2377
                int reloc_offset;
2378
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2379
                    if (rel->r_offset >= start_offset &&
2380
                        rel->r_offset < start_offset + copy_size) {
2381
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2382
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2383
                        type = ELF32_R_TYPE(rel->r_info);
2384
                        addend = rel->r_addend;
2385
                        reloc_offset = rel->r_offset - start_offset;
2386
                        switch(type) {
2387
                        case R_SPARC_32:
2388
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2389
                                    reloc_offset, relname, addend);
2390
                            break;
2391
                        case R_SPARC_HI22:
2392
                            fprintf(outfile,
2393
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2394
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2395
                                    " & ~0x3fffff) "
2396
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2397
                                    reloc_offset, reloc_offset, relname, addend);
2398
                            break;
2399
                        case R_SPARC_LO10:
2400
                            fprintf(outfile,
2401
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2402
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2403
                                    " & ~0x3ff) "
2404
                                    " | ((%s + %d) & 0x3ff);\n",
2405
                                    reloc_offset, reloc_offset, relname, addend);
2406
                            break;
2407
                        case R_SPARC_WDISP30:
2408
                            fprintf(outfile,
2409
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2410
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2411
                                    " & ~0x3fffffff) "
2412
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2413
                                    "    & 0x3fffffff);\n",
2414
                                    reloc_offset, reloc_offset, relname, addend,
2415
                                    reloc_offset);
2416
                            break;
2417
                        case R_SPARC_WDISP22:
2418
                            fprintf(outfile,
2419
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2420
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2421
                                    " & ~0x3fffff) "
2422
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2423
                                    "    & 0x3fffff);\n",
2424
                                    rel->r_offset - start_offset,
2425
                                    rel->r_offset - start_offset,
2426
                                    relname, addend,
2427
                                    rel->r_offset - start_offset);
2428
                            break;
2429
                        default:
2430
                            error("unsupported sparc relocation (%d)", type);
2431
                        }
2432
                    }
2433
                }
2434
            }
2435
#elif defined(HOST_SPARC64)
2436
            {
2437
                char relname[256];
2438
                int type;
2439
                int addend;
2440
                int reloc_offset;
2441
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2442
                    if (rel->r_offset >= start_offset &&
2443
                        rel->r_offset < start_offset + copy_size) {
2444
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2445
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2446
                        type = ELF32_R_TYPE(rel->r_info);
2447
                        addend = rel->r_addend;
2448
                        reloc_offset = rel->r_offset - start_offset;
2449
                        switch(type) {
2450
                        case R_SPARC_32:
2451
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2452
                                    reloc_offset, relname, addend);
2453
                            break;
2454
                        case R_SPARC_HI22:
2455
                            fprintf(outfile,
2456
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2457
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2458
                                    " & ~0x3fffff) "
2459
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2460
                                    reloc_offset, reloc_offset, relname, addend);
2461
                            break;
2462
                        case R_SPARC_LO10:
2463
                            fprintf(outfile,
2464
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2465
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2466
                                    " & ~0x3ff) "
2467
                                    " | ((%s + %d) & 0x3ff);\n",
2468
                                    reloc_offset, reloc_offset, relname, addend);
2469
                            break;
2470
                        case R_SPARC_OLO10:
2471
                            addend += ELF64_R_TYPE_DATA (rel->r_info);
2472
                            fprintf(outfile,
2473
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2474
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2475
                                    " & ~0x3ff) "
2476
                                    " | ((%s + %d) & 0x3ff);\n",
2477
                                    reloc_offset, reloc_offset, relname, addend);
2478
                            break;
2479
                        case R_SPARC_WDISP30:
2480
                            fprintf(outfile,
2481
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2482
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2483
                                    " & ~0x3fffffff) "
2484
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2485
                                    "    & 0x3fffffff);\n",
2486
                                    reloc_offset, reloc_offset, relname, addend,
2487
                                    reloc_offset);
2488
                            break;
2489
                        case R_SPARC_WDISP22:
2490
                            fprintf(outfile,
2491
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2492
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2493
                                    " & ~0x3fffff) "
2494
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2495
                                    "    & 0x3fffff);\n",
2496
                                    reloc_offset, reloc_offset, relname, addend,
2497
                                    reloc_offset);
2498
                            break;
2499
                        case R_SPARC_HH22:
2500
                            fprintf(outfile,
2501
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2502
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2503
                                    " & ~0x00000000) "
2504
                                    " | (((%s + %d) >> 42) & 0x00000000);\n",
2505
                                    reloc_offset, reloc_offset, relname, addend);
2506
                             break;
2507

    
2508
                        case R_SPARC_LM22:
2509
                            fprintf(outfile,
2510
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2511
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2512
                                    " & ~0x00000000) "
2513
                                    " | (((%s + %d) >> 10) & 0x00000000);\n",
2514
                                    reloc_offset, reloc_offset, relname, addend);
2515
                            break;
2516

    
2517
                        case R_SPARC_HM10:
2518
                            fprintf(outfile,
2519
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2520
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2521
                                    " & ~0x00000000) "
2522
                                    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2523
                                    reloc_offset, reloc_offset, relname, addend);
2524
                            break;
2525

    
2526
                        default:
2527
                            error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2528
                        }
2529
                    }
2530
                }
2531
            }
2532
#elif defined(HOST_ARM)
2533
            {
2534
                char relname[256];
2535
                int type;
2536
                int addend;
2537
                int reloc_offset;
2538
                uint32_t insn;
2539

    
2540
                insn = get32((uint32_t *)(p_start + 4));
2541
                /* If prologue ends in sub sp, sp, #const then assume
2542
                   op has a stack frame and needs the frame pointer.  */
2543
                if ((insn & 0xffffff00) == 0xe24dd000) {
2544
                    int i;
2545
                    uint32_t opcode;
2546
                    opcode = 0xe28db000; /* add fp, sp, #0.  */
2547
#if 0
2548
/* ??? Need to undo the extra stack adjustment at the end of the op.
2549
   For now just leave the stack misaligned and hope it doesn't break anything
2550
   too important.  */
2551
                    if ((insn & 4) != 0) {
2552
                        /* Preserve doubleword stack alignment.  */
2553
                        fprintf(outfile,
2554
                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2555
                                insn + 4);
2556
                        opcode -= 4;
2557
                    }
2558
#endif
2559
                    insn = get32((uint32_t *)(p_start - 4));
2560
                    /* Calculate the size of the saved registers,
2561
                       excluding pc.  */
2562
                    for (i = 0; i < 15; i++) {
2563
                        if (insn & (1 << i))
2564
                            opcode += 4;
2565
                    }
2566
                    fprintf(outfile,
2567
                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2568
                }
2569
                arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2570
                                  relocs, nb_relocs);
2571

    
2572
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2573
                if (rel->r_offset >= start_offset &&
2574
                    rel->r_offset < start_offset + copy_size) {
2575
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2576
                    /* the compiler leave some unnecessary references to the code */
2577
                    if (sym_name[0] == '\0')
2578
                        continue;
2579
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2580
                    type = ELF32_R_TYPE(rel->r_info);
2581
                    addend = get32((uint32_t *)(text + rel->r_offset));
2582
                    reloc_offset = rel->r_offset - start_offset;
2583
                    switch(type) {
2584
                    case R_ARM_ABS32:
2585
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2586
                                reloc_offset, relname, addend);
2587
                        break;
2588
                    case R_ARM_PC24:
2589
                    case R_ARM_JUMP24:
2590
                    case R_ARM_CALL:
2591
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2592
                                reloc_offset, addend, relname);
2593
                        break;
2594
                    default:
2595
                        error("unsupported arm relocation (%d)", type);
2596
                    }
2597
                }
2598
                }
2599
            }
2600
#elif defined(HOST_M68K)
2601
            {
2602
                char relname[256];
2603
                int type;
2604
                int addend;
2605
                int reloc_offset;
2606
                Elf32_Sym *sym;
2607
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2608
                if (rel->r_offset >= start_offset &&
2609
                    rel->r_offset < start_offset + copy_size) {
2610
                    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2611
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2612
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2613
                    type = ELF32_R_TYPE(rel->r_info);
2614
                    addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2615
                    reloc_offset = rel->r_offset - start_offset;
2616
                    switch(type) {
2617
                    case R_68K_32:
2618
                        fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2619
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2620
                                reloc_offset, relname, addend );
2621
                        break;
2622
                    case R_68K_PC32:
2623
                        fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2624
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2625
                                reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2626
                        break;
2627
                    default:
2628
                        error("unsupported m68k relocation (%d)", type);
2629
                    }
2630
                }
2631
                }
2632
            }
2633
#elif defined(HOST_HPPA)
2634
            {
2635
                char relname[256];
2636
                int type, is_label;
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 = get_rel_sym_name(rel);
2643
                    sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2644
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2645
                    type = ELF32_R_TYPE(rel->r_info);
2646
                    addend = rel->r_addend;
2647
                    reloc_offset = rel->r_offset - start_offset;
2648

    
2649
                    if (is_label) {
2650
                        switch (type) {
2651
                        case R_PARISC_PCREL17F:
2652
                            fprintf(outfile,
2653
"    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2654
                                    reloc_offset, type, relname, addend);
2655
                            break;
2656
                        default:
2657
                            error("unsupported hppa label relocation (%d)", type);
2658
                        }
2659
                    } else {
2660
                        switch (type) {
2661
                        case R_PARISC_DIR21L:
2662
                            fprintf(outfile,
2663
"    hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2664
                                    reloc_offset, relname, addend);
2665
                            break;
2666
                        case R_PARISC_DIR14R:
2667
                            fprintf(outfile,
2668
"    hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2669
                                    reloc_offset, relname, addend);
2670
                            break;
2671
                        case R_PARISC_PCREL17F:
2672
                            if (strstart(sym_name, "__op_gen_label", NULL)) {
2673
                                fprintf(outfile,
2674
"    hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2675
                                        reloc_offset, relname, addend);
2676
                            } else {
2677
                                fprintf(outfile,
2678
"    HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2679
                                        reloc_offset, relname);
2680
                            }
2681
                            break;
2682
                        case R_PARISC_DPREL21L:
2683
                            if (strstart(sym_name, "__op_param", &p))
2684
                                fprintf(outfile,
2685
"    hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2686
                                        reloc_offset, p, addend);
2687
                            else
2688
                                fprintf(outfile,
2689
"    hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2690
                                        reloc_offset, relname, addend);
2691
                            break;
2692
                        case R_PARISC_DPREL14R:
2693
                            if (strstart(sym_name, "__op_param", &p))
2694
                                fprintf(outfile,
2695
"    hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2696
                                        reloc_offset, p, addend);
2697
                            else
2698
                                fprintf(outfile,
2699
"    hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2700
                                        reloc_offset, relname, addend);
2701
                            break;
2702
                        default:
2703
                            error("unsupported hppa relocation (%d)", type);
2704
                        }
2705
                    }
2706
                }
2707
                }
2708
            }
2709
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2710
            {
2711
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2712
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2713
                        char relname[256];
2714
                        int type;
2715
                        int addend;
2716
                        int reloc_offset;
2717

    
2718
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2719
                        /* the compiler leave some unnecessary references to the code */
2720
                        if (sym_name[0] == '\0')
2721
                            continue;
2722
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2723
                        type = ELF32_R_TYPE(rel->r_info);
2724
                        addend = get32((uint32_t *)(text + rel->r_offset));
2725
                        reloc_offset = rel->r_offset - start_offset;
2726
                        switch (type) {
2727
                        case R_MIPS_26:
2728
                            fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2729
                                    rel->r_offset, sym_name);
2730
                            fprintf(outfile,
2731
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2732
                                    "(0x%x & ~0x3fffff) "
2733
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2734
                                    "   & 0x3fffff);\n",
2735
                                    reloc_offset, addend, addend, relname, reloc_offset);
2736
                            break;
2737
                        case R_MIPS_HI16:
2738
                            fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2739
                                    rel->r_offset, sym_name);
2740
                            fprintf(outfile,
2741
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2742
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2743
                                    " & ~0xffff) "
2744
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2745
                                    reloc_offset, reloc_offset, relname);
2746
                            break;
2747
                        case R_MIPS_LO16:
2748
                            fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2749
                                    rel->r_offset, sym_name);
2750
                            fprintf(outfile,
2751
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2752
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2753
                                    " & ~0xffff) "
2754
                                    " | (%s & 0xffff);\n",
2755
                                    reloc_offset, reloc_offset, relname);
2756
                            break;
2757
                        case R_MIPS_PC16:
2758
                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2759
                                    rel->r_offset, sym_name);
2760
                            fprintf(outfile,
2761
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2762
                                    "(0x%x & ~0xffff) "
2763
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2764
                                    "   & 0xffff);\n",
2765
                                    reloc_offset, addend, addend, relname, reloc_offset);
2766
                            break;
2767
                        case R_MIPS_GOT16:
2768
                        case R_MIPS_CALL16:
2769
                            fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2770
                                    rel->r_offset, sym_name);
2771
                            fprintf(outfile,
2772
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2773
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2774
                                    " & ~0xffff) "
2775
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2776
                                    reloc_offset, reloc_offset, relname);
2777
                            break;
2778
                        default:
2779
                            error("unsupported MIPS relocation (%d)", type);
2780
                        }
2781
                    }
2782
                }
2783
            }
2784
#else
2785
#error unsupported CPU
2786
#endif
2787
        fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2788
        fprintf(outfile, "}\n");
2789
        fprintf(outfile, "break;\n\n");
2790
    } else {
2791
        fprintf(outfile, "static inline void gen_%s(", name);
2792
        if (nb_args == 0) {
2793
            fprintf(outfile, "void");
2794
        } else {
2795
            for(i = 0; i < nb_args; i++) {
2796
                if (i != 0)
2797
                    fprintf(outfile, ", ");
2798
                fprintf(outfile, "long param%d", i + 1);
2799
            }
2800
        }
2801
        fprintf(outfile, ")\n");
2802
        fprintf(outfile, "{\n");
2803
        for(i = 0; i < nb_args; i++) {
2804
            fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2805
        }
2806
        fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2807
        fprintf(outfile, "}\n\n");
2808
    }
2809
}
2810

    
2811
int gen_file(FILE *outfile, int out_type)
2812
{
2813
    int i;
2814
    EXE_SYM *sym;
2815

    
2816
    if (out_type == OUT_INDEX_OP) {
2817
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2818
            const char *name;
2819
            name = get_sym_name(sym);
2820
            if (strstart(name, OP_PREFIX, NULL)) {
2821
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2822
            }
2823
        }
2824
    } else if (out_type == OUT_GEN_OP) {
2825
        /* generate gen_xxx functions */
2826
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2827
            const char *name;
2828
            name = get_sym_name(sym);
2829
            if (strstart(name, OP_PREFIX, NULL)) {
2830
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2831
                if (sym->st_shndx != text_shndx)
2832
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2833
#endif
2834
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2835
            }
2836
        }
2837

    
2838
    } else {
2839
        /* generate big code generation switch */
2840

    
2841
#ifdef HOST_ARM
2842
#error broken
2843
        /* We need to know the size of all the ops so we can figure out when
2844
           to emit constant pools.  This must be consistent with opc.h.  */
2845
fprintf(outfile,
2846
"static const uint32_t arm_opc_size[] = {\n"
2847
"  0,\n" /* end */
2848
"  0,\n" /* nop */
2849
"  0,\n" /* nop1 */
2850
"  0,\n" /* nop2 */
2851
"  0,\n"); /* nop3 */
2852
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2853
            const char *name;
2854
            name = get_sym_name(sym);
2855
            if (strstart(name, OP_PREFIX, NULL)) {
2856
                fprintf(outfile, "  %d,\n", sym->st_size);
2857
            }
2858
        }
2859
fprintf(outfile,
2860
"};\n");
2861
#endif
2862

    
2863
#ifdef HOST_ARM
2864
#error broken
2865
/* Arm is tricky because it uses constant pools for loading immediate values.
2866
   We assume (and require) each function is code followed by a constant pool.
2867
   All the ops are small so this should be ok.  For each op we figure
2868
   out how much "spare" range we have in the load instructions.  This allows
2869
   us to insert subsequent ops in between the op and the constant pool,
2870
   eliminating the neeed to jump around the pool.
2871

2872
   We currently generate:
2873

2874
   [ For this example we assume merging would move op1_pool out of range.
2875
     In practice we should be able to combine many ops before the offset
2876
     limits are reached. ]
2877
   op1_code;
2878
   op2_code;
2879
   goto op3;
2880
   op2_pool;
2881
   op1_pool;
2882
op3:
2883
   op3_code;
2884
   ret;
2885
   op3_pool;
2886

2887
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2888
 */
2889
fprintf(outfile,
2890
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2891
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2892
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2893
/* Initialise the parmissible pool offset to an arbitary large value.  */
2894
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2895
#endif
2896
#ifdef HOST_IA64
2897
#error broken
2898
    {
2899
        long addend, not_first = 0;
2900
        unsigned long sym_idx;
2901
        int index, max_index;
2902
        const char *sym_name;
2903
        EXE_RELOC *rel;
2904

    
2905
        max_index = -1;
2906
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2907
            sym_idx = ELF64_R_SYM(rel->r_info);
2908
            sym_name = (strtab + symtab[sym_idx].st_name);
2909
            if (strstart(sym_name, "__op_gen_label", NULL))
2910
                continue;
2911
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2912
                continue;
2913

    
2914
            addend = rel->r_addend;
2915
            index = get_plt_index(sym_name, addend);
2916
            if (index <= max_index)
2917
                continue;
2918
            max_index = index;
2919
            fprintf(outfile, "    extern void %s(void);\n", sym_name);
2920
        }
2921

    
2922
        fprintf(outfile,
2923
                "    struct ia64_fixup *plt_fixes = NULL, "
2924
                "*ltoff_fixes = NULL;\n"
2925
                "    static long plt_target[] = {\n\t");
2926

    
2927
        max_index = -1;
2928
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2929
            sym_idx = ELF64_R_SYM(rel->r_info);
2930
            sym_name = (strtab + symtab[sym_idx].st_name);
2931
            if (strstart(sym_name, "__op_gen_label", NULL))
2932
                continue;
2933
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2934
                continue;
2935

    
2936
            addend = rel->r_addend;
2937
            index = get_plt_index(sym_name, addend);
2938
            if (index <= max_index)
2939
                continue;
2940
            max_index = index;
2941

    
2942
            if (not_first)
2943
                fprintf(outfile, ",\n\t");
2944
            not_first = 1;
2945
            if (addend)
2946
                fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2947
            else
2948
                fprintf(outfile, "(long) &%s", sym_name);
2949
        }
2950
        fprintf(outfile, "\n    };\n"
2951
            "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2952
    }
2953
#endif
2954

    
2955
#ifdef HOST_ARM
2956
#error broken
2957
/* Generate constant pool if needed */
2958
fprintf(outfile,
2959
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2960
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2961
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2962
"                last_gen_code_ptr = gen_code_ptr;\n"
2963
"                arm_ldr_ptr = arm_ldr_table;\n"
2964
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2965
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2966
"            }\n");
2967
#endif
2968

    
2969
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2970
            const char *name;
2971
            name = get_sym_name(sym);
2972
            if (strstart(name, OP_PREFIX, NULL)) {
2973
#if 0
2974
                printf("%4d: %s pos=0x%08x len=%d\n",
2975
                       i, name, sym->st_value, sym->st_size);
2976
#endif
2977
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2978
                if (sym->st_shndx != text_shndx)
2979
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2980
#endif
2981
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2982
            }
2983
        }
2984
    }
2985

    
2986
    return 0;
2987
}
2988

    
2989
void usage(void)
2990
{
2991
    printf("dyngen (c) 2003 Fabrice Bellard\n"
2992
           "usage: dyngen [-o outfile] [-c] objfile\n"
2993
           "Generate a dynamic code generator from an object file\n"
2994
           "-c     output enum of operations\n"
2995
           "-g     output gen_op_xx() functions\n"
2996
           );
2997
    exit(1);
2998
}
2999

    
3000
int main(int argc, char **argv)
3001
{
3002
    int c, out_type;
3003
    const char *filename, *outfilename;
3004
    FILE *outfile;
3005

    
3006
    outfilename = "out.c";
3007
    out_type = OUT_CODE;
3008
    for(;;) {
3009
        c = getopt(argc, argv, "ho:cg");
3010
        if (c == -1)
3011
            break;
3012
        switch(c) {
3013
        case 'h':
3014
            usage();
3015
            break;
3016
        case 'o':
3017
            outfilename = optarg;
3018
            break;
3019
        case 'c':
3020
            out_type = OUT_INDEX_OP;
3021
            break;
3022
        case 'g':
3023
            out_type = OUT_GEN_OP;
3024
            break;
3025
        }
3026
    }
3027
    if (optind >= argc)
3028
        usage();
3029
    filename = argv[optind];
3030
    outfile = fopen(outfilename, "w");
3031
    if (!outfile)
3032
        error("could not open '%s'", outfilename);
3033

    
3034
    load_object(filename);
3035
    gen_file(outfile, out_type);
3036
    fclose(outfile);
3037
    return 0;
3038
}