Statistics
| Branch: | Revision:

root / dyngen.c @ 8289b279

History | View | Annotate | Download (95.4 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_MIPS)
121

    
122
#define ELF_CLASS        ELFCLASS32
123
#define ELF_ARCH        EM_MIPS
124
#define elf_check_arch(x) ((x) == EM_MIPS)
125
#define ELF_USES_RELOC
126

    
127
#elif defined(HOST_MIPS64)
128

    
129
/* Assume n32 ABI here, which is ELF32. */
130
#define ELF_CLASS        ELFCLASS32
131
#define ELF_ARCH        EM_MIPS
132
#define elf_check_arch(x) ((x) == EM_MIPS)
133
#define ELF_USES_RELOCA
134

    
135
#else
136
#error unsupported CPU - please update the code
137
#endif
138

    
139
#include "elf.h"
140

    
141
#if ELF_CLASS == ELFCLASS32
142
typedef int32_t host_long;
143
typedef uint32_t host_ulong;
144
#define swabls(x) swab32s(x)
145
#define swablss(x) swab32ss(x)
146
#else
147
typedef int64_t host_long;
148
typedef uint64_t host_ulong;
149
#define swabls(x) swab64s(x)
150
#define swablss(x) swab64ss(x)
151
#endif
152

    
153
#ifdef ELF_USES_RELOCA
154
#define SHT_RELOC SHT_RELA
155
#else
156
#define SHT_RELOC SHT_REL
157
#endif
158

    
159
#define EXE_RELOC ELF_RELOC
160
#define EXE_SYM ElfW(Sym)
161

    
162
#endif /* CONFIG_FORMAT_ELF */
163

    
164
#ifdef CONFIG_FORMAT_COFF
165

    
166
typedef int32_t host_long;
167
typedef uint32_t host_ulong;
168

    
169
#include "a.out.h"
170

    
171
#define FILENAMELEN 256
172

    
173
typedef struct coff_sym {
174
    struct external_syment *st_syment;
175
    char st_name[FILENAMELEN];
176
    uint32_t st_value;
177
    int  st_size;
178
    uint8_t st_type;
179
    uint8_t st_shndx;
180
} coff_Sym;
181

    
182
typedef struct coff_rel {
183
    struct external_reloc *r_reloc;
184
    int  r_offset;
185
    uint8_t r_type;
186
} coff_Rel;
187

    
188
#define EXE_RELOC struct coff_rel
189
#define EXE_SYM struct coff_sym
190

    
191
#endif /* CONFIG_FORMAT_COFF */
192

    
193
#ifdef CONFIG_FORMAT_MACH
194

    
195
#include <mach-o/loader.h>
196
#include <mach-o/nlist.h>
197
#include <mach-o/reloc.h>
198
#include <mach-o/ppc/reloc.h>
199

    
200
# define check_mach_header(x) (x.magic == MH_MAGIC)
201
typedef int32_t host_long;
202
typedef uint32_t host_ulong;
203

    
204
struct nlist_extended
205
{
206
   union {
207
   char *n_name;
208
   long  n_strx;
209
   } n_un;
210
   unsigned char n_type;
211
   unsigned char n_sect;
212
   short st_desc;
213
   unsigned long st_value;
214
   unsigned long st_size;
215
};
216

    
217
#define EXE_RELOC struct relocation_info
218
#define EXE_SYM struct nlist_extended
219

    
220
#endif /* CONFIG_FORMAT_MACH */
221

    
222
#include "bswap.h"
223

    
224
enum {
225
    OUT_GEN_OP,
226
    OUT_CODE,
227
    OUT_INDEX_OP,
228
};
229

    
230
/* all dynamically generated functions begin with this code */
231
#define OP_PREFIX "op_"
232

    
233
int do_swap;
234

    
235
static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
236
{
237
    va_list ap;
238
    va_start(ap, fmt);
239
    fprintf(stderr, "dyngen: ");
240
    vfprintf(stderr, fmt, ap);
241
    fprintf(stderr, "\n");
242
    va_end(ap);
243
    exit(1);
244
}
245

    
246
static void *load_data(int fd, long offset, unsigned int size)
247
{
248
    char *data;
249

    
250
    data = malloc(size);
251
    if (!data)
252
        return NULL;
253
    lseek(fd, offset, SEEK_SET);
254
    if (read(fd, data, size) != size) {
255
        free(data);
256
        return NULL;
257
    }
258
    return data;
259
}
260

    
261
int strstart(const char *str, const char *val, const char **ptr)
262
{
263
    const char *p, *q;
264
    p = str;
265
    q = val;
266
    while (*q != '\0') {
267
        if (*p != *q)
268
            return 0;
269
        p++;
270
        q++;
271
    }
272
    if (ptr)
273
        *ptr = p;
274
    return 1;
275
}
276

    
277
void pstrcpy(char *buf, int buf_size, const char *str)
278
{
279
    int c;
280
    char *q = buf;
281

    
282
    if (buf_size <= 0)
283
        return;
284

    
285
    for(;;) {
286
        c = *str++;
287
        if (c == 0 || q >= buf + buf_size - 1)
288
            break;
289
        *q++ = c;
290
    }
291
    *q = '\0';
292
}
293

    
294
void swab16s(uint16_t *p)
295
{
296
    *p = bswap16(*p);
297
}
298

    
299
void swab32s(uint32_t *p)
300
{
301
    *p = bswap32(*p);
302
}
303

    
304
void swab32ss(int32_t *p)
305
{
306
    *p = bswap32(*p);
307
}
308

    
309
void swab64s(uint64_t *p)
310
{
311
    *p = bswap64(*p);
312
}
313

    
314
void swab64ss(int64_t *p)
315
{
316
    *p = bswap64(*p);
317
}
318

    
319
uint16_t get16(uint16_t *p)
320
{
321
    uint16_t val;
322
    val = *p;
323
    if (do_swap)
324
        val = bswap16(val);
325
    return val;
326
}
327

    
328
uint32_t get32(uint32_t *p)
329
{
330
    uint32_t val;
331
    val = *p;
332
    if (do_swap)
333
        val = bswap32(val);
334
    return val;
335
}
336

    
337
void put16(uint16_t *p, uint16_t val)
338
{
339
    if (do_swap)
340
        val = bswap16(val);
341
    *p = val;
342
}
343

    
344
void put32(uint32_t *p, uint32_t val)
345
{
346
    if (do_swap)
347
        val = bswap32(val);
348
    *p = val;
349
}
350

    
351
/* executable information */
352
EXE_SYM *symtab;
353
int nb_syms;
354
int text_shndx;
355
uint8_t *text;
356
EXE_RELOC *relocs;
357
int nb_relocs;
358

    
359
#ifdef CONFIG_FORMAT_ELF
360

    
361
/* ELF file info */
362
struct elf_shdr *shdr;
363
uint8_t **sdata;
364
struct elfhdr ehdr;
365
char *strtab;
366

    
367
int elf_must_swap(struct elfhdr *h)
368
{
369
  union {
370
      uint32_t i;
371
      uint8_t b[4];
372
  } swaptest;
373

    
374
  swaptest.i = 1;
375
  return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
376
      (swaptest.b[0] == 0);
377
}
378

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

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

    
410
void elf_swap_phdr(struct elf_phdr *h)
411
{
412
    swab32s(&h->p_type);                        /* Segment type */
413
    swabls(&h->p_offset);                /* Segment file offset */
414
    swabls(&h->p_vaddr);                /* Segment virtual address */
415
    swabls(&h->p_paddr);                /* Segment physical address */
416
    swabls(&h->p_filesz);                /* Segment size in file */
417
    swabls(&h->p_memsz);                /* Segment size in memory */
418
    swab32s(&h->p_flags);                /* Segment flags */
419
    swabls(&h->p_align);                /* Segment alignment */
420
}
421

    
422
void elf_swap_rel(ELF_RELOC *rel)
423
{
424
    swabls(&rel->r_offset);
425
    swabls(&rel->r_info);
426
#ifdef ELF_USES_RELOCA
427
    swablss(&rel->r_addend);
428
#endif
429
}
430

    
431
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
432
                                  const char *name)
