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