Statistics
| Branch: | Revision:

root / dyngen.c @ ea785922

History | View | Annotate | Download (89 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
#else
121
#error unsupported CPU - please update the code
122
#endif
123

    
124
#include "elf.h"
125

    
126
#if ELF_CLASS == ELFCLASS32
127
typedef int32_t host_long;
128
typedef uint32_t host_ulong;
129
#define swabls(x) swab32s(x)
130
#define swablss(x) swab32ss(x)
131
#else
132
typedef int64_t host_long;
133
typedef uint64_t host_ulong;
134
#define swabls(x) swab64s(x)
135
#define swablss(x) swab64ss(x)
136
#endif
137

    
138
#ifdef ELF_USES_RELOCA
139
#define SHT_RELOC SHT_RELA
140
#else
141
#define SHT_RELOC SHT_REL
142
#endif
143

    
144
#define EXE_RELOC ELF_RELOC
145
#define EXE_SYM ElfW(Sym)
146

    
147
#endif /* CONFIG_FORMAT_ELF */
148

    
149
#ifdef CONFIG_FORMAT_COFF
150

    
151
#include "a.out.h"
152

    
153
typedef int32_t host_long;
154
typedef uint32_t host_ulong;
155

    
156
#define FILENAMELEN 256
157

    
158
typedef struct coff_sym {
159
    struct external_syment *st_syment;
160
    char st_name[FILENAMELEN];
161
    uint32_t st_value;
162
    int  st_size;
163
    uint8_t st_type;
164
    uint8_t st_shndx;
165
} coff_Sym;
166

    
167
typedef struct coff_rel {
168
    struct external_reloc *r_reloc;
169
    int  r_offset;
170
    uint8_t r_type;
171
} coff_Rel;
172

    
173
#define EXE_RELOC struct coff_rel
174
#define EXE_SYM struct coff_sym
175

    
176
#endif /* CONFIG_FORMAT_COFF */
177

    
178
#ifdef CONFIG_FORMAT_MACH
179

    
180
#include <mach-o/loader.h>
181
#include <mach-o/nlist.h>
182
#include <mach-o/reloc.h>
183
#include <mach-o/ppc/reloc.h>
184

    
185
# define check_mach_header(x) (x.magic == MH_MAGIC)
186
typedef int32_t host_long;
187
typedef uint32_t host_ulong;
188

    
189
struct nlist_extended
190
{
191
   union {
192
   char *n_name; 
193
   long  n_strx; 
194
   } n_un;
195
   unsigned char n_type; 
196
   unsigned char n_sect; 
197
   short st_desc;
198
   unsigned long st_value;
199
   unsigned long st_size;
200
};
201

    
202
#define EXE_RELOC struct relocation_info
203
#define EXE_SYM struct nlist_extended
204

    
205
#endif /* CONFIG_FORMAT_MACH */
206

    
207
#include "bswap.h"
208

    
209
enum {
210
    OUT_GEN_OP,
211
    OUT_CODE,
212
    OUT_INDEX_OP,
213
};
214

    
215
/* all dynamically generated functions begin with this code */
216
#define OP_PREFIX "op_"
217

    
218
int do_swap;
219

    
220
void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
221
{
222
    va_list ap;
223
    va_start(ap, fmt);
224
    fprintf(stderr, "dyngen: ");
225
    vfprintf(stderr, fmt, ap);
226
    fprintf(stderr, "\n");
227
    va_end(ap);
228
    exit(1);
229
}
230

    
231
void *load_data(int fd, long offset, unsigned int size)
232
{
233
    char *data;
234

    
235
    data = malloc(size);
236
    if (!data)
237
        return NULL;
238
    lseek(fd, offset, SEEK_SET);
239
    if (read(fd, data, size) != size) {
240
        free(data);
241
        return NULL;
242
    }
243
    return data;
244
}
245

    
246
int strstart(const char *str, const char *val, const char **ptr)
247
{
248
    const char *p, *q;
249
    p = str;
250
    q = val;
251
    while (*q != '\0') {
252
        if (*p != *q)
253
            return 0;
254
        p++;
255
        q++;
256
    }
257
    if (ptr)
258
        *ptr = p;
259
    return 1;
260
}
261

    
262
void pstrcpy(char *buf, int buf_size, const char *str)
263
{
264
    int c;
265
    char *q = buf;
266

    
267
    if (buf_size <= 0)
268
        return;
269

    
270
    for(;;) {
271
        c = *str++;
272
        if (c == 0 || q >= buf + buf_size - 1)
273
            break;
274
        *q++ = c;
275
    }
276
    *q = '\0';
277
}
278

    
279
void swab16s(uint16_t *p)
280
{
281
    *p = bswap16(*p);
282
}
283

    
284
void swab32s(uint32_t *p)
285
{
286
    *p = bswap32(*p);
287
}
288

    
289
void swab32ss(int32_t *p)
290
{
291
    *p = bswap32(*p);
292
}
293

    
294
void swab64s(uint64_t *p)
295
{
296
    *p = bswap64(*p);
297
}
298

    
299
void swab64ss(int64_t *p)
300
{
301
    *p = bswap64(*p);
302
}
303

    
304
uint16_t get16(uint16_t *p)
305
{
306
    uint16_t val;
307
    val = *p;
308
    if (do_swap)
309
        val = bswap16(val);
310
    return val;
311
}
312

    
313
uint32_t get32(uint32_t *p)
314
{
315
    uint32_t val;
316
    val = *p;
317
    if (do_swap)
318
        val = bswap32(val);
319
    return val;
320
}
321

    
322
void put16(uint16_t *p, uint16_t val)
323
{
324
    if (do_swap)
325
        val = bswap16(val);
326
    *p = val;
327
}
328

    
329
void put32(uint32_t *p, uint32_t val)
330
{
331
    if (do_swap)
332
        val = bswap32(val);
333
    *p = val;
334
}
335

    
336
/* executable information */
337
EXE_SYM *symtab;
338
int nb_syms;
339
int text_shndx;
340
uint8_t *text;
341
EXE_RELOC *relocs;
342
int nb_relocs;
343

    
344
#ifdef CONFIG_FORMAT_ELF
345

    
346
/* ELF file info */
347
struct elf_shdr *shdr;
348
uint8_t **sdata;
349
struct elfhdr ehdr;
350
char *strtab;
351

    
352
int elf_must_swap(struct elfhdr *h)
353
{
354
  union {
355
      uint32_t i;
356
      uint8_t b[4];
357
  } swaptest;
358

    
359
  swaptest.i = 1;
360
  return (h->e_ident[EI_DATA] == ELFDATA2MSB) != 
361
      (swaptest.b[0] == 0);
362
}
363
  
364
void elf_swap_ehdr(struct elfhdr *h)
365
{
366
    swab16s(&h->e_type);                        /* Object file type */
367
    swab16s(&h->        e_machine);                /* Architecture */
368
    swab32s(&h->        e_version);                /* Object file version */
369
    swabls(&h->        e_entry);                /* Entry point virtual address */
370
    swabls(&h->        e_phoff);                /* Program header table file offset */
371
    swabls(&h->        e_shoff);                /* Section header table file offset */
372
    swab32s(&h->        e_flags);                /* Processor-specific flags */
373
    swab16s(&h->        e_ehsize);                /* ELF header size in bytes */
374
    swab16s(&h->        e_phentsize);                /* Program header table entry size */
375
    swab16s(&h->        e_phnum);                /* Program header table entry count */
376
    swab16s(&h->        e_shentsize);                /* Section header table entry size */
377
    swab16s(&h->        e_shnum);                /* Section header table entry count */
378
    swab16s(&h->        e_shstrndx);                /* Section header string table index */
379
}
380

    
381
void elf_swap_shdr(struct elf_shdr *h)
382
{
383
  swab32s(&h->        sh_name);                /* Section name (string tbl index) */
384
  swab32s(&h->        sh_type);                /* Section type */
385
  swabls(&h->        sh_flags);                /* Section flags */
386
  swabls(&h->        sh_addr);                /* Section virtual addr at execution */
387
  swabls(&h->        sh_offset);                /* Section file offset */
388
  swabls(&h->        sh_size);                /* Section size in bytes */
389
  swab32s(&h->        sh_link);                /* Link to another section */
390
  swab32s(&h->        sh_info);                /* Additional section information */
391
  swabls(&h->        sh_addralign);                /* Section alignment */
392
  swabls(&h->        sh_entsize);                /* Entry size if section holds table */
393
}
394

    
395
void elf_swap_phdr(struct elf_phdr *h)
396
{
397
    swab32s(&h->p_type);                        /* Segment type */
398
    swabls(&h->p_offset);                /* Segment file offset */
399
    swabls(&h->p_vaddr);                /* Segment virtual address */
400
    swabls(&h->p_paddr);                /* Segment physical address */
401
    swabls(&h->p_filesz);                /* Segment size in file */
402
    swabls(&h->p_memsz);                /* Segment size in memory */
403
    swab32s(&h->p_flags);                /* Segment flags */
404
    swabls(&h->p_align);                /* Segment alignment */
405
}
406

    
407
void elf_swap_rel(ELF_RELOC *rel)
408
{
409
    swabls(&rel->r_offset);
410
    swabls(&rel->r_info);
411
#ifdef ELF_USES_RELOCA
412
    swablss(&rel->r_addend);
413
#endif
414
}
415

    
416
struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr, 
417
                                  const char *name)
418
{
419
    int i;
420
    const char *shname;
421
    struct elf_shdr *sec;
422

    
423
    for(i = 0; i < shnum; i++) {
424
        sec = &shdr[i];
425
        if (!sec->sh_name)
426
            continue;
427
        shname = shstr + sec->sh_name;
428
        if (!strcmp(shname, name))
429
            return sec;
430
    }
431
    return NULL;
432
}
433

    
434
int find_reloc(int sh_index)
435
{
436
    struct elf_shdr *sec;
437
    int i;
438

    
439
    for(i = 0; i < ehdr.e_shnum; i++) {
440
        sec = &shdr[i];
441
        if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index) 
442
            return i;
443
    }
444
    return 0;