433
{
434
    int i;
435
    const char *shname;
436
    struct elf_shdr *sec;
437

    
438
    for(i = 0; i < shnum; i++) {
439
        sec = &shdr[i];
440
        if (!sec->sh_name)
441
            continue;
442
        shname = shstr + sec->sh_name;
443
        if (!strcmp(shname, name))
444
            return sec;
445
    }
446
    return NULL;
447
}
448

    
449
int find_reloc(int sh_index)
450
{
451
    struct elf_shdr *sec;
452
    int i;
453

    
454
    for(i = 0; i < ehdr.e_shnum; i++) {
455
        sec = &shdr[i];
456
        if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
457
            return i;
458
    }
459
    return 0;
460
}
461

    
462
static host_ulong get_rel_offset(EXE_RELOC *rel)
463
{
464
    return rel->r_offset;
465
}
466

    
467
static char *get_rel_sym_name(EXE_RELOC *rel)
468
{
469
    return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
470
}
471

    
472
static char *get_sym_name(EXE_SYM *sym)
473
{
474
    return strtab + sym->st_name;
475
}
476

    
477
/* load an elf object file */
478
int load_object(const char *filename)
479
{
480
    int fd;
481
    struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
482
    int i, j;
483
    ElfW(Sym) *sym;
484
    char *shstr;
485
    ELF_RELOC *rel;
486

    
487
    fd = open(filename, O_RDONLY);
488
    if (fd < 0)
489
        error("can't open file '%s'", filename);
490

    
491
    /* Read ELF header.  */
492
    if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
493
        error("unable to read file header");
494

    
495
    /* Check ELF identification.  */
496
    if (ehdr.e_ident[EI_MAG0] != ELFMAG0
497
     || ehdr.e_ident[EI_MAG1] != ELFMAG1
498
     || ehdr.e_ident[EI_MAG2] != ELFMAG2
499
     || ehdr.e_ident[EI_MAG3] != ELFMAG3
500
     || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
501
        error("bad ELF header");
502
    }
503

    
504
    do_swap = elf_must_swap(&ehdr);
505
    if (do_swap)
506
        elf_swap_ehdr(&ehdr);
507
    if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
508
        error("Unsupported ELF class");
509
    if (ehdr.e_type != ET_REL)
510
        error("ELF object file expected");
511
    if (ehdr.e_version != EV_CURRENT)
512
        error("Invalid ELF version");
513
    if (!elf_check_arch(ehdr.e_machine))
514
        error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
515

    
516
    /* read section headers */
517
    shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
518
    if (do_swap) {
519
        for(i = 0; i < ehdr.e_shnum; i++) {
520
            elf_swap_shdr(&shdr[i]);
521
        }
522
    }
523

    
524
    /* read all section data */
525
    sdata = malloc(sizeof(void *) * ehdr.e_shnum);
526
    memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
527

    
528
    for(i = 0;i < ehdr.e_shnum; i++) {
529
        sec = &shdr[i];
530
        if (sec->sh_type != SHT_NOBITS)
531
            sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
532
    }
533

    
534
    sec = &shdr[ehdr.e_shstrndx];
535
    shstr = (char *)sdata[ehdr.e_shstrndx];
536

    
537
    /* swap relocations */
538
    for(i = 0; i < ehdr.e_shnum; i++) {
539
        sec = &shdr[i];
540
        if (sec->sh_type == SHT_RELOC) {
541
            nb_relocs = sec->sh_size / sec->sh_entsize;
542
            if (do_swap) {
543
                for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
544
                    elf_swap_rel(rel);
545
            }
546
        }
547
    }
548
    /* text section */
549

    
550
    text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
551
    if (!text_sec)
552
        error("could not find .text section");
553
    text_shndx = text_sec - shdr;
554
    text = sdata[text_shndx];
555

    
556
    /* find text relocations, if any */
557
    relocs = NULL;
558
    nb_relocs = 0;
559
    i = find_reloc(text_shndx);
560
    if (i != 0) {
561
        relocs = (ELF_RELOC *)sdata[i];
562
        nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
563
    }
564

    
565
    symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
566
    if (!symtab_sec)
567
        error("could not find .symtab section");
568
    strtab_sec = &shdr[symtab_sec->sh_link];
569

    
570
    symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
571
    strtab = (char *)sdata[symtab_sec->sh_link];
572

    
573
    nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
574
    if (do_swap) {
575
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
576
            swab32s(&sym->st_name);
577
            swabls(&sym->st_value);
578
            swabls(&sym->st_size);
579
            swab16s(&sym->st_shndx);
580
        }
581
    }
582
    close(fd);
583
    return 0;
584
}
585

    
586
#endif /* CONFIG_FORMAT_ELF */
587

    
588
#ifdef CONFIG_FORMAT_COFF
589

    
590
/* COFF file info */
591
struct external_scnhdr *shdr;
592
uint8_t **sdata;
593
struct external_filehdr fhdr;
594
struct external_syment *coff_symtab;
595
char *strtab;
596
int coff_text_shndx, coff_data_shndx;
597

    
598
int data_shndx;
599

    
600
#define STRTAB_SIZE 4
601

    
602
#define DIR32   0x06
603
#define DISP32  0x14
604

    
605
#define T_FUNCTION  0x20
606
#define C_EXTERNAL  2
607

    
608
void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
609
{
610
    char *q;
611
    int c, i, len;
612

    
613
    if (ext_sym->e.e.e_zeroes != 0) {
614
        q = sym->st_name;
615
        for(i = 0; i < 8; i++) {
616
            c = ext_sym->e.e_name[i];
617
            if (c == '\0')
618
                break;
619
            *q++ = c;
620
        }
621
        *q = '\0';
622
    } else {
623
        pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
624
    }
625

    
626
    /* now convert the name to a C name (suppress the leading '_') */
627
    if (sym->st_name[0] == '_') {
628
        len = strlen(sym->st_name);
629
        memmove(sym->st_name, sym->st_name + 1, len - 1);
630
        sym->st_name[len - 1] = '\0';
631
    }
632
}
633

    
634
char *name_for_dotdata(struct coff_rel *rel)
635
{
636
        int i;
637
        struct coff_sym *sym;
638
        uint32_t text_data;
639

    
640
        text_data = *(uint32_t *)(text + rel->r_offset);
641

    
642
        for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
643
                if (sym->st_syment->e_scnum == data_shndx &&
644
                    text_data >= sym->st_value &&
645
                    text_data < sym->st_value + sym->st_size) {
646

    
647
                    return sym->st_name;
648

    
649
                }
650
        }
651
        return NULL;
652
}
653

    
654
static char *get_sym_name(EXE_SYM *sym)
655
{
656
    return sym->st_name;
657
}
658

    
659
static char *get_rel_sym_name(EXE_RELOC *rel)
660
{
661
    char *name;
662
    name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
663
    if (!strcmp(name, ".data"))
664
        name = name_for_dotdata(rel);
665
    if (name[0] == '.')
666
        return NULL;
667
    return name;
668
}
669

    
670
static host_ulong get_rel_offset(EXE_RELOC *rel)
671
{
672
    return rel->r_offset;
673
}
674

    
675
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
676
{
677
    int i;
678
    const char *shname;
679
    struct external_scnhdr *sec;
680

    
681
    for(i = 0; i < shnum; i++) {
682
        sec = &shdr[i];
683
        if (!sec->s_name)
684
            continue;
685
        shname = sec->s_name;
686
        if (!strcmp(shname, name))
687
            return sec;
688
    }
689
    return NULL;
690
}
691

    
692
/* load a coff object file */
693
int load_object(const char *filename)
694
{
695
    int fd;
696
    struct external_scnhdr *sec, *text_sec, *data_sec;
697
    int i;
698
    struct external_syment *ext_sym;
699
    struct external_reloc *coff_relocs;
700
    struct external_reloc *ext_rel;
701
    uint32_t *n_strtab;
702
    EXE_SYM *sym;
703
    EXE_RELOC *rel;
704
    const char *p;
705
    int aux_size, j;
706

    
707
    fd = open(filename, O_RDONLY
708
#ifdef _WIN32
709
              | O_BINARY
710
#endif
711
              );
712
    if (fd < 0)
713
        error("can't open file '%s'", filename);
714

    
715
    /* Read COFF header.  */
716
    if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
717
        error("unable to read file header");
718

    
719
    /* Check COFF identification.  */
720
    if (fhdr.f_magic != I386MAGIC) {
721
        error("bad COFF header");
722
    }
723
    do_swap = 0;
724

    
725
    /* read section headers */
726
    shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
727

    
728
    /* read all section data */
729
    sdata = malloc(sizeof(void *) * fhdr.f_nscns);
730
    memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
731

    
732
    for(i = 0;i < fhdr.f_nscns; i++) {
733
        sec = &shdr[i];
734
        if (!strstart(sec->s_name,  ".bss", &p))
735
            sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
736
    }
737

    
738

    
739
    /* text section */
740
    text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
741
    if (!text_sec)
742
        error("could not find .text section");
743
    coff_text_shndx = text_sec - shdr;
744
    text = sdata[coff_text_shndx];
745

    
746
    /* data section */
747
    data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
748
    if (!data_sec)
749
        error("could not find .data section");
750
    coff_data_shndx = data_sec - shdr;
751

    
752
    coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
753
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
754
        for(i=0;i<8;i++)
755
            printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
756
        printf("\n");
757
    }
758

    
759

    
760
    n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
761
    strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
762

    
763
    nb_syms = fhdr.f_nsyms;
764

    
765
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
766
      if (strstart(ext_sym->e.e_name, ".text", NULL))
767
                  text_shndx = ext_sym->e_scnum;
768
          if (strstart(ext_sym->e.e_name, ".data", NULL))
769
                  data_shndx = ext_sym->e_scnum;
770
    }
771

    
772
        /* set coff symbol */
773
        symtab = malloc(sizeof(struct coff_sym) * nb_syms);
774

    
775
        for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
776
                memset(sym, 0, sizeof(*sym));
777
                sym->st_syment = ext_sym;
778
                sym_ent_name(ext_sym, sym);
779
                sym->st_value = ext_sym->e_value;
780

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

    
809
                sym->st_type = ext_sym->e_type;
810
                sym->st_shndx = ext_sym->e_scnum;
811
        }
812

    
813

    
814
    /* find text relocations, if any */
815
    sec = &shdr[coff_text_shndx];
816
    coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
817
    nb_relocs = sec->s_nreloc;
818

    
819
    /* set coff relocation */
820
    relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
821
    for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
822
         i++, ext_rel++, rel++) {
823
        memset(rel, 0, sizeof(*rel));
824
        rel->r_reloc = ext_rel;
825
        rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
826
        rel->r_type = *(uint16_t *)ext_rel->r_type;
827
    }
828
    return 0;
