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