445
}
446

    
447
static host_ulong get_rel_offset(EXE_RELOC *rel)
448
{
449
    return rel->r_offset;
450
}
451

    
452
static char *get_rel_sym_name(EXE_RELOC *rel)
453
{
454
    return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
455
}
456

    
457
static char *get_sym_name(EXE_SYM *sym)
458
{
459
    return strtab + sym->st_name;
460
}
461

    
462
/* load an elf object file */
463
int load_object(const char *filename)
464
{
465
    int fd;
466
    struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
467
    int i, j;
468
    ElfW(Sym) *sym;
469
    char *shstr;
470
    ELF_RELOC *rel;
471
    
472
    fd = open(filename, O_RDONLY);
473
    if (fd < 0) 
474
        error("can't open file '%s'", filename);
475
    
476
    /* Read ELF header.  */
477
    if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
478
        error("unable to read file header");
479

    
480
    /* Check ELF identification.  */
481
    if (ehdr.e_ident[EI_MAG0] != ELFMAG0
482
     || ehdr.e_ident[EI_MAG1] != ELFMAG1
483
     || ehdr.e_ident[EI_MAG2] != ELFMAG2
484
     || ehdr.e_ident[EI_MAG3] != ELFMAG3
485
     || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
486
        error("bad ELF header");
487
    }
488

    
489
    do_swap = elf_must_swap(&ehdr);
490
    if (do_swap)
491
        elf_swap_ehdr(&ehdr);
492
    if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
493
        error("Unsupported ELF class");
494
    if (ehdr.e_type != ET_REL)
495
        error("ELF object file expected");
496
    if (ehdr.e_version != EV_CURRENT)
497
        error("Invalid ELF version");
498
    if (!elf_check_arch(ehdr.e_machine))
499
        error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
500

    
501
    /* read section headers */
502
    shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
503
    if (do_swap) {
504
        for(i = 0; i < ehdr.e_shnum; i++) {
505
            elf_swap_shdr(&shdr[i]);
506
        }
507
    }
508

    
509
    /* read all section data */
510
    sdata = malloc(sizeof(void *) * ehdr.e_shnum);
511
    memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
512
    
513
    for(i = 0;i < ehdr.e_shnum; i++) {
514
        sec = &shdr[i];
515
        if (sec->sh_type != SHT_NOBITS)
516
            sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
517
    }
518

    
519
    sec = &shdr[ehdr.e_shstrndx];
520
    shstr = (char *)sdata[ehdr.e_shstrndx];
521

    
522
    /* swap relocations */
523
    for(i = 0; i < ehdr.e_shnum; i++) {
524
        sec = &shdr[i];
525
        if (sec->sh_type == SHT_RELOC) {
526
            nb_relocs = sec->sh_size / sec->sh_entsize;
527
            if (do_swap) {
528
                for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
529
                    elf_swap_rel(rel);
530
            }
531
        }
532
    }
533
    /* text section */
534

    
535
    text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
536
    if (!text_sec)
537
        error("could not find .text section");
538
    text_shndx = text_sec - shdr;
539
    text = sdata[text_shndx];
540

    
541
    /* find text relocations, if any */
542
    relocs = NULL;
543
    nb_relocs = 0;
544
    i = find_reloc(text_shndx);
545
    if (i != 0) {
546
        relocs = (ELF_RELOC *)sdata[i];
547
        nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
548
    }
549

    
550
    symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
551
    if (!symtab_sec)
552
        error("could not find .symtab section");
553
    strtab_sec = &shdr[symtab_sec->sh_link];
554

    
555
    symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
556
    strtab = (char *)sdata[symtab_sec->sh_link];
557
    
558
    nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
559
    if (do_swap) {
560
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
561
            swab32s(&sym->st_name);
562
            swabls(&sym->st_value);
563
            swabls(&sym->st_size);
564
            swab16s(&sym->st_shndx);
565
        }
566
    }
567
    close(fd);
568
    return 0;
569
}
570

    
571
#endif /* CONFIG_FORMAT_ELF */
572

    
573
#ifdef CONFIG_FORMAT_COFF
574

    
575
/* COFF file info */
576
struct external_scnhdr *shdr;
577
uint8_t **sdata;
578
struct external_filehdr fhdr;
579
struct external_syment *coff_symtab;
580
char *strtab;
581
int coff_text_shndx, coff_data_shndx;
582

    
583
int data_shndx;
584

    
585
#define STRTAB_SIZE 4
586

    
587
#define DIR32   0x06
588
#define DISP32  0x14
589

    
590
#define T_FUNCTION  0x20
591
#define C_EXTERNAL  2
592

    
593
void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
594
{
595
    char *q;
596
    int c, i, len;
597
    
598
    if (ext_sym->e.e.e_zeroes != 0) {
599
        q = sym->st_name;
600
        for(i = 0; i < 8; i++) {
601
            c = ext_sym->e.e_name[i];
602
            if (c == '\0')
603
                break;
604
            *q++ = c;
605
        }
606
        *q = '\0';
607
    } else {
608
        pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
609
    }
610

    
611
    /* now convert the name to a C name (suppress the leading '_') */
612
    if (sym->st_name[0] == '_') {
613
        len = strlen(sym->st_name);
614
        memmove(sym->st_name, sym->st_name + 1, len - 1);
615
        sym->st_name[len - 1] = '\0';
616
    }
617
}
618

    
619
char *name_for_dotdata(struct coff_rel *rel)
620
{
621
        int i;
622
        struct coff_sym *sym;
623
        uint32_t text_data;
624

    
625
        text_data = *(uint32_t *)(text + rel->r_offset);
626

    
627
        for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
628
                if (sym->st_syment->e_scnum == data_shndx &&
629
                    text_data >= sym->st_value &&
630
                    text_data < sym->st_value + sym->st_size) {
631
                    
632
                    return sym->st_name;
633

    
634
                }
635
        }
636
        return NULL;
637
}
638

    
639
static char *get_sym_name(EXE_SYM *sym)
640
{
641
    return sym->st_name;
642
}
643

    
644
static char *get_rel_sym_name(EXE_RELOC *rel)
645
{
646
    char *name;
647
    name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
648
    if (!strcmp(name, ".data"))
649
        name = name_for_dotdata(rel);
650
    if (name[0] == '.')
651
        return NULL;
652
    return name;
653
}
654

    
655
static host_ulong get_rel_offset(EXE_RELOC *rel)
656
{
657
    return rel->r_offset;
658
}
659

    
660
struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
661
{
662
    int i;
663
    const char *shname;
664
    struct external_scnhdr *sec;
665

    
666
    for(i = 0; i < shnum; i++) {
667
        sec = &shdr[i];
668
        if (!sec->s_name)
669
            continue;
670
        shname = sec->s_name;
671
        if (!strcmp(shname, name))
672
            return sec;
673
    }
674
    return NULL;
675
}
676

    
677
/* load a coff object file */
678
int load_object(const char *filename)
679
{
680
    int fd;
681
    struct external_scnhdr *sec, *text_sec, *data_sec;
682
    int i;
683
    struct external_syment *ext_sym;
684
    struct external_reloc *coff_relocs;
685
    struct external_reloc *ext_rel;
686
    uint32_t *n_strtab;
687
    EXE_SYM *sym;
688
    EXE_RELOC *rel;
689
        
690
    fd = open(filename, O_RDONLY 
691
#ifdef _WIN32
692
              | O_BINARY
693
#endif
694
              );
695
    if (fd < 0) 
696
        error("can't open file '%s'", filename);
697
    
698
    /* Read COFF header.  */
699
    if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
700
        error("unable to read file header");
701

    
702
    /* Check COFF identification.  */
703
    if (fhdr.f_magic != I386MAGIC) {
704
        error("bad COFF header");
705
    }
706
    do_swap = 0;
707

    
708
    /* read section headers */
709
    shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
710
        
711
    /* read all section data */
712
    sdata = malloc(sizeof(void *) * fhdr.f_nscns);
713
    memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
714
    
715
    const char *p;
716
    for(i = 0;i < fhdr.f_nscns; i++) {
717
        sec = &shdr[i];
718
        if (!strstart(sec->s_name,  ".bss", &p))
719
            sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
720
    }
721

    
722

    
723
    /* text section */
724
    text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
725
    if (!text_sec)
726
        error("could not find .text section");
727
    coff_text_shndx = text_sec - shdr;
728
    text = sdata[coff_text_shndx];
729

    
730
    /* data section */
731
    data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
732
    if (!data_sec)
733
        error("could not find .data section");
734
    coff_data_shndx = data_sec - shdr;
735
    
736
    coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
737
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
738
        for(i=0;i<8;i++)
739
            printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
740
        printf("\n");
741
    }
742

    
743

    
744
    n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
745
    strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab); 
746
    
747
    nb_syms = fhdr.f_nsyms;
748

    
749
    for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
750
      if (strstart(ext_sym->e.e_name, ".text", NULL))
751
                  text_shndx = ext_sym->e_scnum;
752
          if (strstart(ext_sym->e.e_name, ".data", NULL))
753
                  data_shndx = ext_sym->e_scnum;
754
    }
755

    
756
        /* set coff symbol */
757
        symtab = malloc(sizeof(struct coff_sym) * nb_syms);
758

    
759
        int aux_size, j;
760
        for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
761
                memset(sym, 0, sizeof(*sym));
762
                sym->st_syment = ext_sym;
763
                sym_ent_name(ext_sym, sym);
764
                sym->st_value = ext_sym->e_value;
765

    
766
                aux_size = *(int8_t *)ext_sym->e_numaux;
767
                if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
768
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
769
                                if ((ext_sym + j)->e_scnum == text_shndx &&
770
                                        (ext_sym + j)->e_type == T_FUNCTION ){
771
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
772
                                        break;
773
                                } else if (j == nb_syms - i - 1) {
774
                                        sec = &shdr[coff_text_shndx];
775
                                        sym->st_size = sec->s_size - ext_sym->e_value;
776
                                        break;
777
                                }
778
                        }
779
                } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
780
                        for (j = aux_size + 1; j < nb_syms - i; j++) {
781
                                if ((ext_sym + j)->e_scnum == data_shndx) {
782
                                        sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
783
                                        break;
784
                                } else if (j == nb_syms - i - 1) {
785
                                        sec = &shdr[coff_data_shndx];
786
                                        sym->st_size = sec->s_size - ext_sym->e_value;
787
                                        break;
788
                                }
789
                        }
790
                } else {
791
                        sym->st_size = 0;
792
                }
793
                
794
                sym->st_type = ext_sym->e_type;
795
                sym->st_shndx = ext_sym->e_scnum;
796
        }
797

    
798
                
799
    /* find text relocations, if any */
800
    sec = &shdr[coff_text_shndx];
801
    coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
802
    nb_relocs = sec->s_nreloc;
803

    
804
    /* set coff relocation */
805
    relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
806
    for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs; 
807
         i++, ext_rel++, rel++) {
808
        memset(rel, 0, sizeof(*rel));
809
        rel->r_reloc = ext_rel;
810
        rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
811
        rel->r_type = *(uint16_t *)ext_rel->r_type;
812
    }
813
    return 0;
814
}
815

    
816
#endif /* CONFIG_FORMAT_COFF */
817

    
818
#ifdef CONFIG_FORMAT_MACH
819

    
820
/* File Header */
821
struct mach_header         mach_hdr;
822

    
823
/* commands */
824
struct segment_command         *segment = 0;
825
struct dysymtab_command *dysymtabcmd = 0;
826
struct symtab_command         *symtabcmd = 0;
827

    
828
/* section */
829
struct section         *section_hdr;
830
struct section *text_sec_hdr;
831
uint8_t         **sdata;
832

    
833
/* relocs */
834
struct relocation_info *relocs;
835
        