829
}
830

    
831
#endif /* CONFIG_FORMAT_COFF */
832

    
833
#ifdef CONFIG_FORMAT_MACH
834

    
835
/* File Header */
836
struct mach_header         mach_hdr;
837

    
838
/* commands */
839
struct segment_command         *segment = 0;
840
struct dysymtab_command *dysymtabcmd = 0;
841
struct symtab_command         *symtabcmd = 0;
842

    
843
/* section */
844
struct section         *section_hdr;
845
struct section *text_sec_hdr;
846
uint8_t         **sdata;
847

    
848
/* relocs */
849
struct relocation_info *relocs;
850

    
851
/* symbols */
852
EXE_SYM                        *symtab;
853
struct nlist         *symtab_std;
854
char                        *strtab;
855

    
856
/* indirect symbols */
857
uint32_t         *tocdylib;
858

    
859
/* Utility functions */
860

    
861
static inline char *find_str_by_index(int index)
862
{
863
    return strtab+index;
864
}
865

    
866
/* Used by dyngen common code */
867
static char *get_sym_name(EXE_SYM *sym)
868
{
869
        char *name = find_str_by_index(sym->n_un.n_strx);
870

    
871
        if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
872
                return "debug";
873

    
874
        if(!name)
875
                return name;
876
        if(name[0]=='_')
877
                return name + 1;
878
        else
879
                return name;
880
}
881

    
882
/* find a section index given its segname, sectname */
883
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
884
                                  const char *sectname)
885
{
886
    int i;
887
    struct section *sec = section_hdr;
888

    
889
    for(i = 0; i < shnum; i++, sec++) {
890
        if (!sec->segname || !sec->sectname)
891
            continue;
892
        if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
893
            return i;
894
    }
895
    return -1;
896
}
897

    
898
/* find a section header given its segname, sectname */
899
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
900
                                  const char *sectname)
901
{
902
    int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
903
        if(index == -1)
904
                return NULL;
905
        return section_hdr+index;
906
}
907

    
908

    
909
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
910
{
911
    struct scattered_relocation_info * scarel;
912

    
913
    if(R_SCATTERED & rel->r_address) {
914
        scarel = (struct scattered_relocation_info*)rel;
915
        if(scarel->r_type != PPC_RELOC_PAIR)
916
            error("fetch_next_pair_value: looking for a pair which was not found (1)");
917
        *value = scarel->r_value;
918
    } else {
919
                if(rel->r_type != PPC_RELOC_PAIR)
920
                        error("fetch_next_pair_value: looking for a pair which was not found (2)");
921
                *value = rel->r_address;
922
        }
923
}
924

    
925
/* find a sym name given its value, in a section number */
926
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
927
{
928
        int i, ret = -1;
929

    
930
        for( i = 0 ; i < nb_syms; i++ )
931
        {
932
            if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
933
                         (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
934
                {
935
                        if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
936
                                ret = i;
937
                }
938
        }
939
        if( ret < 0 ) {
940
                *offset = 0;
941
                return 0;
942
        } else {
943
                *offset = value - symtab[ret].st_value;
944
                return get_sym_name(&symtab[ret]);
945
        }
946
}
947

    
948
/*
949
 *  Find symbol name given a (virtual) address, and a section which is of type
950
 *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
951
 */
952
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
953
{
954
    unsigned int tocindex, symindex, size;
955
    const char *name = 0;
956

    
957
    /* Sanity check */
958
    if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
959
        return (char*)0;
960

    
961
        if( sec_hdr->flags & S_SYMBOL_STUBS ){
962
                size = sec_hdr->reserved2;
963
                if(size == 0)
964
                    error("size = 0");
965

    
966
        }
967
        else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
968
                    sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
969
                size = sizeof(unsigned long);
970
        else
971
                return 0;
972

    
973
    /* Compute our index in toc */
974
        tocindex = (address - sec_hdr->addr)/size;
975
        symindex = tocdylib[sec_hdr->reserved1 + tocindex];
976

    
977
        name = get_sym_name(&symtab[symindex]);
978

    
979
    return name;
980
}
981

    
982
static const char * find_reloc_name_given_its_address(int address)
983
{
984
    unsigned int i;
985
    for(i = 0; i < segment->nsects ; i++)
986
    {
987
        const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
988
        if((long)name != -1)
989
            return name;
990
    }
991
    return 0;
992
}
993

    
994
static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
995
{
996
        char * name = 0;
997
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
998
        int sectnum = rel->r_symbolnum;
999
        int sectoffset;
1000
        int other_half=0;
1001

    
1002
        /* init the slide value */
1003
        *sslide = 0;
1004

    
1005
        if(R_SCATTERED & rel->r_address)
1006
                return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1007

    
1008
        if(rel->r_extern)
1009
        {
1010
                /* ignore debug sym */
1011
                if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1012
                        return 0;
1013
                return get_sym_name(&symtab[rel->r_symbolnum]);
1014
        }
1015

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

    
1019
        if(sectnum==0xffffff)
1020
                return 0;
1021

    
1022
        /* Sanity Check */
1023
        if(sectnum > segment->nsects)
1024
                error("sectnum > segment->nsects");
1025

    
1026
        switch(rel->r_type)
1027
        {
1028
                case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1029
                        break;
1030
                case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1031
                        break;
1032
                case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1033
                        break;
1034
                case PPC_RELOC_BR24:
1035
                        sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1036
                        if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1037
                        break;
1038
                default:
1039
                        error("switch(rel->type) not found");
1040
        }
1041

    
1042
        if(rel->r_pcrel)
1043
                sectoffset += rel->r_address;
1044

    
1045
        if (rel->r_type == PPC_RELOC_BR24)
1046
                name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1047

    
1048
        /* search it in the full symbol list, if not found */
1049
        if(!name)
1050
                name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1051

    
1052
        return name;
1053
}
1054

    
1055
/* Used by dyngen common code */
1056
static const char * get_rel_sym_name(EXE_RELOC * rel)
1057
{
1058
        int sslide;
1059
        return get_reloc_name( rel, &sslide);
1060
}
1061

    
1062
/* Used by dyngen common code */
1063
static host_ulong get_rel_offset(EXE_RELOC *rel)
1064
{
1065
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1066
    if(R_SCATTERED & rel->r_address)
1067
                return sca_rel->r_address;
1068
        else
1069
                return rel->r_address;
1070
}
1071

    
1072
/* load a mach-o object file */
1073
int load_object(const char *filename)
1074
{
1075
        int fd;
1076
        unsigned int offset_to_segment = 0;
1077
    unsigned int offset_to_dysymtab = 0;
1078
    unsigned int offset_to_symtab = 0;
1079
    struct load_command lc;
1080
    unsigned int i, j;
1081
        EXE_SYM *sym;
1082
        struct nlist *syment;
1083

    
1084
        fd = open(filename, O_RDONLY);
1085
    if (fd < 0)
1086
        error("can't open file '%s'", filename);
1087

    
1088
    /* Read Mach header.  */
1089
    if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1090
        error("unable to read file header");
1091

    
1092
    /* Check Mach identification.  */
1093
    if (!check_mach_header(mach_hdr)) {
1094
        error("bad Mach header");
1095
    }
1096

    
1097
    if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1098
        error("Unsupported CPU");
1099

    
1100
    if (mach_hdr.filetype != MH_OBJECT)
1101
        error("Unsupported Mach Object");
1102

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

    
1134
        lseek(fd, j, SEEK_SET);
1135
    }
1136

    
1137
    if(!segment)
1138
        error("unable to find LC_SEGMENT");
1139

    
1140
    /* read section headers */
1141
    section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1142

    
1143
    /* read all section data */
1144
    sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1145
    memset(sdata, 0, sizeof(void *) * segment->nsects);
1146

    
1147
        /* Load the data in section data */
1148
        for(i = 0; i < segment->nsects; i++) {
1149
        sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1150
    }
1151

    
1152
    /* text section */
1153
        text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1154
        i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1155
        if (i == -1 || !text_sec_hdr)
1156
        error("could not find __TEXT,__text section");
1157
    text = sdata[i];
1158

    
1159
    /* Make sure dysym was loaded */
1160
    if(!(int)dysymtabcmd)
1161
        error("could not find __DYSYMTAB segment");
1162

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

    
1166
    /* Make sure symtab was loaded  */
1167
    if(!(int)symtabcmd)
1168
        error("could not find __SYMTAB segment");
1169
    nb_syms = symtabcmd->nsyms;
1170

    
1171
    symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1172
    strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1173

    
1174
        symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1175

    
1176
        /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1177
        for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1178
        struct nlist *sym_follow, *sym_next = 0;
1179
        unsigned int j;
1180
                memset(sym, 0, sizeof(*sym));
1181

    
1182
                if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1183
            continue;
1184

    
1185
                memcpy(sym, syment, sizeof(*syment));
1186

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

    
1205
    /* Find Reloc */
1206
    relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1207
    nb_relocs = text_sec_hdr->nreloc;
1208

    
1209
        close(fd);
1210
        return 0;
1211
}
1212

    
1213
#endif /* CONFIG_FORMAT_MACH */
1214

    
1215
/* return true if the expression is a label reference */
1216
int get_reloc_expr(char *name, int name_size, const char *sym_name)
1217
{
1218
    const char *p;
1219

    
1220
    if (strstart(sym_name, "__op_param", &p)) {
1221
        snprintf(name, name_size, "param%s", p);
1222
    } else if (strstart(sym_name, "__op_gen_label", &p)) {
1223
        snprintf(name, name_size, "param%s", p);
1224
        return 1;
1225
    } else {
1226
#ifdef HOST_SPARC
1227
        if (sym_name[0] == '.')
1228
            snprintf(name, name_size,
1229
                     "(long)(&__dot_%s)",
1230
                     sym_name + 1);
1231
        else
1232
#endif
1233
            snprintf(name, name_size, "(long)(&%s)", sym_name);
1234
    }
1235
    return 0;
1236
}
1237

    
1238
#ifdef HOST_IA64
1239

    
1240
#define PLT_ENTRY_SIZE        16        /* 1 bundle containing "brl" */
1241

    
1242
struct plt_entry {
1243
    struct plt_entry *next;
1244
    const char *name;
1245
    unsigned long addend;
1246
} *plt_list;
1247

    
1248
static int
1249
get_plt_index (const char *name, unsigned long addend)
1250
{
1251
    struct plt_entry *plt, *prev= NULL;
1252
    int index = 0;
1253

    
1254
    /* see if we already have an entry for this target: */
1255
    for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1256
        if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1257
            return index;
1258

    
1259
    /* nope; create a new PLT entry: */
1260

    
1261
    plt = malloc(sizeof(*plt));
1262
    if (!plt) {
1263
        perror("malloc");
1264
        exit(1);
1265
    }
1266
    memset(plt, 0, sizeof(*plt));
1267
    plt->name = strdup(name);
1268
    plt->addend = addend;
1269

    
1270
    /* append to plt-list: */
1271
    if (prev)
1272
        prev->next = plt;
1273
    else
1274
        plt_list = plt;
1275
    return index;
1276
}
1277

    
1278
#endif
1279

    
1280
#ifdef HOST_ARM
1281

    
1282
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1283
                      FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1284
                      ELF_RELOC *relocs, int nb_relocs)
