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