836
/* symbols */
837
EXE_SYM                        *symtab;
838
struct nlist         *symtab_std;
839
char                        *strtab;
840

    
841
/* indirect symbols */
842
uint32_t         *tocdylib;
843

    
844
/* Utility functions */
845

    
846
static inline char *find_str_by_index(int index)
847
{
848
    return strtab+index;
849
}
850

    
851
/* Used by dyngen common code */
852
static char *get_sym_name(EXE_SYM *sym)
853
{
854
        char *name = find_str_by_index(sym->n_un.n_strx);
855
        
856
        if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
857
                return "debug";
858
                        
859
        if(!name)
860
                return name;
861
        if(name[0]=='_')
862
                return name + 1;
863
        else
864
                return name;
865
}
866

    
867
/* find a section index given its segname, sectname */
868
static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname, 
869
                                  const char *sectname)
870
{
871
    int i;
872
    struct section *sec = section_hdr;
873

    
874
    for(i = 0; i < shnum; i++, sec++) {
875
        if (!sec->segname || !sec->sectname)
876
            continue;
877
        if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
878
            return i;
879
    }
880
    return -1;
881
}
882

    
883
/* find a section header given its segname, sectname */
884
struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname, 
885
                                  const char *sectname)
886
{
887
    int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
888
        if(index == -1)
889
                return NULL;
890
        return section_hdr+index;
891
}
892

    
893

    
894
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
895
{
896
    struct scattered_relocation_info * scarel;
897
        
898
    if(R_SCATTERED & rel->r_address) {
899
        scarel = (struct scattered_relocation_info*)rel;
900
        if(scarel->r_type != PPC_RELOC_PAIR)
901
            error("fetch_next_pair_value: looking for a pair which was not found (1)");
902
        *value = scarel->r_value;
903
    } else {
904
                if(rel->r_type != PPC_RELOC_PAIR)
905
                        error("fetch_next_pair_value: looking for a pair which was not found (2)");
906
                *value = rel->r_address;
907
        }
908
}
909

    
910
/* find a sym name given its value, in a section number */
911
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
912
{
913
        int i, ret = -1;
914
        
915
        for( i = 0 ; i < nb_syms; i++ )
916
        {
917
            if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
918
                         (symtab[i].n_sect ==  sectnum) && (symtab[i].st_value <= value) )
919
                {
920
                        if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
921
                                ret = i;
922
                }
923
        }
924
        if( ret < 0 ) {
925
                *offset = 0;
926
                return 0;
927
        } else {
928
                *offset = value - symtab[ret].st_value;
929
                return get_sym_name(&symtab[ret]);
930
        }
931
}
932

    
933
/* 
934
 *  Find symbol name given a (virtual) address, and a section which is of type 
935
 *  S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
936
 */
937
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
938
{
939
    unsigned int tocindex, symindex, size;
940
    const char *name = 0;
941
    
942
    /* Sanity check */
943
    if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
944
        return (char*)0;
945
                
946
        if( sec_hdr->flags & S_SYMBOL_STUBS ){
947
                size = sec_hdr->reserved2;
948
                if(size == 0)
949
                    error("size = 0");
950
                
951
        }
952
        else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
953
                    sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
954
                size = sizeof(unsigned long);
955
        else
956
                return 0;
957
                
958
    /* Compute our index in toc */
959
        tocindex = (address - sec_hdr->addr)/size;
960
        symindex = tocdylib[sec_hdr->reserved1 + tocindex];
961
        
962
        name = get_sym_name(&symtab[symindex]);
963

    
964
    return name;
965
}
966

    
967
static const char * find_reloc_name_given_its_address(int address)
968
{
969
    unsigned int i;
970
    for(i = 0; i < segment->nsects ; i++)
971
    {
972
        const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
973
        if((long)name != -1)
974
            return name;
975
    }
976
    return 0;
977
}
978

    
979
static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
980
{
981
        char * name = 0;
982
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
983
        int sectnum = rel->r_symbolnum;
984
        int sectoffset;
985
        int other_half=0;
986
        
987
        /* init the slide value */
988
        *sslide = 0;
989
        
990
        if(R_SCATTERED & rel->r_address)
991
                return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
992

    
993
        if(rel->r_extern)
994
        {
995
                /* ignore debug sym */
996
                if ( symtab[rel->r_symbolnum].n_type & N_STAB ) 
997
                        return 0;
998
                return get_sym_name(&symtab[rel->r_symbolnum]);
999
        }
1000

    
1001
        /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1002
        sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1003
                        
1004
        if(sectnum==0xffffff)
1005
                return 0;
1006

    
1007
        /* Sanity Check */
1008
        if(sectnum > segment->nsects)
1009
                error("sectnum > segment->nsects");
1010

    
1011
        switch(rel->r_type)
1012
        {
1013
                case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1014
                        break;
1015
                case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1016
                        break;
1017
                case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1018
                        break;
1019
                case PPC_RELOC_BR24:
1020
                        sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1021
                        if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1022
                        break;
1023
                default:
1024
                        error("switch(rel->type) not found");
1025
        }
1026

    
1027
        if(rel->r_pcrel)
1028
                sectoffset += rel->r_address;
1029
                        
1030
        if (rel->r_type == PPC_RELOC_BR24)
1031
                name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1032

    
1033
        /* search it in the full symbol list, if not found */
1034
        if(!name)
1035
                name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1036
        
1037
        return name;
1038
}
1039

    
1040
/* Used by dyngen common code */
1041
static const char * get_rel_sym_name(EXE_RELOC * rel)
1042
{
1043
        int sslide;
1044
        return get_reloc_name( rel, &sslide);
1045
}
1046

    
1047
/* Used by dyngen common code */
1048
static host_ulong get_rel_offset(EXE_RELOC *rel)
1049
{
1050
        struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1051
    if(R_SCATTERED & rel->r_address)
1052
                return sca_rel->r_address;
1053
        else
1054
                return rel->r_address;
1055
}
1056

    
1057
/* load a mach-o object file */
1058
int load_object(const char *filename)
1059
{
1060
        int fd;
1061
        unsigned int offset_to_segment = 0;
1062
    unsigned int offset_to_dysymtab = 0;
1063
    unsigned int offset_to_symtab = 0;
1064
    struct load_command lc;
1065
    unsigned int i, j;
1066
        EXE_SYM *sym;
1067
        struct nlist *syment;
1068
    
1069
        fd = open(filename, O_RDONLY);
1070
    if (fd < 0) 
1071
        error("can't open file '%s'", filename);
1072
                
1073
    /* Read Mach header.  */
1074
    if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1075
        error("unable to read file header");
1076

    
1077
    /* Check Mach identification.  */
1078
    if (!check_mach_header(mach_hdr)) {
1079
        error("bad Mach header");
1080
    }
1081
    
1082
    if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1083
        error("Unsupported CPU");
1084
        
1085
    if (mach_hdr.filetype != MH_OBJECT)
1086
        error("Unsupported Mach Object");
1087
    
1088
    /* read segment headers */
1089
    for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1090
    {
1091
        if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1092
            error("unable to read load_command");
1093
        if(lc.cmd == LC_SEGMENT)
1094
        {
1095
            offset_to_segment = j;
1096
            lseek(fd, offset_to_segment, SEEK_SET);
1097
            segment = malloc(sizeof(struct segment_command));
1098
            if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1099
                error("unable to read LC_SEGMENT");
1100
        }
1101
        if(lc.cmd == LC_DYSYMTAB)
1102
        {
1103
            offset_to_dysymtab = j;
1104
            lseek(fd, offset_to_dysymtab, SEEK_SET);
1105
            dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1106
            if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1107
                error("unable to read LC_DYSYMTAB");
1108
        }
1109
        if(lc.cmd == LC_SYMTAB)
1110
        {
1111
            offset_to_symtab = j;
1112
            lseek(fd, offset_to_symtab, SEEK_SET);
1113
            symtabcmd = malloc(sizeof(struct symtab_command));
1114
            if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1115
                error("unable to read LC_SYMTAB");
1116
        }
1117
        j+=lc.cmdsize;
1118

    
1119
        lseek(fd, j, SEEK_SET);
1120
    }
1121

    
1122
    if(!segment)
1123
        error("unable to find LC_SEGMENT");
1124

    
1125
    /* read section headers */
1126
    section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1127

    
1128
    /* read all section data */
1129
    sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1130
    memset(sdata, 0, sizeof(void *) * segment->nsects);
1131
    
1132
        /* Load the data in section data */
1133
        for(i = 0; i < segment->nsects; i++) {
1134
        sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1135
    }
1136
        
1137
    /* text section */
1138
        text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1139
        i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1140
        if (i == -1 || !text_sec_hdr)
1141
        error("could not find __TEXT,__text section");
1142
    text = sdata[i];
1143
        
1144
    /* Make sure dysym was loaded */
1145
    if(!(int)dysymtabcmd)
1146
        error("could not find __DYSYMTAB segment");
1147
    
1148
    /* read the table of content of the indirect sym */
1149
    tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1150
    
1151
    /* Make sure symtab was loaded  */
1152
    if(!(int)symtabcmd)
1153
        error("could not find __SYMTAB segment");
1154
    nb_syms = symtabcmd->nsyms;
1155

    
1156
    symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1157
    strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1158
        
1159
        symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1160
        
1161
        /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1162
        for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1163
        struct nlist *sym_follow, *sym_next = 0;
1164
        unsigned int j;
1165
                memset(sym, 0, sizeof(*sym));
1166
                
1167
                if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1168
            continue;
1169
                        
1170
                memcpy(sym, syment, sizeof(*syment));
1171
                        
1172
                /* Find the following symbol in order to get the current symbol size */
1173
        for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1174
            if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1175
                continue;
1176
            if(!sym_next) {
1177
                sym_next = sym_follow;
1178
                continue;
1179
            }
1180
            if(!(sym_next->n_value > sym_follow->n_value))
1181
                continue;
1182
            sym_next = sym_follow;
1183
        }
1184
                if(sym_next)
1185
            sym->st_size = sym_next->n_value - sym->st_value;
1186
                else
1187
            sym->st_size = text_sec_hdr->size - sym->st_value;
1188
        }
1189
        
1190
    /* Find Reloc */
1191
    relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1192
    nb_relocs = text_sec_hdr->nreloc;
1193

    
1194
        close(fd);
1195
        return 0;