1285
{
1286
    uint8_t *p;
1287
    uint32_t insn;
1288
    int offset, min_offset, pc_offset, data_size, spare, max_pool;
1289
    uint8_t data_allocated[1024];
1290
    unsigned int data_index;
1291
    int type;
1292

    
1293
    memset(data_allocated, 0, sizeof(data_allocated));
1294

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

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

    
1364
    /* Copy and relocate the constant pool data.  */
1365
    data_size = (p_end - p_start) - min_offset;
1366
    if (data_size > 0 && outfile) {
1367
        spare += min_offset;
1368
        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1369
        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1370
        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1371
                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
1372
                         spare, spare);
1373

    
1374
        data_index = 0;
1375
        for (pc_offset = min_offset;
1376
             pc_offset < p_end - p_start;
1377
             pc_offset += 4) {
1378

    
1379
            ELF_RELOC *rel;
1380
            int i, addend, type;
1381
            const char *sym_name;
1382
            char relname[1024];
1383

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

    
1404
            data_index++;
1405
        }
1406
    }
1407

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

    
1434

    
1435
#define MAX_ARGS 3
1436

    
1437
/* generate op code */
1438
void gen_code(const char *name, host_ulong offset, host_ulong size,
1439
              FILE *outfile, int gen_switch)
1440
{
1441
    int copy_size = 0;
1442
    uint8_t *p_start, *p_end;
1443
    host_ulong start_offset;
1444
    int nb_args, i, n;
1445
    uint8_t args_present[MAX_ARGS];
1446
    const char *sym_name, *p;
1447
    EXE_RELOC *rel;
1448

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

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

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

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

    
1611
                error("ret; restore; not found at end of %s", name);
1612
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1613
            ;
1614
        } else {
1615
            error("No save at the beginning of %s", name);
1616
        }
1617

    
1618
#if 0
1619
        /* Skip a preceeding nop, if present.  */
1620
        if (p > p_start) {
1621
            skip_insn = get32((uint32_t *)(p - 0x4));
1622
            if (skip_insn == 0x01000000)
1623
                p -= 4;
1624
        }
1625
#endif
1626

    
1627
        copy_size = p - p_start;
1628
    }
1629
#elif defined(HOST_ARM)
1630
    {
1631
        uint32_t insn;
1632

    
1633
        if ((p_end - p_start) <= 16)
1634
            error("%s: function too small", name);
1635
        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1636
            (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1637
            get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1638
            error("%s: invalid prolog", name);
1639
        p_start += 12;
1640
        start_offset += 12;
1641
        insn = get32((uint32_t *)p_start);
1642
        if ((insn & 0xffffff00) == 0xe24dd000) {
1643
            /* Stack adjustment.  Assume op uses the frame pointer.  */
1644
            p_start -= 4;
1645
            start_offset -= 4;
1646
        }
1647
        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1648
                                      relocs, nb_relocs);
1649
    }
1650
#elif defined(HOST_M68K)
1651
    {
1652
        uint8_t *p;
1653
        p = (void *)(p_end - 2);
1654
        if (p == p_start)
1655
            error("empty code for %s", name);
1656
        // remove NOP's, probably added for alignment
1657
        while ((get16((uint16_t *)p) == 0x4e71) &&
1658
               (p>p_start))
1659
            p -= 2;
1660
        if (get16((uint16_t *)p) != 0x4e75)
1661
            error("rts expected at the end of %s", name);
1662
        copy_size = p - p_start;
1663
    }
1664
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1665
    {
1666
#define INSN_RETURN     0x03e00008
1667
#define INSN_NOP        0x00000000
1668

    
1669
        uint8_t *p = p_end;
1670

    
1671
        if (p < (p_start + 0x8)) {
1672
            error("empty code for %s", name);
1673
        } else {
1674
            uint32_t end_insn1, end_insn2;
1675

    
1676
            p -= 0x8;
1677
            end_insn1 = get32((uint32_t *)(p + 0x0));
1678
            end_insn2 = get32((uint32_t *)(p + 0x4));
1679
            if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1680
                error("jr ra not found at end of %s", name);
1681
        }
1682
        copy_size = p - p_start;
1683
    }
1684
#else
1685
#error unsupported CPU
1686
#endif
1687

    
1688
    /* compute the number of arguments by looking at the relocations */
1689
    for(i = 0;i < MAX_ARGS; i++)
1690
        args_present[i] = 0;
1691

    
1692
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1693
        host_ulong offset = get_rel_offset(rel);
1694
        if (offset >= start_offset &&
1695
            offset < start_offset + (p_end - p_start)) {
1696
            sym_name = get_rel_sym_name(rel);
1697
            if(!sym_name)
1698
                continue;
1699
            if (strstart(sym_name, "__op_param", &p) ||
1700
                strstart(sym_name, "__op_gen_label", &p)) {
1701
                n = strtoul(p, NULL, 10);
1702
                if (n > MAX_ARGS)
1703
                    error("too many arguments in %s", name);
1704
                args_present[n - 1] = 1;
1705
            }
1706
        }
1707
    }
1708

    
1709
    nb_args = 0;
1710
    while (nb_args < MAX_ARGS && args_present[nb_args])
1711
        nb_args++;
1712
    for(i = nb_args; i < MAX_ARGS; i++) {
1713
        if (args_present[i])
1714
            error("inconsistent argument numbering in %s", name);
1715
    }
1716

    
1717
    if (gen_switch == 2) {
1718
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1719
    } else if (gen_switch == 1) {
1720

    
1721
        /* output C code */
1722
        fprintf(outfile, "case INDEX_%s: {\n", name);
1723
        if (nb_args > 0) {
1724
            fprintf(outfile, "    long ");
1725
            for(i = 0; i < nb_args; i++) {
1726
                if (i != 0)
1727
                    fprintf(outfile, ", ");
1728
                fprintf(outfile, "param%d", i + 1);
1729
            }
1730
            fprintf(outfile, ";\n");
1731
        }
1732
#if defined(HOST_IA64)
1733
        fprintf(outfile, "    extern char %s;\n", name);
1734
#else
1735
        fprintf(outfile, "    extern void %s();\n", name);
1736
#endif
1737

    
1738
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1739
            host_ulong offset = get_rel_offset(rel);
1740
            if (offset >= start_offset &&
1741
                offset < start_offset + (p_end - p_start)) {
1742
                sym_name = get_rel_sym_name(rel);
1743
                if(!sym_name)
1744
                    continue;
1745
                if (*sym_name &&
1746
                    !strstart(sym_name, "__op_param", NULL) &&
1747
                    !strstart(sym_name, "__op_jmp", NULL) &&
1748
                    !strstart(sym_name, "__op_gen_label", NULL)) {
1749
#if defined(HOST_SPARC)
1750
                    if (sym_name[0] == '.') {
1751
                        fprintf(outfile,
1752
                                "extern char __dot_%s __asm__(\"%s\");\n",
1753
                                sym_name+1, sym_name);
1754
                        continue;
1755
                    }
1756
#endif
1757
#if defined(__APPLE__)
1758
                    /* Set __attribute((unused)) on darwin because we
1759
                       want to avoid warning when we don't use the symbol.  */
1760
                    fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
1761
#elif defined(HOST_IA64)
1762
                        if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1763
                                /*
1764
                                 * PCREL21 br.call targets generally
1765
                                 * are out of range and need to go
1766
                                 * through an "import stub".
1767
                                 */
1768
                                fprintf(outfile, "    extern char %s;\n",
1769
                                        sym_name);
1770
#else
1771
                    fprintf(outfile, "extern char %s;\n", sym_name);
1772
#endif
1773
                }
1774
            }
1775
        }
1776

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

    
1780
        /* emit code offset information */
