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