1196
}
1197

    
1198
#endif /* CONFIG_FORMAT_MACH */
1199

    
1200
void get_reloc_expr(char *name, int name_size, const char *sym_name)
1201
{
1202
    const char *p;
1203

    
1204
    if (strstart(sym_name, "__op_param", &p)) {
1205
        snprintf(name, name_size, "param%s", p);
1206
    } else if (strstart(sym_name, "__op_gen_label", &p)) {
1207
        snprintf(name, name_size, "gen_labels[param%s]", p);
1208
    } else {
1209
#ifdef HOST_SPARC
1210
        if (sym_name[0] == '.')
1211
            snprintf(name, name_size,
1212
                     "(long)(&__dot_%s)",
1213
                     sym_name + 1);
1214
        else
1215
#endif
1216
            snprintf(name, name_size, "(long)(&%s)", sym_name);
1217
    }
1218
}
1219

    
1220
#ifdef HOST_IA64
1221

    
1222
#define PLT_ENTRY_SIZE        16        /* 1 bundle containing "brl" */
1223

    
1224
struct plt_entry {
1225
    struct plt_entry *next;
1226
    const char *name;
1227
    unsigned long addend;
1228
} *plt_list;
1229

    
1230
static int
1231
get_plt_index (const char *name, unsigned long addend)
1232
{
1233
    struct plt_entry *plt, *prev= NULL;
1234
    int index = 0;
1235

    
1236
    /* see if we already have an entry for this target: */
1237
    for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1238
        if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1239
            return index;
1240

    
1241
    /* nope; create a new PLT entry: */
1242

    
1243
    plt = malloc(sizeof(*plt));
1244
    if (!plt) {
1245
        perror("malloc");
1246
        exit(1);
1247
    }
1248
    memset(plt, 0, sizeof(*plt));
1249
    plt->name = strdup(name);
1250
    plt->addend = addend;
1251

    
1252
    /* append to plt-list: */
1253
    if (prev)
1254
        prev->next = plt;
1255
    else
1256
        plt_list = plt;
1257
    return index;
1258
}
1259

    
1260
#endif
1261

    
1262
#ifdef HOST_ARM
1263

    
1264
int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1265
                      FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1266
                      ELF_RELOC *relocs, int nb_relocs)
1267
{
1268
    uint8_t *p;
1269
    uint32_t insn;
1270
    int offset, min_offset, pc_offset, data_size, spare, max_pool;
1271
    uint8_t data_allocated[1024];
1272
    unsigned int data_index;
1273
    int type;
1274
    
1275
    memset(data_allocated, 0, sizeof(data_allocated));
1276
    
1277
    p = p_start;
1278
    min_offset = p_end - p_start;
1279
    spare = 0x7fffffff;
1280
    while (p < p_start + min_offset) {
1281
        insn = get32((uint32_t *)p);
1282
        /* TODO: Armv5e ldrd.  */
1283
        /* TODO: VFP load.  */
1284
        if ((insn & 0x0d5f0000) == 0x051f0000) {
1285
            /* ldr reg, [pc, #im] */
1286
            offset = insn & 0xfff;
1287
            if (!(insn & 0x00800000))
1288
                offset = -offset;
1289
            max_pool = 4096;
1290
            type = 0;
1291
        } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1292
            /* FPA ldf.  */
1293
            offset = (insn & 0xff) << 2;
1294
            if (!(insn & 0x00800000))
1295
                offset = -offset;
1296
            max_pool = 1024;
1297
            type = 1;
1298
        } else if ((insn & 0x0fff0000) == 0x028f0000) {
1299
            /* Some gcc load a doubleword immediate with
1300
               add regN, pc, #imm
1301
               ldmia regN, {regN, regM}
1302
               Hope and pray the compiler never generates somethin like
1303
               add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1304
            int r;
1305

    
1306
            r = (insn & 0xf00) >> 7;
1307
            offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1308
            max_pool = 1024;
1309
            type = 2;
1310
        } else {
1311
            max_pool = 0;
1312
            type = -1;
1313
        }
1314
        if (type >= 0) {
1315
            /* PC-relative load needs fixing up.  */
1316
            if (spare > max_pool - offset)
1317
                spare = max_pool - offset;
1318
            if ((offset & 3) !=0)
1319
                error("%s:%04x: pc offset must be 32 bit aligned", 
1320
                      name, start_offset + p - p_start);
1321
            if (offset < 0)
1322
                error("%s:%04x: Embedded literal value",
1323
                      name, start_offset + p - p_start);
1324
            pc_offset = p - p_start + offset + 8;
1325
            if (pc_offset <= (p - p_start) || 
1326
                pc_offset >= (p_end - p_start))
1327
                error("%s:%04x: pc offset must point inside the function code", 
1328
                      name, start_offset + p - p_start);
1329
            if (pc_offset < min_offset)
1330
                min_offset = pc_offset;
1331
            if (outfile) {
1332
                /* The intruction position */
1333
                fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", 
1334
                        p - p_start);
1335
                /* The position of the constant pool data.  */
1336
                data_index = ((p_end - p_start) - pc_offset) >> 2;
1337
                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n", 
1338
                        data_index);
1339
                fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
1340
                fprintf(outfile, "    arm_ldr_ptr++;\n");
1341
            }
1342
        }
1343
        p += 4;
1344
    }
1345

    
1346
    /* Copy and relocate the constant pool data.  */
1347
    data_size = (p_end - p_start) - min_offset;
1348
    if (data_size > 0 && outfile) {
1349
        spare += min_offset;
1350
        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
1351
        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
1352
        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
1353
                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
1354
                         spare, spare);
1355

    
1356
        data_index = 0;
1357
        for (pc_offset = min_offset;
1358
             pc_offset < p_end - p_start;
1359
             pc_offset += 4) {
1360

    
1361
            ELF_RELOC *rel;
1362
            int i, addend, type;
1363
            const char *sym_name;
1364
            char relname[1024];
1365

    
1366
            /* data value */
1367
            addend = get32((uint32_t *)(p_start + pc_offset));
1368
            relname[0] = '\0';
1369
            for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1370
                if (rel->r_offset == (pc_offset + start_offset)) {
1371
                    sym_name = get_rel_sym_name(rel);
1372
                    /* the compiler leave some unnecessary references to the code */
1373
                    get_reloc_expr(relname, sizeof(relname), sym_name);
1374
                    type = ELF32_R_TYPE(rel->r_info);
1375
                    if (type != R_ARM_ABS32)
1376
                        error("%s: unsupported data relocation", name);
1377
                    break;
1378
                }
1379
            }
1380
            fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
1381
                    data_index, addend);
1382
            if (relname[0] != '\0')
1383
                fprintf(outfile, " + %s", relname);
1384
            fprintf(outfile, ";\n");
1385

    
1386
            data_index++;
1387
        }
1388
    }
1389

    
1390
    if (p == p_start)
1391
        goto arm_ret_error;
1392
    p -= 4;
1393
    insn = get32((uint32_t *)p);
1394
    /* The last instruction must be an ldm instruction.  There are several
1395
       forms generated by gcc:
1396
        ldmib sp, {..., pc}  (implies a sp adjustment of +4)
1397
        ldmia sp, {..., pc}
1398
        ldmea fp, {..., pc} */
1399
    if ((insn & 0xffff8000) == 0xe99d8000) {
1400
        if (outfile) {
1401
            fprintf(outfile,
1402
                    "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1403
                    p - p_start);
1404
        }
1405
        p += 4;
1406
    } else if ((insn & 0xffff8000) != 0xe89d8000
1407
        && (insn & 0xffff8000) != 0xe91b8000) {
1408
    arm_ret_error:
1409
        if (!outfile)
1410
            printf("%s: invalid epilog\n", name);
1411
    }
1412
    return p - p_start;
1413
}
1414
#endif
1415

    
1416

    
1417
#define MAX_ARGS 3
1418

    
1419
/* generate op code */
1420
void gen_code(const char *name, host_ulong offset, host_ulong size, 
1421
              FILE *outfile, int gen_switch)
1422
{
1423
    int copy_size = 0;
1424
    uint8_t *p_start, *p_end;
1425
    host_ulong start_offset;
1426
    int nb_args, i, n;
1427
    uint8_t args_present[MAX_ARGS];
1428
    const char *sym_name, *p;
1429
    EXE_RELOC *rel;
1430

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

    
1523
        uint32_t start_insn, end_insn1, end_insn2;
1524
        uint8_t *p;
1525
        p = (void *)(p_end - 8);
1526
        if (p <= p_start)
1527
            error("empty code for %s", name);
1528
        start_insn = get32((uint32_t *)(p_start + 0x0));
1529
        end_insn1 = get32((uint32_t *)(p + 0x0));
1530
        end_insn2 = get32((uint32_t *)(p + 0x4));
1531
        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1532
            (start_insn & ~0x1fff) == INSN_ADD_SP) {
1533
            p_start += 0x4;
1534
            start_offset += 0x4;
1535
            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1536
                /* SPARC v7: ret; restore; */ ;
1537
            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1538
                /* SPARC v9: return; nop; */ ;
1539
            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1540
                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1541
            else
1542

    
1543
                error("ret; restore; not found at end of %s", name);
1544
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1545
            ;
1546
        } else {
1547
            error("No save at the beginning of %s", name);
1548
        }
1549
#if 0
1550
        /* Skip a preceeding nop, if present.  */
1551
        if (p > p_start) {
1552
            skip_insn = get32((uint32_t *)(p - 0x4));
1553
            if (skip_insn == INSN_NOP)
1554
                p -= 4;
1555
        }
1556
#endif
1557
        copy_size = p - p_start;
1558
    }
1559
#elif defined(HOST_SPARC64)
1560
    {
1561
#define INSN_SAVE       0x9de3a000
1562
#define INSN_RET        0x81c7e008
1563
#define INSN_RETL       0x81c3e008
1564
#define INSN_RESTORE    0x81e80000
1565
#define INSN_RETURN     0x81cfe008
1566
#define INSN_NOP        0x01000000
1567
#define INSN_ADD_SP     0x9c03a000 // add %sp, nn, %sp
1568
#define INSN_SUB_SP     0x9c23a000 // sub %sp, nn, %sp
1569

    
1570
        uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1571
        uint8_t *p;
1572
        p = (void *)(p_end - 8);
1573
#if 0
1574
        /* XXX: check why it occurs */
1575
        if (p <= p_start)
1576
            error("empty code for %s", name);
1577
#endif
1578
        start_insn = get32((uint32_t *)(p_start + 0x0));
1579
        end_insn1 = get32((uint32_t *)(p + 0x0));
1580
        end_insn2 = get32((uint32_t *)(p + 0x4));
1581
        if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1582
            (start_insn & ~0x1fff) == INSN_ADD_SP) {
1583
            p_start += 0x4;
1584
            start_offset += 0x4;
1585
            if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1586
                /* SPARC v7: ret; restore; */ ;
1587
            else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1588
                /* SPARC v9: return; nop; */ ;
1589
            else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1590
                /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1591
            else
1592

    
1593
                error("ret; restore; not found at end of %s", name);
1594
        } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1595
            ;
1596
        } else {
1597
            error("No save at the beginning of %s", name);
1598
        }