1781
        {
1782
            EXE_SYM *sym;
1783
            const char *sym_name, *p;
1784
            host_ulong val;
1785
            int n;
1786

    
1787
            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1788
                sym_name = get_sym_name(sym);
1789
                if (strstart(sym_name, "__op_label", &p)) {
1790
                    uint8_t *ptr;
1791
                    unsigned long offset;
1792

    
1793
                    /* test if the variable refers to a label inside
1794
                       the code we are generating */
1795
#ifdef CONFIG_FORMAT_COFF
1796
                    if (sym->st_shndx == text_shndx) {
1797
                        ptr = sdata[coff_text_shndx];
1798
                    } else if (sym->st_shndx == data_shndx) {
1799
                        ptr = sdata[coff_data_shndx];
1800
                    } else {
1801
                        ptr = NULL;
1802
                    }
1803
#elif defined(CONFIG_FORMAT_MACH)
1804
                    if(!sym->n_sect)
1805
                        continue;
1806
                    ptr = sdata[sym->n_sect-1];
1807
#else
1808
                    ptr = sdata[sym->st_shndx];
1809
#endif
1810
                    if (!ptr)
1811
                        error("__op_labelN in invalid section");
1812
                    offset = sym->st_value;
1813
#ifdef CONFIG_FORMAT_MACH
1814
                    offset -= section_hdr[sym->n_sect-1].addr;
1815
#endif
1816
                    val = *(host_ulong *)(ptr + offset);
1817
#ifdef ELF_USES_RELOCA
1818
                    {
1819
                        int reloc_shndx, nb_relocs1, j;
1820

    
1821
                        /* try to find a matching relocation */
1822
                        reloc_shndx = find_reloc(sym->st_shndx);
1823
                        if (reloc_shndx) {
1824
                            nb_relocs1 = shdr[reloc_shndx].sh_size /
1825
                                shdr[reloc_shndx].sh_entsize;
1826
                            rel = (ELF_RELOC *)sdata[reloc_shndx];
1827
                            for(j = 0; j < nb_relocs1; j++) {
1828
                                if (rel->r_offset == offset) {
1829
                                    val = rel->r_addend;
1830
                                    break;
1831
                                }
1832
                                rel++;
1833
                            }
1834
                        }
1835
                    }
1836
#endif
1837
                    if (val >= start_offset && val <= start_offset + copy_size) {
1838
                        n = strtol(p, NULL, 10);
1839
                        fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1840
                    }
1841
                }
1842
            }
1843
        }
1844

    
1845
        /* load parameters in variables */
1846
        for(i = 0; i < nb_args; i++) {
1847
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1848
        }
1849

    
1850
        /* patch relocations */
1851
#if defined(HOST_I386)
1852
            {
1853
                char relname[256];
1854
                int type, is_label;
1855
                int addend;
1856
                int reloc_offset;
1857
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1858
                if (rel->r_offset >= start_offset &&
1859
                    rel->r_offset < start_offset + copy_size) {
1860
                    sym_name = get_rel_sym_name(rel);
1861
                    if (!sym_name)
1862
                        continue;
1863
                    reloc_offset = rel->r_offset - start_offset;
1864
                    if (strstart(sym_name, "__op_jmp", &p)) {
1865
                        int n;
1866
                        n = strtol(p, NULL, 10);
1867
                        /* __op_jmp relocations are done at
1868
                           runtime to do translated block
1869
                           chaining: the offset of the instruction
1870
                           needs to be stored */
1871
                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1872
                                n, reloc_offset);
1873
                        continue;
1874
                    }
1875

    
1876
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1877
                    addend = get32((uint32_t *)(text + rel->r_offset));
1878
#ifdef CONFIG_FORMAT_ELF
1879
                    type = ELF32_R_TYPE(rel->r_info);
1880
                    if (is_label) {
1881
                        switch(type) {
1882
                        case R_386_32:
1883
                        case R_386_PC32:
1884
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1885
                                    reloc_offset, type, relname, addend);
1886
                            break;
1887
                        default:
1888
                            error("unsupported i386 relocation (%d)", type);
1889
                        }
1890
                    } else {
1891
                        switch(type) {
1892
                        case R_386_32:
1893
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1894
                                    reloc_offset, relname, addend);
1895
                            break;
1896
                        case R_386_PC32:
1897
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1898
                                    reloc_offset, relname, reloc_offset, addend);
1899
                            break;
1900
                        default:
1901
                            error("unsupported i386 relocation (%d)", type);
1902
                        }
1903
                    }
1904
#elif defined(CONFIG_FORMAT_COFF)
1905
                    {
1906
                        char *temp_name;
1907
                        int j;
1908
                        EXE_SYM *sym;
1909
                        temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1910
                        if (!strcmp(temp_name, ".data")) {
1911
                            for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1912
                                if (strstart(sym->st_name, sym_name, NULL)) {
1913
                                    addend -= sym->st_value;
1914
                                }
1915
                            }
1916
                        }
1917
                    }
1918
                    type = rel->r_type;
1919
                    if (is_label) {
1920
/* TCG uses elf relocation constants */
1921
#define R_386_32        1
1922
#define R_386_PC32        2
1923
                        switch(type) {
1924
                        case DIR32:
1925
                            type = R_386_32;
1926
                            goto do_reloc;
1927
                        case DISP32:
1928
                            type = R_386_PC32;
1929
                            addend -= 4;
1930
                        do_reloc:
1931
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1932
                                    reloc_offset, type, relname, addend);
1933
                            break;
1934
                        default:
1935
                            error("unsupported i386 relocation (%d)", type);
1936
                        }
1937
                    } else {
1938
                        switch(type) {
1939
                        case DIR32:
1940
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1941
                                    reloc_offset, relname, addend);
1942
                            break;
1943
                        case DISP32:
1944
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1945
                                    reloc_offset, relname, reloc_offset, addend);
1946
                            break;
1947
                        default:
1948
                            error("unsupported i386 relocation (%d)", type);
1949
                        }
1950
                    }
1951
#else
1952
#error unsupport object format
1953
#endif
1954
                }
1955
                }
1956
            }
1957
#elif defined(HOST_X86_64)
1958
            {
1959
                char relname[256];
1960
                int type, is_label;
1961
                int addend;
1962
                int reloc_offset;
1963
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1964
                if (rel->r_offset >= start_offset &&
1965
                    rel->r_offset < start_offset + copy_size) {
1966
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1967
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1968
                    type = ELF32_R_TYPE(rel->r_info);
1969
                    addend = rel->r_addend;
1970
                    reloc_offset = rel->r_offset - start_offset;
1971
                    if (is_label) {
1972
                        switch(type) {
1973
                        case R_X86_64_32:
1974
                        case R_X86_64_32S:
1975
                        case R_X86_64_PC32:
1976
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1977
                                    reloc_offset, type, relname, addend);
1978
                            break;
1979
                        default:
1980
                            error("unsupported X86_64 relocation (%d)", type);
1981
                        }
1982
                    } else {
1983
                        switch(type) {
1984
                        case R_X86_64_32:
1985
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1986
                                    reloc_offset, relname, addend);
1987
                            break;
1988
                        case R_X86_64_32S:
1989
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1990
                                    reloc_offset, relname, addend);
1991
                            break;
1992
                        case R_X86_64_PC32:
1993
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1994
                                    reloc_offset, relname, reloc_offset, addend);
1995
                            break;
1996
                        default:
1997
                            error("unsupported X86_64 relocation (%d)", type);
1998
                        }
1999
                    }
2000
                }
2001
                }
2002
            }
2003
#elif defined(HOST_PPC)
2004
            {
2005
#ifdef CONFIG_FORMAT_ELF
2006
                char relname[256];
2007
                int type;
2008
                int addend;
2009
                int reloc_offset;
2010
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2011
                    if (rel->r_offset >= start_offset &&
2012
                        rel->r_offset < start_offset + copy_size) {
2013
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2014
                        reloc_offset = rel->r_offset - start_offset;
2015
                        if (strstart(sym_name, "__op_jmp", &p)) {
2016
                            int n;
2017
                            n = strtol(p, NULL, 10);
2018
                            /* __op_jmp relocations are done at
2019
                               runtime to do translated block
2020
                               chaining: the offset of the instruction
2021
                               needs to be stored */
2022
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2023
                                    n, reloc_offset);
2024
                            continue;
2025
                        }
2026

    
2027
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2028
                        type = ELF32_R_TYPE(rel->r_info);
2029
                        addend = rel->r_addend;
2030
                        switch(type) {
2031
                        case R_PPC_ADDR32:
2032
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2033
                                    reloc_offset, relname, addend);
2034
                            break;
2035
                        case R_PPC_ADDR16_LO:
2036
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2037
                                    reloc_offset, relname, addend);
2038
                            break;
2039
                        case R_PPC_ADDR16_HI:
2040
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2041
                                    reloc_offset, relname, addend);
2042
                            break;
2043
                        case R_PPC_ADDR16_HA:
2044
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2045
                                    reloc_offset, relname, addend);
2046
                            break;
2047
                        case R_PPC_REL24:
2048
                            /* warning: must be at 32 MB distancy */
2049
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2050
                                    reloc_offset, reloc_offset, relname, reloc_offset, addend);
2051
                            break;
2052
                        default:
2053
                            error("unsupported powerpc relocation (%d)", type);
2054
                        }
2055
                    }
2056
                }
2057
#elif defined(CONFIG_FORMAT_MACH)
2058
                struct scattered_relocation_info *scarel;
2059
                struct relocation_info * rel;
2060
                char final_sym_name[256];
2061
                const char *sym_name;
2062
                const char *p;
2063
                int slide, sslide;
2064
                int i;
2065

    
2066
                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2067
                    unsigned int offset, length, value = 0;
2068
                    unsigned int type, pcrel, isym = 0;
2069
                    unsigned int usesym = 0;
2070

    
2071
                    if(R_SCATTERED & rel->r_address) {
2072
                        scarel = (struct scattered_relocation_info*)rel;
2073
                        offset = (unsigned int)scarel->r_address;
2074
                        length = scarel->r_length;
2075
                        pcrel = scarel->r_pcrel;
2076
                        type = scarel->r_type;
2077
                        value = scarel->r_value;
2078
                    } else {
2079
                        value = isym = rel->r_symbolnum;
2080
                        usesym = (rel->r_extern);
2081
                        offset = rel->r_address;
2082
                        length = rel->r_length;
2083
                        pcrel = rel->r_pcrel;
2084
                        type = rel->r_type;
2085
                    }
2086

    
2087
                    slide = offset - start_offset;
2088

    
2089
                    if (!(offset >= start_offset && offset < start_offset + size))
2090
                        continue;  /* not in our range */
2091

    
2092
                        sym_name = get_reloc_name(rel, &sslide);
2093

    
2094
                        if(usesym && symtab[isym].n_type & N_STAB)
2095
                            continue; /* don't handle STAB (debug sym) */
2096

    
2097
                        if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2098
                            int n;
2099
                            n = strtol(p, NULL, 10);
2100
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2101
                                    n, slide);
2102
                            continue; /* Nothing more to do */
2103
                        }
2104

    
2105
                        if(!sym_name) {
2106
                            fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2107
                                    name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2108
                            continue; /* dunno how to handle without final_sym_name */
2109
                        }
2110

    
2111
                        get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2112
                                       sym_name);
2113
                        switch(type) {
2114
                        case PPC_RELOC_BR24:
2115
                            if (!strstart(sym_name,"__op_gen_label",&p)) {
2116
                                fprintf(outfile, "{\n");
2117
                                fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2118
                                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",
2119
                                        slide, slide, name, sslide);
2120
                                fprintf(outfile, "}\n");
2121
                            } else {
2122
                                fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2123
                                        slide, slide, final_sym_name, slide);
2124
                            }
2125
                            break;
2126
                        case PPC_RELOC_HI16:
2127
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2128
                                    slide, final_sym_name, sslide);
2129
                            break;
2130
                        case PPC_RELOC_LO16:
2131
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2132
                                    slide, final_sym_name, sslide);
2133
                            break;
2134
                        case PPC_RELOC_HA16:
2135
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2136
                                    slide, final_sym_name, sslide);
2137
                            break;
2138
                        default:
2139
                            error("unsupported powerpc relocation (%d)", type);
2140
                    }
2141
                }
2142
#else
2143
#error unsupport object format
2144
#endif
2145
            }
2146
#elif defined(HOST_S390)
2147
            {
2148
                char relname[256];
2149
                int type;
2150
                int addend;
2151
                int reloc_offset;
2152
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2153
                    if (rel->r_offset >= start_offset &&
2154
                        rel->r_offset < start_offset + copy_size) {
2155
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2156
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2157
                        type = ELF32_R_TYPE(rel->r_info);
2158
                        addend = rel->r_addend;
2159
                        reloc_offset = rel->r_offset - start_offset;
2160
                        switch(type) {
2161
                        case R_390_32:
2162
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2163
                                    reloc_offset, relname, addend);
2164
                            break;
2165
                        case R_390_16:
2166
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2167
                                    reloc_offset, relname, addend);
2168
                            break;
2169
                        case R_390_8:
2170
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2171
                                    reloc_offset, relname, addend);
2172
                            break;
2173
                        case R_390_PC32DBL:
2174
                            if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2175
                                fprintf(outfile,
2176
                                        "    *(uint32_t *)(gen_code_ptr + %d) += "
2177
                                        "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2178
                                        reloc_offset, name);
2179
                            }
2180
                            else
2181
                                fprintf(outfile,
2182
                                        "    *(uint32_t *)(gen_code_ptr + %d) = "
2183
                                        "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2184
                                        reloc_offset, relname, addend, reloc_offset);
2185
                            break;
2186
                        default:
2187
                            error("unsupported s390 relocation (%d)", type);
2188
                        }
2189
                    }
2190
                }
2191
            }
2192
#elif defined(HOST_ALPHA)
2193
            {
2194
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2195
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2196
                        int type;
2197
                        long reloc_offset;
2198

    
2199
                        type = ELF64_R_TYPE(rel->r_info);
2200
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2201
                        reloc_offset = rel->r_offset - start_offset;
2202
                        switch (type) {
2203
                        case R_ALPHA_GPDISP:
2204
                            /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2205
                               as an immediate instead of constructing it from the pv or ra.  */
2206
                            fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2207
                                    reloc_offset);
2208
                            fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2209
                                    reloc_offset + (int)rel->r_addend);
2210
                            break;
2211
                        case R_ALPHA_LITUSE:
2212
                            /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2213
                               now, since some called functions (libc) need pv to be set up.  */
2214
                            break;
2215
                        case R_ALPHA_HINT:
2216
                            /* Branch target prediction hint. Ignore for now.  Should be already
2217
                               correct for in-function jumps.  */
2218
                            break;
2219
                        case R_ALPHA_LITERAL:
2220
                            /* Load a literal from the GOT relative to the gp.  Since there's only a
2221
                               single gp, nothing is to be done.  */
2222
                            break;
2223
                        case R_ALPHA_GPRELHIGH:
2224
                            /* Handle fake relocations against __op_param symbol.  Need to emit the
2225
                               high part of the immediate value instead.  Other symbols need no
2226
                               special treatment.  */
2227
                            if (strstart(sym_name, "__op_param", &p))
2228
                                fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2229
                                        reloc_offset, p);
2230
                            break;
2231
                        case R_ALPHA_GPRELLOW:
2232
                            if (strstart(sym_name, "__op_param", &p))
2233
                                fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2234
                                        reloc_offset, p);
2235
                            break;
2236
                        case R_ALPHA_BRSGP:
2237
                            /* PC-relative jump. Tweak offset to skip the two instructions that try to
2238
                               set up the gp from the pv.  */
2239
                            fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2240
                                    reloc_offset, sym_name, reloc_offset);
2241
                            break;
2242
                        default:
2243
                            error("unsupported Alpha relocation (%d)", type);
2244
                        }
2245
                    }
2246
                }
2247
            }
2248
#elif defined(HOST_IA64)
2249
            {
2250
                unsigned long sym_idx;
2251
                long code_offset;
2252
                char relname[256];
2253
                int type;
2254
                long addend;
2255

    
2256
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2257
                    sym_idx = ELF64_R_SYM(rel->r_info);
2258
                    if (rel->r_offset < start_offset
2259
                        || rel->r_offset >= start_offset + copy_size)
2260
                        continue;
2261
                    sym_name = (strtab + symtab[sym_idx].st_name);
2262
                    code_offset = rel->r_offset - start_offset;
2263
                    if (strstart(sym_name, "__op_jmp", &p)) {
2264
                        int n;
2265
                        n = strtol(p, NULL, 10);
2266
                        /* __op_jmp relocations are done at
2267
                           runtime to do translated block
2268
                           chaining: the offset of the instruction
2269
                           needs to be stored */
2270
                        fprintf(outfile, "    jmp_offsets[%d] ="
2271
                                "%ld + (gen_code_ptr - gen_code_buf);\n",
2272
                                n, code_offset);
2273
                        continue;
2274
                    }
2275
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2276
                    type = ELF64_R_TYPE(rel->r_info);
2277
                    addend = rel->r_addend;
2278
                    switch(type) {
2279
                      case R_IA64_IMM64:
2280
                          fprintf(outfile,
2281
                                  "    ia64_imm64(gen_code_ptr + %ld, "
2282
                                  "%s + %ld);\n",
2283
                                  code_offset, relname, addend);
2284
                          break;
2285
                      case R_IA64_LTOFF22X:
2286
                      case R_IA64_LTOFF22:
2287
                          fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2288
                                  " %s + %ld, %d);\n",
2289
                                  code_offset, relname, addend,
2290
                                  (type == R_IA64_LTOFF22X));
2291
                          break;
2292
                      case R_IA64_LDXMOV:
2293
                          fprintf(outfile,
2294
                                  "    ia64_ldxmov(gen_code_ptr + %ld,"
2295
                                  " %s + %ld);\n", code_offset, relname, addend);
2296
                          break;
2297

    
2298
                      case R_IA64_PCREL21B:
2299
                          if (strstart(sym_name, "__op_gen_label", NULL)) {
2300
                              fprintf(outfile,
2301
                                      "    ia64_imm21b(gen_code_ptr + %ld,"
2302
                                      " (long) (%s + %ld -\n\t\t"
2303
                                      "((long) gen_code_ptr + %ld)) >> 4);\n",
2304
                                      code_offset, relname, addend,
2305
                                      code_offset & ~0xfUL);
2306
                          } else {
2307
                              fprintf(outfile,
2308
                                      "    IA64_PLT(gen_code_ptr + %ld, "
2309
                                      "%d);\t/* %s + %ld */\n",
2310
                                      code_offset,
2311
                                      get_plt_index(sym_name, addend),
2312
                                      sym_name, addend);
2313
                          }
2314
                          break;
2315
                      default:
2316
                          error("unsupported ia64 relocation (0x%x)",
2317
                                type);
2318
                    }
2319
                }
2320
                fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2321
                        copy_size - 16 + 2);
2322
            }