1599
        
1600
        /* Skip a preceeding nop, if present.  */
1601
        if (p > p_start) {
1602
            skip_insn = get32((uint32_t *)(p - 0x4));
1603
            if (skip_insn == 0x01000000)
1604
                p -= 4;
1605
        }
1606
        
1607
        copy_size = p - p_start;
1608
    }
1609
#elif defined(HOST_ARM)
1610
    {
1611
        uint32_t insn;
1612

    
1613
        if ((p_end - p_start) <= 16)
1614
            error("%s: function too small", name);
1615
        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1616
            (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1617
            get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1618
            error("%s: invalid prolog", name);
1619
        p_start += 12;
1620
        start_offset += 12;
1621
        insn = get32((uint32_t *)p_start);
1622
        if ((insn & 0xffffff00) == 0xe24dd000) {
1623
            /* Stack adjustment.  Assume op uses the frame pointer.  */
1624
            p_start -= 4;
1625
            start_offset -= 4;
1626
        }
1627
        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, 
1628
                                      relocs, nb_relocs);
1629
    }
1630
#elif defined(HOST_M68K)
1631
    {
1632
        uint8_t *p;
1633
        p = (void *)(p_end - 2);
1634
        if (p == p_start)
1635
            error("empty code for %s", name);
1636
        // remove NOP's, probably added for alignment
1637
        while ((get16((uint16_t *)p) == 0x4e71) &&
1638
               (p>p_start)) 
1639
            p -= 2;
1640
        if (get16((uint16_t *)p) != 0x4e75)
1641
            error("rts expected at the end of %s", name);
1642
        copy_size = p - p_start;
1643
    }
1644
#else
1645
#error unsupported CPU
1646
#endif
1647

    
1648
    /* compute the number of arguments by looking at the relocations */
1649
    for(i = 0;i < MAX_ARGS; i++)
1650
        args_present[i] = 0;
1651

    
1652
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1653
        host_ulong offset = get_rel_offset(rel);
1654
        if (offset >= start_offset &&
1655
            offset < start_offset + (p_end - p_start)) {
1656
            sym_name = get_rel_sym_name(rel);
1657
            if(!sym_name)
1658
                continue;
1659
            if (strstart(sym_name, "__op_param", &p) ||
1660
                strstart(sym_name, "__op_gen_label", &p)) {
1661
                n = strtoul(p, NULL, 10);
1662
                if (n > MAX_ARGS)
1663
                    error("too many arguments in %s", name);
1664
                args_present[n - 1] = 1;
1665
            }
1666
        }
1667
    }
1668
    
1669
    nb_args = 0;
1670
    while (nb_args < MAX_ARGS && args_present[nb_args])
1671
        nb_args++;
1672
    for(i = nb_args; i < MAX_ARGS; i++) {
1673
        if (args_present[i])
1674
            error("inconsistent argument numbering in %s", name);
1675
    }
1676

    
1677
    if (gen_switch == 2) {
1678
        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1679
    } else if (gen_switch == 1) {
1680

    
1681
        /* output C code */
1682
        fprintf(outfile, "case INDEX_%s: {\n", name);
1683
        if (nb_args > 0) {
1684
            fprintf(outfile, "    long ");
1685
            for(i = 0; i < nb_args; i++) {
1686
                if (i != 0)
1687
                    fprintf(outfile, ", ");
1688
                fprintf(outfile, "param%d", i + 1);
1689
            }
1690
            fprintf(outfile, ";\n");
1691
        }
1692
#if defined(HOST_IA64)
1693
        fprintf(outfile, "    extern char %s;\n", name);
1694
#else
1695
        fprintf(outfile, "    extern void %s();\n", name);
1696
#endif
1697

    
1698
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1699
            host_ulong offset = get_rel_offset(rel);
1700
            if (offset >= start_offset &&
1701
                offset < start_offset + (p_end - p_start)) {
1702
                sym_name = get_rel_sym_name(rel);
1703
                if(!sym_name)
1704
                    continue;
1705
                if (*sym_name && 
1706
                    !strstart(sym_name, "__op_param", NULL) &&
1707
                    !strstart(sym_name, "__op_jmp", NULL) &&
1708
                    !strstart(sym_name, "__op_gen_label", NULL)) {
1709
#if defined(HOST_SPARC)
1710
                    if (sym_name[0] == '.') {
1711
                        fprintf(outfile,
1712
                                "extern char __dot_%s __asm__(\"%s\");\n",
1713
                                sym_name+1, sym_name);
1714
                        continue;
1715
                    }
1716
#endif
1717
#if defined(__APPLE__)
1718
/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
1719
                    fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
1720
#elif defined(HOST_IA64)
1721
                        if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1722
                                /*
1723
                                 * PCREL21 br.call targets generally
1724
                                 * are out of range and need to go
1725
                                 * through an "import stub".
1726
                                 */
1727
                                fprintf(outfile, "    extern char %s;\n",
1728
                                        sym_name);
1729
#else
1730
                    fprintf(outfile, "extern char %s;\n", sym_name);
1731
#endif
1732
                }
1733
            }
1734
        }
1735

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

    
1739
        /* emit code offset information */
1740
        {
1741
            EXE_SYM *sym;
1742
            const char *sym_name, *p;
1743
            unsigned long val;
1744
            int n;
1745

    
1746
            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1747
                sym_name = get_sym_name(sym);
1748
                if (strstart(sym_name, "__op_label", &p)) {
1749
                    uint8_t *ptr;
1750
                    unsigned long offset;
1751
                    
1752
                    /* test if the variable refers to a label inside
1753
                       the code we are generating */
1754
#ifdef CONFIG_FORMAT_COFF
1755
                    if (sym->st_shndx == text_shndx) {
1756
                        ptr = sdata[coff_text_shndx];
1757
                    } else if (sym->st_shndx == data_shndx) {
1758
                        ptr = sdata[coff_data_shndx];
1759
                    } else {
1760
                        ptr = NULL;
1761
                    }
1762
#elif defined(CONFIG_FORMAT_MACH)
1763
                    if(!sym->n_sect)
1764
                        continue;
1765
                    ptr = sdata[sym->n_sect-1];
1766
#else
1767
                    ptr = sdata[sym->st_shndx];
1768
#endif
1769
                    if (!ptr)
1770
                        error("__op_labelN in invalid section");
1771
                    offset = sym->st_value;
1772
#ifdef CONFIG_FORMAT_MACH
1773
                    offset -= section_hdr[sym->n_sect-1].addr;
1774
#endif
1775
                    val = *(unsigned long *)(ptr + offset);
1776
#ifdef ELF_USES_RELOCA
1777
                    {
1778
                        int reloc_shndx, nb_relocs1, j;
1779

    
1780
                        /* try to find a matching relocation */
1781
                        reloc_shndx = find_reloc(sym->st_shndx);
1782
                        if (reloc_shndx) {
1783
                            nb_relocs1 = shdr[reloc_shndx].sh_size / 
1784
                                shdr[reloc_shndx].sh_entsize;
1785
                            rel = (ELF_RELOC *)sdata[reloc_shndx];
1786
                            for(j = 0; j < nb_relocs1; j++) {
1787
                                if (rel->r_offset == offset) {
1788
                                    val = rel->r_addend;
1789
                                    break;
1790
                                }
1791
                                rel++;
1792
                            }
1793
                        }
1794
                    }
1795
#endif                    
1796
                    if (val >= start_offset && val <= start_offset + copy_size) {
1797
                        n = strtol(p, NULL, 10);
1798
                        fprintf(outfile, "    label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1799
                    }
1800
                }
1801
            }
1802
        }
1803

    
1804
        /* load parameres in variables */
1805
        for(i = 0; i < nb_args; i++) {
1806
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
1807
        }
1808

    
1809
        /* patch relocations */
1810
#if defined(HOST_I386)
1811
            {
1812
                char name[256];
1813
                int type;
1814
                int addend;
1815
                int reloc_offset;
1816
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1817
                if (rel->r_offset >= start_offset &&
1818
                    rel->r_offset < start_offset + copy_size) {
1819
                    sym_name = get_rel_sym_name(rel);
1820
                    if (!sym_name)
1821
                        continue;
1822
                    reloc_offset = rel->r_offset - start_offset;
1823
                    if (strstart(sym_name, "__op_jmp", &p)) {
1824
                        int n;
1825
                        n = strtol(p, NULL, 10);
1826
                        /* __op_jmp relocations are done at
1827
                           runtime to do translated block
1828
                           chaining: the offset of the instruction
1829
                           needs to be stored */
1830
                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1831
                                n, reloc_offset);
1832
                        continue;
1833
                    }
1834

    
1835
                    get_reloc_expr(name, sizeof(name), sym_name);
1836
                    addend = get32((uint32_t *)(text + rel->r_offset));
1837
#ifdef CONFIG_FORMAT_ELF
1838
                    type = ELF32_R_TYPE(rel->r_info);
1839
                    switch(type) {
1840
                    case R_386_32:
1841
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1842
                                reloc_offset, name, addend);
1843
                        break;
1844
                    case R_386_PC32:
1845
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", 
1846
                                reloc_offset, name, reloc_offset, addend);
1847
                        break;
1848
                    default:
1849
                        error("unsupported i386 relocation (%d)", type);
1850
                    }
1851
#elif defined(CONFIG_FORMAT_COFF)
1852
                    {
1853
                        char *temp_name;
1854
                        int j;
1855
                        EXE_SYM *sym;
1856
                        temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1857
                        if (!strcmp(temp_name, ".data")) {
1858
                            for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1859
                                if (strstart(sym->st_name, sym_name, NULL)) {
1860
                                    addend -= sym->st_value;
1861
                                }
1862
                            }
1863
                        }
1864
                    }
1865
                    type = rel->r_type;
1866
                    switch(type) {
1867
                    case DIR32:
1868
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1869
                                reloc_offset, name, addend);
1870
                        break;
1871
                    case DISP32:
1872
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n", 
1873
                                reloc_offset, name, reloc_offset, addend);
1874
                        break;
1875
                    default:
1876
                        error("unsupported i386 relocation (%d)", type);
1877
                    }
1878
#else
1879
#error unsupport object format
1880
#endif
1881
                }
1882
                }
1883
            }
1884
#elif defined(HOST_X86_64)
1885
            {
1886
                char name[256];
1887
                int type;
1888
                int addend;
1889
                int reloc_offset;
1890
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1891
                if (rel->r_offset >= start_offset &&
1892
                    rel->r_offset < start_offset + copy_size) {
1893
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1894
                    get_reloc_expr(name, sizeof(name), sym_name);
1895
                    type = ELF32_R_TYPE(rel->r_info);
1896
                    addend = rel->r_addend;
1897
                    reloc_offset = rel->r_offset - start_offset;
1898
                    switch(type) {
1899
                    case R_X86_64_32:
1900
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n", 
1901
                                reloc_offset, name, addend);
1902
                        break;
1903
                    case R_X86_64_32S:
1904
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", 
1905
                                reloc_offset, name, addend);
1906
                        break;
1907
                    case R_X86_64_PC32:
1908
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", 
1909
                                reloc_offset, name, reloc_offset, addend);