2323
#elif defined(HOST_SPARC)
2324
            {
2325
                char relname[256];
2326
                int type;
2327
                int addend;
2328
                int reloc_offset;
2329
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2330
                    if (rel->r_offset >= start_offset &&
2331
                        rel->r_offset < start_offset + copy_size) {
2332
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2333
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2334
                        type = ELF32_R_TYPE(rel->r_info);
2335
                        addend = rel->r_addend;
2336
                        reloc_offset = rel->r_offset - start_offset;
2337
                        switch(type) {
2338
                        case R_SPARC_32:
2339
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2340
                                    reloc_offset, relname, addend);
2341
                            break;
2342
                        case R_SPARC_HI22:
2343
                            fprintf(outfile,
2344
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2345
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2346
                                    " & ~0x3fffff) "
2347
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2348
                                    reloc_offset, reloc_offset, relname, addend);
2349
                            break;
2350
                        case R_SPARC_LO10:
2351
                            fprintf(outfile,
2352
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2353
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2354
                                    " & ~0x3ff) "
2355
                                    " | ((%s + %d) & 0x3ff);\n",
2356
                                    reloc_offset, reloc_offset, relname, addend);
2357
                            break;
2358
                        case R_SPARC_WDISP30:
2359
                            fprintf(outfile,
2360
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2361
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2362
                                    " & ~0x3fffffff) "
2363
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2364
                                    "    & 0x3fffffff);\n",
2365
                                    reloc_offset, reloc_offset, relname, addend,
2366
                                    reloc_offset);
2367
                            break;
2368
                        case R_SPARC_WDISP22:
2369
                            fprintf(outfile,
2370
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2371
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2372
                                    " & ~0x3fffff) "
2373
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2374
                                    "    & 0x3fffff);\n",
2375
                                    rel->r_offset - start_offset,
2376
                                    rel->r_offset - start_offset,
2377
                                    relname, addend,
2378
                                    rel->r_offset - start_offset);
2379
                            break;
2380
                        default:
2381
                            error("unsupported sparc relocation (%d)", type);
2382
                        }
2383
                    }
2384
                }
2385
            }
2386
#elif defined(HOST_SPARC64)
2387
            {
2388
                char relname[256];
2389
                int type;
2390
                int addend;
2391
                int reloc_offset;
2392
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2393
                    if (rel->r_offset >= start_offset &&
2394
                        rel->r_offset < start_offset + copy_size) {
2395
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2396
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2397
                        type = ELF32_R_TYPE(rel->r_info);
2398
                        addend = rel->r_addend;
2399
                        reloc_offset = rel->r_offset - start_offset;
2400
                        switch(type) {
2401
                        case R_SPARC_32:
2402
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2403
                                    reloc_offset, relname, addend);
2404
                            break;
2405
                        case R_SPARC_HI22:
2406
                            fprintf(outfile,
2407
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2408
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2409
                                    " & ~0x3fffff) "
2410
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2411
                                    reloc_offset, reloc_offset, relname, addend);
2412
                            break;
2413
                        case R_SPARC_LO10:
2414
                            fprintf(outfile,
2415
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2416
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2417
                                    " & ~0x3ff) "
2418
                                    " | ((%s + %d) & 0x3ff);\n",
2419
                                    reloc_offset, reloc_offset, relname, addend);
2420
                            break;
2421
                        case R_SPARC_OLO10:
2422
                            addend += ELF64_R_TYPE_DATA (rel->r_info);
2423
                            fprintf(outfile,
2424
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2425
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2426
                                    " & ~0x3ff) "
2427
                                    " | ((%s + %d) & 0x3ff);\n",
2428
                                    reloc_offset, reloc_offset, relname, addend);
2429
                            break;
2430
                        case R_SPARC_WDISP30:
2431
                            fprintf(outfile,
2432
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2433
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2434
                                    " & ~0x3fffffff) "
2435
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2436
                                    "    & 0x3fffffff);\n",
2437
                                    reloc_offset, reloc_offset, relname, addend,
2438
                                    reloc_offset);
2439
                            break;
2440
                        case R_SPARC_WDISP22:
2441
                            fprintf(outfile,
2442
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2443
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2444
                                    " & ~0x3fffff) "
2445
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2446
                                    "    & 0x3fffff);\n",
2447
                                    reloc_offset, reloc_offset, relname, addend,
2448
                                    reloc_offset);
2449
                            break;
2450
                        case R_SPARC_HH22:
2451
                            fprintf(outfile,
2452
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2453
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2454
                                    " & ~0x00000000) "
2455
                                    " | (((%s + %d) >> 42) & 0x00000000);\n",
2456
                                    reloc_offset, reloc_offset, relname, addend);
2457
                             break;
2458

    
2459
                        case R_SPARC_LM22:
2460
                            fprintf(outfile,
2461
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2462
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2463
                                    " & ~0x00000000) "
2464
                                    " | (((%s + %d) >> 10) & 0x00000000);\n",
2465
                                    reloc_offset, reloc_offset, relname, addend);
2466
                            break;
2467

    
2468
                        case R_SPARC_HM10:
2469
                            fprintf(outfile,
2470
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2471
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2472
                                    " & ~0x00000000) "
2473
                                    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2474
                                    reloc_offset, reloc_offset, relname, addend);
2475
                            break;
2476

    
2477
                        default:
2478
                            error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2479
                        }
2480
                    }
2481
                }
2482
            }
2483
#elif defined(HOST_ARM)
2484
            {
2485
                char relname[256];
2486
                int type;
2487
                int addend;
2488
                int reloc_offset;
2489
                uint32_t insn;
2490

    
2491
                insn = get32((uint32_t *)(p_start + 4));
2492
                /* If prologue ends in sub sp, sp, #const then assume
2493
                   op has a stack frame and needs the frame pointer.  */
2494
                if ((insn & 0xffffff00) == 0xe24dd000) {
2495
                    int i;
2496
                    uint32_t opcode;
2497
                    opcode = 0xe28db000; /* add fp, sp, #0.  */
2498
#if 0
2499
/* ??? Need to undo the extra stack adjustment at the end of the op.
2500
   For now just leave the stack misaligned and hope it doesn't break anything
2501
   too important.  */
2502
                    if ((insn & 4) != 0) {
2503
                        /* Preserve doubleword stack alignment.  */
2504
                        fprintf(outfile,
2505
                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2506
                                insn + 4);
2507
                        opcode -= 4;
2508
                    }
2509
#endif
2510
                    insn = get32((uint32_t *)(p_start - 4));
2511
                    /* Calculate the size of the saved registers,
2512
                       excluding pc.  */
2513
                    for (i = 0; i < 15; i++) {
2514
                        if (insn & (1 << i))
2515
                            opcode += 4;
2516
                    }
2517
                    fprintf(outfile,
2518
                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2519
                }
2520
                arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2521
                                  relocs, nb_relocs);
2522

    
2523
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2524
                if (rel->r_offset >= start_offset &&
2525
                    rel->r_offset < start_offset + copy_size) {
2526
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2527
                    /* the compiler leave some unnecessary references to the code */
2528
                    if (sym_name[0] == '\0')
2529
                        continue;
2530
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2531
                    type = ELF32_R_TYPE(rel->r_info);
2532
                    addend = get32((uint32_t *)(text + rel->r_offset));
2533
                    reloc_offset = rel->r_offset - start_offset;
2534
                    switch(type) {
2535
                    case R_ARM_ABS32:
2536
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2537
                                reloc_offset, relname, addend);
2538
                        break;
2539
                    case R_ARM_PC24:
2540
                    case R_ARM_JUMP24:
2541
                    case R_ARM_CALL:
2542
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2543
                                reloc_offset, addend, relname);
2544
                        break;
2545
                    default:
2546
                        error("unsupported arm relocation (%d)", type);
2547
                    }
2548
                }
2549
                }
2550
            }
2551
#elif defined(HOST_M68K)
2552
            {
2553
                char relname[256];
2554
                int type;
2555
                int addend;
2556
                int reloc_offset;
2557
                Elf32_Sym *sym;
2558
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2559
                if (rel->r_offset >= start_offset &&
2560
                    rel->r_offset < start_offset + copy_size) {
2561
                    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2562
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2563
                    get_reloc_expr(relname, sizeof(relname), sym_name);
2564
                    type = ELF32_R_TYPE(rel->r_info);
2565
                    addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2566
                    reloc_offset = rel->r_offset - start_offset;
2567
                    switch(type) {
2568
                    case R_68K_32:
2569
                        fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2570
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2571
                                reloc_offset, relname, addend );
2572
                        break;
2573
                    case R_68K_PC32:
2574
                        fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2575
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2576
                                reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2577
                        break;
2578
                    default:
2579
                        error("unsupported m68k relocation (%d)", type);
2580
                    }
2581
                }
2582
                }
2583
            }
2584
#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2585
            {
2586
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2587
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2588
                        char relname[256];
2589
                        int type;
2590
                        int addend;
2591
                        int reloc_offset;
2592

    
2593
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2594
                        /* the compiler leave some unnecessary references to the code */
2595
                        if (sym_name[0] == '\0')
2596
                            continue;
2597
                        get_reloc_expr(relname, sizeof(relname), sym_name);
2598
                        type = ELF32_R_TYPE(rel->r_info);
2599
                        addend = get32((uint32_t *)(text + rel->r_offset));
2600
                        reloc_offset = rel->r_offset - start_offset;
2601
                        switch (type) {
2602
                        case R_MIPS_26:
2603
                            fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2604
                                    rel->r_offset, sym_name);
2605
                            fprintf(outfile,
2606
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2607
                                    "(0x%x & ~0x3fffff) "
2608
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2609
                                    "   & 0x3fffff);\n",
2610
                                    reloc_offset, addend, addend, relname, reloc_offset);
2611
                            break;
2612
                        case R_MIPS_HI16:
2613
                            fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2614
                                    rel->r_offset, sym_name);
2615
                            fprintf(outfile,
2616
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2617
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2618
                                    " & ~0xffff) "
2619
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2620
                                    reloc_offset, reloc_offset, relname);
2621
                            break;
2622
                        case R_MIPS_LO16:
2623
                            fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2624
                                    rel->r_offset, sym_name);
2625
                            fprintf(outfile,
2626
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2627
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2628
                                    " & ~0xffff) "
2629
                                    " | (%s & 0xffff);\n",
2630
                                    reloc_offset, reloc_offset, relname);
2631
                            break;
2632
                        case R_MIPS_PC16:
2633
                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2634
                                    rel->r_offset, sym_name);
2635
                            fprintf(outfile,
2636
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2637
                                    "(0x%x & ~0xffff) "
2638
                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2639
                                    "   & 0xffff);\n",
2640
                                    reloc_offset, addend, addend, relname, reloc_offset);
2641
                            break;
2642
                        case R_MIPS_GOT16:
2643
                        case R_MIPS_CALL16:
2644
                            fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2645
                                    rel->r_offset, sym_name);
2646
                            fprintf(outfile,
2647
                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
2648
                                    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2649
                                    " & ~0xffff) "
2650
                                    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2651
                                    reloc_offset, reloc_offset, relname);
2652
                            break;
2653
                        default:
2654
                            error("unsupported MIPS relocation (%d)", type);
2655
                        }
2656
                    }
2657
                }
2658
            }
2659
#else
2660
#error unsupported CPU
2661
#endif
2662
        fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2663
        fprintf(outfile, "}\n");
2664
        fprintf(outfile, "break;\n\n");
2665
    } else {
2666
        fprintf(outfile, "static inline void gen_%s(", name);
2667
        if (nb_args == 0) {
2668
            fprintf(outfile, "void");
2669
        } else {
2670
            for(i = 0; i < nb_args; i++) {
2671
                if (i != 0)
2672
                    fprintf(outfile, ", ");
2673
                fprintf(outfile, "long param%d", i + 1);
2674
            }
2675
        }
2676
        fprintf(outfile, ")\n");
2677
        fprintf(outfile, "{\n");
2678
        for(i = 0; i < nb_args; i++) {
2679
            fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2680
        }
2681
        fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2682
        fprintf(outfile, "}\n\n");
2683
    }
2684
}
2685

    
2686
int gen_file(FILE *outfile, int out_type)
2687
{
2688
    int i;
2689
    EXE_SYM *sym;
2690

    
2691
    if (out_type == OUT_INDEX_OP) {
2692
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2693
            const char *name;
2694
            name = get_sym_name(sym);
2695
            if (strstart(name, OP_PREFIX, NULL)) {
2696
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2697
            }
2698
        }
2699
    } else if (out_type == OUT_GEN_OP) {
2700
        /* generate gen_xxx functions */
2701
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2702
            const char *name;
2703
            name = get_sym_name(sym);
2704
            if (strstart(name, OP_PREFIX, NULL)) {
2705
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2706
                if (sym->st_shndx != text_shndx)
2707
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2708
#endif
2709
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2710
            }
2711
        }
2712

    
2713
    } else {
2714
        /* generate big code generation switch */
2715

    
2716
#ifdef HOST_ARM
2717
#error broken
2718
        /* We need to know the size of all the ops so we can figure out when
2719
           to emit constant pools.  This must be consistent with opc.h.  */
2720
fprintf(outfile,
2721
"static const uint32_t arm_opc_size[] = {\n"
2722
"  0,\n" /* end */
2723
"  0,\n" /* nop */
2724
"  0,\n" /* nop1 */
2725
"  0,\n" /* nop2 */
2726
"  0,\n"); /* nop3 */
2727
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2728
            const char *name;
2729
            name = get_sym_name(sym);
2730
            if (strstart(name, OP_PREFIX, NULL)) {
2731
                fprintf(outfile, "  %d,\n", sym->st_size);
2732
            }
2733
        }
2734
fprintf(outfile,
2735
"};\n");
2736
#endif
2737

    
2738
#ifdef HOST_ARM
2739
#error broken
2740
/* Arm is tricky because it uses constant pools for loading immediate values.
2741
   We assume (and require) each function is code followed by a constant pool.
2742
   All the ops are small so this should be ok.  For each op we figure
2743
   out how much "spare" range we have in the load instructions.  This allows
2744
   us to insert subsequent ops in between the op and the constant pool,
2745
   eliminating the neeed to jump around the pool.
2746

2747
   We currently generate:
2748

2749
   [ For this example we assume merging would move op1_pool out of range.
2750
     In practice we should be able to combine many ops before the offset
2751
     limits are reached. ]
2752
   op1_code;
2753
   op2_code;
2754
   goto op3;
2755
   op2_pool;
2756
   op1_pool;
2757
op3:
2758
   op3_code;
2759
   ret;
2760
   op3_pool;
2761

2762
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2763
 */
2764
fprintf(outfile,
2765
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2766
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2767
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2768
/* Initialise the parmissible pool offset to an arbitary large value.  */
2769
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2770
#endif
2771
#ifdef HOST_IA64
2772
#error broken
2773
    {
2774
        long addend, not_first = 0;
2775
        unsigned long sym_idx;
2776
        int index, max_index;
2777
        const char *sym_name;
2778
        EXE_RELOC *rel;
2779

    
2780
        max_index = -1;
2781
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2782
            sym_idx = ELF64_R_SYM(rel->r_info);
2783
            sym_name = (strtab + symtab[sym_idx].st_name);
2784
            if (strstart(sym_name, "__op_gen_label", NULL))
2785
                continue;
2786
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2787
                continue;
2788

    
2789
            addend = rel->r_addend;
2790
            index = get_plt_index(sym_name, addend);
2791
            if (index <= max_index)
2792
                continue;
2793
            max_index = index;
2794
            fprintf(outfile, "    extern void %s(void);\n", sym_name);
2795
        }
2796

    
2797
        fprintf(outfile,
2798
                "    struct ia64_fixup *plt_fixes = NULL, "
2799
                "*ltoff_fixes = NULL;\n"
2800
                "    static long plt_target[] = {\n\t");
2801

    
2802
        max_index = -1;
2803
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2804
            sym_idx = ELF64_R_SYM(rel->r_info);
2805
            sym_name = (strtab + symtab[sym_idx].st_name);
2806
            if (strstart(sym_name, "__op_gen_label", NULL))
2807
                continue;
2808
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2809
                continue;
2810

    
2811
            addend = rel->r_addend;
2812
            index = get_plt_index(sym_name, addend);
2813
            if (index <= max_index)
2814
                continue;
2815
            max_index = index;
2816

    
2817
            if (not_first)
2818
                fprintf(outfile, ",\n\t");
2819
            not_first = 1;
2820
            if (addend)
2821
                fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2822
            else
2823
                fprintf(outfile, "(long) &%s", sym_name);
2824
        }
2825
        fprintf(outfile, "\n    };\n"
2826
            "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2827
    }
2828
#endif
2829

    
2830
#ifdef HOST_ARM
2831
#error broken
2832
/* Generate constant pool if needed */
2833
fprintf(outfile,
2834
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2835
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2836
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2837
"                last_gen_code_ptr = gen_code_ptr;\n"
2838
"                arm_ldr_ptr = arm_ldr_table;\n"
2839
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2840
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2841
"            }\n");
2842
#endif
2843

    
2844
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2845
            const char *name;
2846
            name = get_sym_name(sym);
2847
            if (strstart(name, OP_PREFIX, NULL)) {
2848
#if 0
2849
                printf("%4d: %s pos=0x%08x len=%d\n",
2850
                       i, name, sym->st_value, sym->st_size);
2851
#endif
2852
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2853
                if (sym->st_shndx != text_shndx)
2854
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2855
#endif
2856
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2857
            }
2858
        }
2859
    }
2860

    
2861
    return 0;
2862
}
2863

    
2864
void usage(void)
2865
{
2866
    printf("dyngen (c) 2003 Fabrice Bellard\n"
2867
           "usage: dyngen [-o outfile] [-c] objfile\n"
2868
           "Generate a dynamic code generator from an object file\n"
2869
           "-c     output enum of operations\n"
2870
           "-g     output gen_op_xx() functions\n"
2871
           );
2872
    exit(1);
2873
}
2874

    
2875
int main(int argc, char **argv)
2876
{
2877
    int c, out_type;
2878
    const char *filename, *outfilename;
2879
    FILE *outfile;
2880

    
2881
    outfilename = "out.c";
2882
    out_type = OUT_CODE;
2883
    for(;;) {
2884
        c = getopt(argc, argv, "ho:cg");
2885
        if (c == -1)
2886
            break;
2887
        switch(c) {
2888
        case 'h':
2889
            usage();
2890
            break;
2891
        case 'o':
2892
            outfilename = optarg;
2893
            break;
2894
        case 'c':
2895
            out_type = OUT_INDEX_OP;
2896
            break;
2897
        case 'g':
2898
            out_type = OUT_GEN_OP;
2899
            break;
2900
        }
2901
    }
2902
    if (optind >= argc)
2903
        usage();
2904
    filename = argv[optind];
2905
    outfile = fopen(outfilename, "w");
2906
    if (!outfile)
2907
        error("could not open '%s'", outfilename);
2908

    
2909
    load_object(filename);
2910
    gen_file(outfile, out_type);
2911
    fclose(outfile);
2912
    return 0;
2913
}