1910
                        break;
1911
                    default:
1912
                        error("unsupported X86_64 relocation (%d)", type);
1913
                    }
1914
                }
1915
                }
1916
            }
1917
#elif defined(HOST_PPC)
1918
            {
1919
#ifdef CONFIG_FORMAT_ELF
1920
                char name[256];
1921
                int type;
1922
                int addend;
1923
                int reloc_offset;
1924
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1925
                    if (rel->r_offset >= start_offset &&
1926
                        rel->r_offset < start_offset + copy_size) {
1927
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1928
                        reloc_offset = rel->r_offset - start_offset;
1929
                        if (strstart(sym_name, "__op_jmp", &p)) {
1930
                            int n;
1931
                            n = strtol(p, NULL, 10);
1932
                            /* __op_jmp relocations are done at
1933
                               runtime to do translated block
1934
                               chaining: the offset of the instruction
1935
                               needs to be stored */
1936
                            fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1937
                                    n, reloc_offset);
1938
                            continue;
1939
                        }
1940
                        
1941
                        get_reloc_expr(name, sizeof(name), sym_name);
1942
                        type = ELF32_R_TYPE(rel->r_info);
1943
                        addend = rel->r_addend;
1944
                        switch(type) {
1945
                        case R_PPC_ADDR32:
1946
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
1947
                                    reloc_offset, name, addend);
1948
                            break;
1949
                        case R_PPC_ADDR16_LO:
1950
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", 
1951
                                    reloc_offset, name, addend);
1952
                            break;
1953
                        case R_PPC_ADDR16_HI:
1954
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", 
1955
                                    reloc_offset, name, addend);
1956
                            break;
1957
                        case R_PPC_ADDR16_HA:
1958
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", 
1959
                                    reloc_offset, name, addend);
1960
                            break;
1961
                        case R_PPC_REL24:
1962
                            /* warning: must be at 32 MB distancy */
1963
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", 
1964
                                    reloc_offset, reloc_offset, name, reloc_offset, addend);
1965
                            break;
1966
                        default:
1967
                            error("unsupported powerpc relocation (%d)", type);
1968
                        }
1969
                    }
1970
                }
1971
#elif defined(CONFIG_FORMAT_MACH)
1972
                                struct scattered_relocation_info *scarel;
1973
                                struct relocation_info * rel;
1974
                                char final_sym_name[256];
1975
                                const char *sym_name;
1976
                                const char *p;
1977
                                int slide, sslide;
1978
                                int i;
1979
        
1980
                                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1981
                                        unsigned int offset, length, value = 0;
1982
                                        unsigned int type, pcrel, isym = 0;
1983
                                        unsigned int usesym = 0;
1984
                                
1985
                                        if(R_SCATTERED & rel->r_address) {
1986
                                                scarel = (struct scattered_relocation_info*)rel;
1987
                                                offset = (unsigned int)scarel->r_address;
1988
                                                length = scarel->r_length;
1989
                                                pcrel = scarel->r_pcrel;
1990
                                                type = scarel->r_type;
1991
                                                value = scarel->r_value;
1992
                                        } else {
1993
                                                value = isym = rel->r_symbolnum;
1994
                                                usesym = (rel->r_extern);
1995
                                                offset = rel->r_address;
1996
                                                length = rel->r_length;
1997
                                                pcrel = rel->r_pcrel;
1998
                                                type = rel->r_type;
1999
                                        }
2000
                                
2001
                                        slide = offset - start_offset;
2002
                
2003
                                        if (!(offset >= start_offset && offset < start_offset + size)) 
2004
                                                continue;  /* not in our range */
2005

    
2006
                                        sym_name = get_reloc_name(rel, &sslide);
2007
                                        
2008
                                        if(usesym && symtab[isym].n_type & N_STAB)
2009
                                                continue; /* don't handle STAB (debug sym) */
2010
                                        
2011
                                        if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2012
                                                int n;
2013
                                                n = strtol(p, NULL, 10);
2014
                                                fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2015
                                                        n, slide);
2016
                                                continue; /* Nothing more to do */
2017
                                        }
2018
                                        
2019
                                        if(!sym_name)
2020
                                        {
2021
                                                fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2022
                                                           name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2023
                                                continue; /* dunno how to handle without final_sym_name */
2024
                                        }
2025
                                                                                                           
2026
                                        get_reloc_expr(final_sym_name, sizeof(final_sym_name), 
2027
                                                       sym_name);
2028
                                        switch(type) {
2029
                                        case PPC_RELOC_BR24:
2030
                                            if (!strstart(sym_name,"__op_gen_label",&p)) {
2031
                                                    fprintf(outfile, "{\n");
2032
                                                    fprintf(outfile, "    uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2033
                                                    fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n", 
2034
                                                                                        slide, slide, name, sslide );
2035
                                                    fprintf(outfile, "}\n");
2036
                                            } else {
2037
                                                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2038
                                                                                        slide, slide, final_sym_name, slide);
2039
                                            }
2040
                                                break;
2041
                                        case PPC_RELOC_HI16:
2042
                                                fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n", 
2043
                                                        slide, final_sym_name, sslide);
2044
                                                break;
2045
                                        case PPC_RELOC_LO16:
2046
                                                fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n", 
2047
                                        slide, final_sym_name, sslide);
2048
                            break;
2049
                                        case PPC_RELOC_HA16:
2050
                                                fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n", 
2051
                                                        slide, final_sym_name, sslide);
2052
                                                break;
2053
                                default:
2054
                                        error("unsupported powerpc relocation (%d)", type);
2055
                                }
2056
                        }
2057
#else
2058
#error unsupport object format
2059
#endif
2060
            }
2061
#elif defined(HOST_S390)
2062
            {
2063
                char name[256];
2064
                int type;
2065
                int addend;
2066
                int reloc_offset;
2067
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2068
                    if (rel->r_offset >= start_offset &&
2069
                        rel->r_offset < start_offset + copy_size) {
2070
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2071
                        get_reloc_expr(name, sizeof(name), sym_name);
2072
                        type = ELF32_R_TYPE(rel->r_info);
2073
                        addend = rel->r_addend;
2074
                        reloc_offset = rel->r_offset - start_offset;
2075
                        switch(type) {
2076
                        case R_390_32:
2077
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
2078
                                    reloc_offset, name, addend);
2079
                            break;
2080
                        case R_390_16:
2081
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", 
2082
                                    reloc_offset, name, addend);
2083
                            break;
2084
                        case R_390_8:
2085
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", 
2086
                                    reloc_offset, name, addend);
2087
                            break;
2088
                        default:
2089
                            error("unsupported s390 relocation (%d)", type);
2090
                        }
2091
                    }
2092
                }
2093
            }
2094
#elif defined(HOST_ALPHA)
2095
            {
2096
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2097
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2098
                        int type;
2099
                        long reloc_offset;
2100

    
2101
                        type = ELF64_R_TYPE(rel->r_info);
2102
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2103
                        reloc_offset = rel->r_offset - start_offset;
2104
                        switch (type) {
2105
                        case R_ALPHA_GPDISP:
2106
                            /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2107
                               as an immediate instead of constructing it from the pv or ra.  */
2108
                            fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
2109
                                    reloc_offset);
2110
                            fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
2111
                                    reloc_offset + (int)rel->r_addend);
2112
                            break;
2113
                        case R_ALPHA_LITUSE:
2114
                            /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2115
                               now, since some called functions (libc) need pv to be set up.  */
2116
                            break;
2117
                        case R_ALPHA_HINT:
2118
                            /* Branch target prediction hint. Ignore for now.  Should be already
2119
                               correct for in-function jumps.  */
2120
                            break;
2121
                        case R_ALPHA_LITERAL:
2122
                            /* Load a literal from the GOT relative to the gp.  Since there's only a
2123
                               single gp, nothing is to be done.  */
2124
                            break;
2125
                        case R_ALPHA_GPRELHIGH:
2126
                            /* Handle fake relocations against __op_param symbol.  Need to emit the
2127
                               high part of the immediate value instead.  Other symbols need no
2128
                               special treatment.  */
2129
                            if (strstart(sym_name, "__op_param", &p))
2130
                                fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2131
                                        reloc_offset, p);
2132
                            break;
2133
                        case R_ALPHA_GPRELLOW:
2134
                            if (strstart(sym_name, "__op_param", &p))
2135
                                fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
2136
                                        reloc_offset, p);
2137
                            break;
2138
                        case R_ALPHA_BRSGP:
2139
                            /* PC-relative jump. Tweak offset to skip the two instructions that try to
2140
                               set up the gp from the pv.  */
2141
                            fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2142
                                    reloc_offset, sym_name, reloc_offset);
2143
                            break;
2144
                        default:
2145
                            error("unsupported Alpha relocation (%d)", type);
2146
                        }
2147
                    }
2148
                }
2149
            }
2150
#elif defined(HOST_IA64)
2151
            {
2152
                unsigned long sym_idx;
2153
                long code_offset;
2154
                char name[256];
2155
                int type;
2156
                long addend;
2157

    
2158
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2159
                    sym_idx = ELF64_R_SYM(rel->r_info);
2160
                    if (rel->r_offset < start_offset
2161
                        || rel->r_offset >= start_offset + copy_size)
2162
                        continue;
2163
                    sym_name = (strtab + symtab[sym_idx].st_name);
2164
                    code_offset = rel->r_offset - start_offset;
2165
                    if (strstart(sym_name, "__op_jmp", &p)) {
2166
                        int n;
2167
                        n = strtol(p, NULL, 10);
2168
                        /* __op_jmp relocations are done at
2169
                           runtime to do translated block
2170
                           chaining: the offset of the instruction
2171
                           needs to be stored */
2172
                        fprintf(outfile, "    jmp_offsets[%d] ="
2173
                                "%ld + (gen_code_ptr - gen_code_buf);\n",
2174
                                n, code_offset);
2175
                        continue;
2176
                    }
2177
                    get_reloc_expr(name, sizeof(name), sym_name);
2178
                    type = ELF64_R_TYPE(rel->r_info);
2179
                    addend = rel->r_addend;
2180
                    switch(type) {
2181
                      case R_IA64_IMM64:
2182
                          fprintf(outfile,
2183
                                  "    ia64_imm64(gen_code_ptr + %ld, "
2184
                                  "%s + %ld);\n",
2185
                                  code_offset, name, addend);
2186
                          break;
2187
                      case R_IA64_LTOFF22X:
2188
                      case R_IA64_LTOFF22:
2189
                          fprintf(outfile, "    IA64_LTOFF(gen_code_ptr + %ld,"
2190
                                  " %s + %ld, %d);\n",
2191
                                  code_offset, name, addend,
2192
                                  (type == R_IA64_LTOFF22X));
2193
                          break;
2194
                      case R_IA64_LDXMOV:
2195
                          fprintf(outfile,
2196
                                  "    ia64_ldxmov(gen_code_ptr + %ld,"
2197
                                  " %s + %ld);\n", code_offset, name, addend);
2198
                          break;
2199

    
2200
                      case R_IA64_PCREL21B:
2201
                          if (strstart(sym_name, "__op_gen_label", NULL)) {
2202
                              fprintf(outfile,
2203
                                      "    ia64_imm21b(gen_code_ptr + %ld,"
2204
                                      " (long) (%s + %ld -\n\t\t"
2205
                                      "((long) gen_code_ptr + %ld)) >> 4);\n",
2206
                                      code_offset, name, addend,
2207
                                      code_offset & ~0xfUL);
2208
                          } else {
2209
                              fprintf(outfile,
2210
                                      "    IA64_PLT(gen_code_ptr + %ld, "
2211
                                      "%d);\t/* %s + %ld */\n",
2212
                                      code_offset,
2213
                                      get_plt_index(sym_name, addend),
2214
                                      sym_name, addend);
2215
                          }
2216
                          break;
2217
                      default:
2218
                          error("unsupported ia64 relocation (0x%x)",
2219
                                type);
2220
                    }
2221
                }
2222
                fprintf(outfile, "    ia64_nop_b(gen_code_ptr + %d);\n",
2223
                        copy_size - 16 + 2);
2224
            }
2225
#elif defined(HOST_SPARC)
2226
            {
2227
                char name[256];
2228
                int type;
2229
                int addend;
2230
                int reloc_offset;
2231
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2232
                    if (rel->r_offset >= start_offset &&
2233
                        rel->r_offset < start_offset + copy_size) {
2234
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2235
                        get_reloc_expr(name, sizeof(name), sym_name);
2236
                        type = ELF32_R_TYPE(rel->r_info);
2237
                        addend = rel->r_addend;
2238
                        reloc_offset = rel->r_offset - start_offset;
2239
                        switch(type) {
2240
                        case R_SPARC_32:
2241
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
2242
                                    reloc_offset, name, addend);
2243
                            break;
2244
                        case R_SPARC_HI22:
2245
                            fprintf(outfile,
2246
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2247
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2248
                                    " & ~0x3fffff) "
2249
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2250
                                    reloc_offset, reloc_offset, name, addend);
2251
                            break;
2252
                        case R_SPARC_LO10:
2253
                            fprintf(outfile,
2254
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2255
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2256
                                    " & ~0x3ff) "
2257
                                    " | ((%s + %d) & 0x3ff);\n",
2258
                                    reloc_offset, reloc_offset, name, addend);
2259
                            break;
2260
                        case R_SPARC_WDISP30:
2261
                            fprintf(outfile,
2262
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2263
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2264
                                    " & ~0x3fffffff) "
2265
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2266
                                    "    & 0x3fffffff);\n",
2267
                                    reloc_offset, reloc_offset, name, addend,
2268
                                    reloc_offset);
2269
                            break;
2270
                        case R_SPARC_WDISP22:
2271
                            fprintf(outfile,
2272
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2273
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2274
                                    " & ~0x3fffff) "
2275
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2276
                                    "    & 0x3fffff);\n",
2277
                                    rel->r_offset - start_offset,
2278
                                    rel->r_offset - start_offset,
2279
                                    name, addend,
2280
                                    rel->r_offset - start_offset);
2281
                            break;
2282
                        default:
2283
                            error("unsupported sparc relocation (%d)", type);
2284
                        }
2285
                    }
2286
                }
2287
            }
2288
#elif defined(HOST_SPARC64)
2289
            {
2290
                char name[256];
2291
                int type;
2292
                int addend;
2293
                int reloc_offset;
2294
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2295
                    if (rel->r_offset >= start_offset &&
2296
                        rel->r_offset < start_offset + copy_size) {
2297
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2298
                        get_reloc_expr(name, sizeof(name), sym_name);
2299
                        type = ELF32_R_TYPE(rel->r_info);
2300
                        addend = rel->r_addend;
2301
                        reloc_offset = rel->r_offset - start_offset;
2302
                        switch(type) {
2303
                        case R_SPARC_32:
2304
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2305
                                    reloc_offset, name, addend);
2306
                            break;
2307
                        case R_SPARC_HI22:
2308
                            fprintf(outfile,
2309
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2310
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2311
                                    " & ~0x3fffff) "
2312
                                    " | (((%s + %d) >> 10) & 0x3fffff);\n",
2313
                                    reloc_offset, reloc_offset, name, addend);
2314
                            break;
2315
                        case R_SPARC_LO10:
2316
                            fprintf(outfile,
2317
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2318
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2319
                                    " & ~0x3ff) "
2320
                                    " | ((%s + %d) & 0x3ff);\n",
2321
                                    reloc_offset, reloc_offset, name, addend);
2322
                            break;
2323
                        case R_SPARC_OLO10:
2324
                            addend += ELF64_R_TYPE_DATA (rel->r_info);
2325
                            fprintf(outfile,
2326
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2327
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2328
                                    " & ~0x3ff) "
2329
                                    " | ((%s + %d) & 0x3ff);\n",
2330
                                    reloc_offset, reloc_offset, name, addend);
2331
                            break;
2332
                        case R_SPARC_WDISP30:
2333
                            fprintf(outfile,
2334
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2335
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2336
                                    " & ~0x3fffffff) "
2337
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2338
                                    "    & 0x3fffffff);\n",
2339
                                    reloc_offset, reloc_offset, name, addend,
2340
                                    reloc_offset);
2341
                            break;
2342
                        case R_SPARC_WDISP22:
2343
                            fprintf(outfile,
2344
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2345
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2346
                                    " & ~0x3fffff) "
2347
                                    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2348
                                    "    & 0x3fffff);\n",
2349
                                    reloc_offset, reloc_offset, name, addend,
2350
                                    reloc_offset);
2351
                            break;
2352
                        case R_SPARC_HH22:
2353
                            fprintf(outfile,
2354
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2355
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2356
                                    " & ~0x00000000) "
2357
                                    " | (((%s + %d) >> 42) & 0x00000000);\n",
2358
                                    reloc_offset, reloc_offset, name, addend);
2359
                             break;
2360

    
2361
                        case R_SPARC_LM22:
2362
                            fprintf(outfile,
2363
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2364
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2365
                                    " & ~0x00000000) "
2366
                                    " | (((%s + %d) >> 10) & 0x00000000);\n",
2367
                                    reloc_offset, reloc_offset, name, addend);
2368
                            break;
2369

    
2370
                        case R_SPARC_HM10:
2371
                            fprintf(outfile,
2372
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
2373
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
2374
                                    " & ~0x00000000) "
2375
                                    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2376
                                    reloc_offset, reloc_offset, name, addend);
2377
                            break;
2378

    
2379
                        default:
2380
                            error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
2381
                        }
2382
                    }
2383
                }
2384
            }
2385
#elif defined(HOST_ARM)
2386
            {
2387
                char name[256];
2388
                int type;
2389
                int addend;
2390
                int reloc_offset;
2391
                uint32_t insn;
2392

    
2393
                insn = get32((uint32_t *)(p_start + 4));
2394
                /* If prologue ends in sub sp, sp, #const then assume
2395
                   op has a stack frame and needs the frame pointer.  */
2396
                if ((insn & 0xffffff00) == 0xe24dd000) {
2397
                    int i;
2398
                    uint32_t opcode;
2399
                    opcode = 0xe28db000; /* add fp, sp, #0.  */
2400
#if 0
2401
/* ??? Need to undo the extra stack adjustment at the end of the op.
2402
   For now just leave the stack misaligned and hope it doesn't break anything
2403
   too important.  */
2404
                    if ((insn & 4) != 0) {
2405
                        /* Preserve doubleword stack alignment.  */
2406
                        fprintf(outfile,
2407
                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2408
                                insn + 4);
2409
                        opcode -= 4;
2410
                    }
2411
#endif
2412
                    insn = get32((uint32_t *)(p_start - 4));
2413
                    /* Calculate the size of the saved registers,
2414
                       excluding pc.  */
2415
                    for (i = 0; i < 15; i++) {
2416
                        if (insn & (1 << i))
2417
                            opcode += 4;
2418
                    }
2419
                    fprintf(outfile,
2420
                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2421
                }
2422
                arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
2423
                                  relocs, nb_relocs);
2424

    
2425
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2426
                if (rel->r_offset >= start_offset &&
2427
                    rel->r_offset < start_offset + copy_size) {
2428
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2429
                    /* the compiler leave some unnecessary references to the code */
2430
                    if (sym_name[0] == '\0')
2431
                        continue;
2432
                    get_reloc_expr(name, sizeof(name), sym_name);
2433
                    type = ELF32_R_TYPE(rel->r_info);
2434
                    addend = get32((uint32_t *)(text + rel->r_offset));
2435
                    reloc_offset = rel->r_offset - start_offset;
2436
                    switch(type) {
2437
                    case R_ARM_ABS32:
2438
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
2439
                                reloc_offset, name, addend);
2440
                        break;
2441
                    case R_ARM_PC24:
2442
                    case R_ARM_JUMP24:
2443
                    case R_ARM_CALL:
2444
                        fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n", 
2445
                                reloc_offset, addend, name);
2446
                        break;
2447
                    default:
2448
                        error("unsupported arm relocation (%d)", type);
2449
                    }
2450
                }
2451
                }
2452
            }
2453
#elif defined(HOST_M68K)
2454
            {
2455
                char name[256];
2456
                int type;
2457
                int addend;
2458
                int reloc_offset;
2459
                Elf32_Sym *sym;
2460
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2461
                if (rel->r_offset >= start_offset &&
2462
                    rel->r_offset < start_offset + copy_size) {
2463
                    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2464
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2465
                    get_reloc_expr(name, sizeof(name), sym_name);
2466
                    type = ELF32_R_TYPE(rel->r_info);
2467
                    addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2468
                    reloc_offset = rel->r_offset - start_offset;
2469
                    switch(type) {
2470
                    case R_68K_32:
2471
                        fprintf(outfile, "    /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2472
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n", 
2473
                                reloc_offset, name, addend );
2474
                        break;
2475
                    case R_68K_PC32:
2476
                        fprintf(outfile, "    /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2477
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n", 
2478
                                reloc_offset, name, reloc_offset, /*sym->st_value+*/ addend);
2479
                        break;
2480
                    default:
2481
                        error("unsupported m68k relocation (%d)", type);
2482
                    }
2483
                }
2484
                }
2485
            }
2486
#else
2487
#error unsupported CPU
2488
#endif
2489
        fprintf(outfile, "    gen_code_ptr += %d;\n", copy_size);
2490
        fprintf(outfile, "}\n");
2491
        fprintf(outfile, "break;\n\n");
2492
    } else {
2493
        fprintf(outfile, "static inline void gen_%s(", name);
2494
        if (nb_args == 0) {
2495
            fprintf(outfile, "void");
2496
        } else {
2497
            for(i = 0; i < nb_args; i++) {
2498
                if (i != 0)
2499
                    fprintf(outfile, ", ");
2500
                fprintf(outfile, "long param%d", i + 1);
2501
            }
2502
        }
2503
        fprintf(outfile, ")\n");
2504
        fprintf(outfile, "{\n");
2505
        for(i = 0; i < nb_args; i++) {
2506
            fprintf(outfile, "    *gen_opparam_ptr++ = param%d;\n", i + 1);
2507
        }
2508
        fprintf(outfile, "    *gen_opc_ptr++ = INDEX_%s;\n", name);
2509
        fprintf(outfile, "}\n\n");
2510
    }
2511
}
2512

    
2513
int gen_file(FILE *outfile, int out_type)
2514
{
2515
    int i;
2516
    EXE_SYM *sym;
2517

    
2518
    if (out_type == OUT_INDEX_OP) {
2519
        fprintf(outfile, "DEF(end, 0, 0)\n");
2520
        fprintf(outfile, "DEF(nop, 0, 0)\n");
2521
        fprintf(outfile, "DEF(nop1, 1, 0)\n");
2522
        fprintf(outfile, "DEF(nop2, 2, 0)\n");
2523
        fprintf(outfile, "DEF(nop3, 3, 0)\n");
2524
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2525
            const char *name;
2526
            name = get_sym_name(sym);
2527
            if (strstart(name, OP_PREFIX, NULL)) {
2528
                gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2529
            }
2530
        }
2531
    } else if (out_type == OUT_GEN_OP) {
2532
        /* generate gen_xxx functions */
2533
        fprintf(outfile, "#include \"dyngen-op.h\"\n");
2534
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2535
            const char *name;
2536
            name = get_sym_name(sym);
2537
            if (strstart(name, OP_PREFIX, NULL)) {
2538
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2539
                if (sym->st_shndx != text_shndx)
2540
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2541
#endif
2542
                gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2543
            }
2544
        }
2545
        
2546
    } else {
2547
        /* generate big code generation switch */
2548

    
2549
#ifdef HOST_ARM
2550
        /* We need to know the size of all the ops so we can figure out when
2551
           to emit constant pools.  This must be consistent with opc.h.  */
2552
fprintf(outfile,
2553
"static const uint32_t arm_opc_size[] = {\n"
2554
"  0,\n" /* end */
2555
"  0,\n" /* nop */
2556
"  0,\n" /* nop1 */
2557
"  0,\n" /* nop2 */
2558
"  0,\n"); /* nop3 */
2559
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2560
            const char *name;
2561
            name = get_sym_name(sym);
2562
            if (strstart(name, OP_PREFIX, NULL)) {
2563
                fprintf(outfile, "  %d,\n", sym->st_size);
2564
            }
2565
        }
2566
fprintf(outfile,
2567
"};\n");
2568
#endif
2569

    
2570
fprintf(outfile,
2571
"int dyngen_code(uint8_t *gen_code_buf,\n"
2572
"                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2573
"                const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2574
"{\n"
2575
"    uint8_t *gen_code_ptr;\n"
2576
"    const uint16_t *opc_ptr;\n"
2577
"    const uint32_t *opparam_ptr;\n");
2578

    
2579
#ifdef HOST_ARM
2580
/* Arm is tricky because it uses constant pools for loading immediate values.
2581
   We assume (and require) each function is code followed by a constant pool.
2582
   All the ops are small so this should be ok.  For each op we figure
2583
   out how much "spare" range we have in the load instructions.  This allows
2584
   us to insert subsequent ops in between the op and the constant pool,
2585
   eliminating the neeed to jump around the pool.
2586

2587
   We currently generate:
2588
   
2589
   [ For this example we assume merging would move op1_pool out of range.
2590
     In practice we should be able to combine many ops before the offset
2591
     limits are reached. ]
2592
   op1_code;
2593
   op2_code;
2594
   goto op3;
2595
   op2_pool;
2596
   op1_pool;
2597
op3:
2598
   op3_code;
2599
   ret;
2600
   op3_pool;
2601

2602
   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2603
 */
2604
fprintf(outfile,
2605
"    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2606
"    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2607
"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2608
/* Initialise the parmissible pool offset to an arbitary large value.  */
2609
"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2610
#endif
2611
#ifdef HOST_IA64
2612
    {
2613
        long addend, not_first = 0;
2614
        unsigned long sym_idx;
2615
        int index, max_index;
2616
        const char *sym_name;
2617
        EXE_RELOC *rel;
2618

    
2619
        max_index = -1;
2620
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2621
            sym_idx = ELF64_R_SYM(rel->r_info);
2622
            sym_name = (strtab + symtab[sym_idx].st_name);
2623
            if (strstart(sym_name, "__op_gen_label", NULL))
2624
                continue;
2625
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2626
                continue;
2627

    
2628
            addend = rel->r_addend;
2629
            index = get_plt_index(sym_name, addend);
2630
            if (index <= max_index)
2631
                continue;
2632
            max_index = index;
2633
            fprintf(outfile, "    extern void %s(void);\n", sym_name);
2634
        }
2635

    
2636
        fprintf(outfile,
2637
                "    struct ia64_fixup *plt_fixes = NULL, "
2638
                "*ltoff_fixes = NULL;\n"
2639
                "    static long plt_target[] = {\n\t");
2640

    
2641
        max_index = -1;
2642
        for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2643
            sym_idx = ELF64_R_SYM(rel->r_info);
2644
            sym_name = (strtab + symtab[sym_idx].st_name);
2645
            if (strstart(sym_name, "__op_gen_label", NULL))
2646
                continue;
2647
            if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2648
                continue;
2649

    
2650
            addend = rel->r_addend;
2651
            index = get_plt_index(sym_name, addend);
2652
            if (index <= max_index)
2653
                continue;
2654
            max_index = index;
2655

    
2656
            if (not_first)
2657
                fprintf(outfile, ",\n\t");
2658
            not_first = 1;
2659
            if (addend)
2660
                fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2661
            else
2662
                fprintf(outfile, "(long) &%s", sym_name);
2663
        }
2664
        fprintf(outfile, "\n    };\n"
2665
            "    unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2666
    }
2667
#endif
2668

    
2669
fprintf(outfile,
2670
"\n"
2671
"    gen_code_ptr = gen_code_buf;\n"
2672
"    opc_ptr = opc_buf;\n"
2673
"    opparam_ptr = opparam_buf;\n");
2674

    
2675
        /* Generate prologue, if needed. */ 
2676

    
2677
fprintf(outfile,
2678
"    for(;;) {\n");
2679

    
2680
#ifdef HOST_ARM
2681
/* Generate constant pool if needed */
2682
fprintf(outfile,
2683
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2684
"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2685
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2686
"                last_gen_code_ptr = gen_code_ptr;\n"
2687
"                arm_ldr_ptr = arm_ldr_table;\n"
2688
"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2689
"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2690
"            }\n");
2691
#endif
2692

    
2693
fprintf(outfile,
2694
"        switch(*opc_ptr++) {\n");
2695

    
2696
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2697
            const char *name;
2698
            name = get_sym_name(sym);
2699
            if (strstart(name, OP_PREFIX, NULL)) {
2700
#if 0
2701
                printf("%4d: %s pos=0x%08x len=%d\n", 
2702
                       i, name, sym->st_value, sym->st_size);
2703
#endif
2704
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2705
                if (sym->st_shndx != text_shndx)
2706
                    error("invalid section for opcode (0x%x)", sym->st_shndx);
2707
#endif
2708
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2709
            }
2710
        }
2711

    
2712
fprintf(outfile,
2713
"        case INDEX_op_nop:\n"
2714
"            break;\n"
2715
"        case INDEX_op_nop1:\n"
2716
"            opparam_ptr++;\n"
2717
"            break;\n"
2718
"        case INDEX_op_nop2:\n"
2719
"            opparam_ptr += 2;\n"
2720
"            break;\n"
2721
"        case INDEX_op_nop3:\n"
2722
"            opparam_ptr += 3;\n"
2723
"            break;\n"
2724
"        default:\n"
2725
"            goto the_end;\n"
2726
"        }\n");
2727

    
2728

    
2729
fprintf(outfile,
2730
"    }\n"
2731
" the_end:\n"
2732
);
2733
#ifdef HOST_IA64
2734
    fprintf(outfile,
2735
            "    {\n"
2736
            "      extern char code_gen_buffer[];\n"
2737
            "      ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2738
            "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2739
            "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2740
            "plt_target, plt_offset);\n    }\n");
2741
#endif
2742

    
2743
/* generate some code patching */ 
2744
#ifdef HOST_ARM
2745
fprintf(outfile,
2746
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2747
"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2748
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2749
#endif
2750
    /* flush instruction cache */
2751
    fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2752

    
2753
    fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n");
2754
    fprintf(outfile, "}\n\n");
2755

    
2756
    }
2757

    
2758
    return 0;
2759
}
2760

    
2761
void usage(void)
2762
{
2763
    printf("dyngen (c) 2003 Fabrice Bellard\n"
2764
           "usage: dyngen [-o outfile] [-c] objfile\n"
2765
           "Generate a dynamic code generator from an object file\n"
2766
           "-c     output enum of operations\n"
2767
           "-g     output gen_op_xx() functions\n"
2768
           );
2769
    exit(1);
2770
}
2771

    
2772
int main(int argc, char **argv)
2773
{
2774
    int c, out_type;
2775
    const char *filename, *outfilename;
2776
    FILE *outfile;
2777

    
2778
    outfilename = "out.c";
2779
    out_type = OUT_CODE;
2780
    for(;;) {
2781
        c = getopt(argc, argv, "ho:cg");
2782
        if (c == -1)
2783
            break;
2784
        switch(c) {
2785
        case 'h':
2786
            usage();
2787
            break;
2788
        case 'o':
2789
            outfilename = optarg;
2790
            break;
2791
        case 'c':
2792
            out_type = OUT_INDEX_OP;
2793
            break;
2794
        case 'g':
2795
            out_type = OUT_GEN_OP;
2796
            break;
2797
        }
2798
    }
2799
    if (optind >= argc)
2800
        usage();
2801
    filename = argv[optind];
2802
    outfile = fopen(outfilename, "w");
2803
    if (!outfile)
2804
        error("could not open '%s'", outfilename);
2805

    
2806
    load_object(filename);
2807
    gen_file(outfile, out_type);
2808
    fclose(outfile);
2809
    return 0;
2810
}