Add serial loopback mode (patch from Hervé Poussineau).
[qemu/mini2440.git] / dyngen.c
blobe5122e37323bf5a024bd4a1bd3fd8739c82411a4
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 /* return true if the expression is a label reference */
1216 int get_reloc_expr(char *name, int name_size, const char *sym_name)
1218 const char *p;
1220 if (strstart(sym_name, "__op_param", &p)) {
1221 snprintf(name, name_size, "param%s", p);
1222 } else if (strstart(sym_name, "__op_gen_label", &p)) {
1223 snprintf(name, name_size, "param%s", p);
1224 return 1;
1225 } else {
1226 #ifdef HOST_SPARC
1227 if (sym_name[0] == '.')
1228 snprintf(name, name_size,
1229 "(long)(&__dot_%s)",
1230 sym_name + 1);
1231 else
1232 #endif
1233 snprintf(name, name_size, "(long)(&%s)", sym_name);
1235 return 0;
1238 #ifdef HOST_IA64
1240 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1242 struct plt_entry {
1243 struct plt_entry *next;
1244 const char *name;
1245 unsigned long addend;
1246 } *plt_list;
1248 static int
1249 get_plt_index (const char *name, unsigned long addend)
1251 struct plt_entry *plt, *prev= NULL;
1252 int index = 0;
1254 /* see if we already have an entry for this target: */
1255 for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1256 if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1257 return index;
1259 /* nope; create a new PLT entry: */
1261 plt = malloc(sizeof(*plt));
1262 if (!plt) {
1263 perror("malloc");
1264 exit(1);
1266 memset(plt, 0, sizeof(*plt));
1267 plt->name = strdup(name);
1268 plt->addend = addend;
1270 /* append to plt-list: */
1271 if (prev)
1272 prev->next = plt;
1273 else
1274 plt_list = plt;
1275 return index;
1278 #endif
1280 #ifdef HOST_ARM
1282 int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1283 FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1284 ELF_RELOC *relocs, int nb_relocs)
1286 uint8_t *p;
1287 uint32_t insn;
1288 int offset, min_offset, pc_offset, data_size, spare, max_pool;
1289 uint8_t data_allocated[1024];
1290 unsigned int data_index;
1291 int type;
1293 memset(data_allocated, 0, sizeof(data_allocated));
1295 p = p_start;
1296 min_offset = p_end - p_start;
1297 spare = 0x7fffffff;
1298 while (p < p_start + min_offset) {
1299 insn = get32((uint32_t *)p);
1300 /* TODO: Armv5e ldrd. */
1301 /* TODO: VFP load. */
1302 if ((insn & 0x0d5f0000) == 0x051f0000) {
1303 /* ldr reg, [pc, #im] */
1304 offset = insn & 0xfff;
1305 if (!(insn & 0x00800000))
1306 offset = -offset;
1307 max_pool = 4096;
1308 type = 0;
1309 } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1310 /* FPA ldf. */
1311 offset = (insn & 0xff) << 2;
1312 if (!(insn & 0x00800000))
1313 offset = -offset;
1314 max_pool = 1024;
1315 type = 1;
1316 } else if ((insn & 0x0fff0000) == 0x028f0000) {
1317 /* Some gcc load a doubleword immediate with
1318 add regN, pc, #imm
1319 ldmia regN, {regN, regM}
1320 Hope and pray the compiler never generates somethin like
1321 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1322 int r;
1324 r = (insn & 0xf00) >> 7;
1325 offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1326 max_pool = 1024;
1327 type = 2;
1328 } else {
1329 max_pool = 0;
1330 type = -1;
1332 if (type >= 0) {
1333 /* PC-relative load needs fixing up. */
1334 if (spare > max_pool - offset)
1335 spare = max_pool - offset;
1336 if ((offset & 3) !=0)
1337 error("%s:%04x: pc offset must be 32 bit aligned",
1338 name, start_offset + p - p_start);
1339 if (offset < 0)
1340 error("%s:%04x: Embedded literal value",
1341 name, start_offset + p - p_start);
1342 pc_offset = p - p_start + offset + 8;
1343 if (pc_offset <= (p - p_start) ||
1344 pc_offset >= (p_end - p_start))
1345 error("%s:%04x: pc offset must point inside the function code",
1346 name, start_offset + p - p_start);
1347 if (pc_offset < min_offset)
1348 min_offset = pc_offset;
1349 if (outfile) {
1350 /* The intruction position */
1351 fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1352 p - p_start);
1353 /* The position of the constant pool data. */
1354 data_index = ((p_end - p_start) - pc_offset) >> 2;
1355 fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1356 data_index);
1357 fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
1358 fprintf(outfile, " arm_ldr_ptr++;\n");
1361 p += 4;
1364 /* Copy and relocate the constant pool data. */
1365 data_size = (p_end - p_start) - min_offset;
1366 if (data_size > 0 && outfile) {
1367 spare += min_offset;
1368 fprintf(outfile, " arm_data_ptr -= %d;\n", data_size >> 2);
1369 fprintf(outfile, " arm_pool_ptr -= %d;\n", data_size);
1370 fprintf(outfile, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1371 " arm_pool_ptr = gen_code_ptr + %d;\n",
1372 spare, spare);
1374 data_index = 0;
1375 for (pc_offset = min_offset;
1376 pc_offset < p_end - p_start;
1377 pc_offset += 4) {
1379 ELF_RELOC *rel;
1380 int i, addend, type;
1381 const char *sym_name;
1382 char relname[1024];
1384 /* data value */
1385 addend = get32((uint32_t *)(p_start + pc_offset));
1386 relname[0] = '\0';
1387 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1388 if (rel->r_offset == (pc_offset + start_offset)) {
1389 sym_name = get_rel_sym_name(rel);
1390 /* the compiler leave some unnecessary references to the code */
1391 get_reloc_expr(relname, sizeof(relname), sym_name);
1392 type = ELF32_R_TYPE(rel->r_info);
1393 if (type != R_ARM_ABS32)
1394 error("%s: unsupported data relocation", name);
1395 break;
1398 fprintf(outfile, " arm_data_ptr[%d] = 0x%x",
1399 data_index, addend);
1400 if (relname[0] != '\0')
1401 fprintf(outfile, " + %s", relname);
1402 fprintf(outfile, ";\n");
1404 data_index++;
1408 if (p == p_start)
1409 goto arm_ret_error;
1410 p -= 4;
1411 insn = get32((uint32_t *)p);
1412 /* The last instruction must be an ldm instruction. There are several
1413 forms generated by gcc:
1414 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1415 ldmia sp, {..., pc}
1416 ldmea fp, {..., pc} */
1417 if ((insn & 0xffff8000) == 0xe99d8000) {
1418 if (outfile) {
1419 fprintf(outfile,
1420 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1421 p - p_start);
1423 p += 4;
1424 } else if ((insn & 0xffff8000) != 0xe89d8000
1425 && (insn & 0xffff8000) != 0xe91b8000) {
1426 arm_ret_error:
1427 if (!outfile)
1428 printf("%s: invalid epilog\n", name);
1430 return p - p_start;
1432 #endif
1435 #define MAX_ARGS 3
1437 /* generate op code */
1438 void gen_code(const char *name, host_ulong offset, host_ulong size,
1439 FILE *outfile, int gen_switch)
1441 int copy_size = 0;
1442 uint8_t *p_start, *p_end;
1443 host_ulong start_offset;
1444 int nb_args, i, n;
1445 uint8_t args_present[MAX_ARGS];
1446 const char *sym_name, *p;
1447 EXE_RELOC *rel;
1449 /* Compute exact size excluding prologue and epilogue instructions.
1450 * Increment start_offset to skip epilogue instructions, then compute
1451 * copy_size the indicate the size of the remaining instructions (in
1452 * bytes).
1454 p_start = text + offset;
1455 p_end = p_start + size;
1456 start_offset = offset;
1457 #if defined(HOST_I386) || defined(HOST_X86_64)
1458 #ifdef CONFIG_FORMAT_COFF
1460 uint8_t *p;
1461 p = p_end - 1;
1462 if (p == p_start)
1463 error("empty code for %s", name);
1464 while (*p != 0xc3) {
1465 p--;
1466 if (p <= p_start)
1467 error("ret or jmp expected at the end of %s", name);
1469 copy_size = p - p_start;
1471 #else
1473 int len;
1474 len = p_end - p_start;
1475 if (len == 0)
1476 error("empty code for %s", name);
1477 if (p_end[-1] == 0xc3) {
1478 len--;
1479 } else {
1480 error("ret or jmp expected at the end of %s", name);
1482 copy_size = len;
1484 #endif
1485 #elif defined(HOST_PPC)
1487 uint8_t *p;
1488 p = (void *)(p_end - 4);
1489 if (p == p_start)
1490 error("empty code for %s", name);
1491 if (get32((uint32_t *)p) != 0x4e800020)
1492 error("blr expected at the end of %s", name);
1493 copy_size = p - p_start;
1495 #elif defined(HOST_S390)
1497 uint8_t *p;
1498 p = (void *)(p_end - 2);
1499 if (p == p_start)
1500 error("empty code for %s", name);
1501 if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1502 error("br expected at the end of %s", name);
1503 copy_size = p - p_start;
1505 #elif defined(HOST_ALPHA)
1507 uint8_t *p;
1508 p = p_end - 4;
1509 #if 0
1510 /* XXX: check why it occurs */
1511 if (p == p_start)
1512 error("empty code for %s", name);
1513 #endif
1514 if (get32((uint32_t *)p) != 0x6bfa8001)
1515 error("ret expected at the end of %s", name);
1516 copy_size = p - p_start;
1518 #elif defined(HOST_IA64)
1520 uint8_t *p;
1521 p = (void *)(p_end - 4);
1522 if (p == p_start)
1523 error("empty code for %s", name);
1524 /* br.ret.sptk.many b0;; */
1525 /* 08 00 84 00 */
1526 if (get32((uint32_t *)p) != 0x00840008)
1527 error("br.ret.sptk.many b0;; expected at the end of %s", name);
1528 copy_size = p_end - p_start;
1530 #elif defined(HOST_SPARC)
1532 #define INSN_SAVE 0x9de3a000
1533 #define INSN_RET 0x81c7e008
1534 #define INSN_RETL 0x81c3e008
1535 #define INSN_RESTORE 0x81e80000
1536 #define INSN_RETURN 0x81cfe008
1537 #define INSN_NOP 0x01000000
1538 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1539 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1541 uint32_t start_insn, end_insn1, end_insn2;
1542 uint8_t *p;
1543 p = (void *)(p_end - 8);
1544 if (p <= p_start)
1545 error("empty code for %s", name);
1546 start_insn = get32((uint32_t *)(p_start + 0x0));
1547 end_insn1 = get32((uint32_t *)(p + 0x0));
1548 end_insn2 = get32((uint32_t *)(p + 0x4));
1549 if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1550 (start_insn & ~0x1fff) == INSN_ADD_SP) {
1551 p_start += 0x4;
1552 start_offset += 0x4;
1553 if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1554 /* SPARC v7: ret; restore; */ ;
1555 else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1556 /* SPARC v9: return; nop; */ ;
1557 else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1558 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1559 else
1561 error("ret; restore; not found at end of %s", name);
1562 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1564 } else {
1565 error("No save at the beginning of %s", name);
1567 #if 0
1568 /* Skip a preceeding nop, if present. */
1569 if (p > p_start) {
1570 skip_insn = get32((uint32_t *)(p - 0x4));
1571 if (skip_insn == INSN_NOP)
1572 p -= 4;
1574 #endif
1575 copy_size = p - p_start;
1577 #elif defined(HOST_SPARC64)
1579 #define INSN_SAVE 0x9de3a000
1580 #define INSN_RET 0x81c7e008
1581 #define INSN_RETL 0x81c3e008
1582 #define INSN_RESTORE 0x81e80000
1583 #define INSN_RETURN 0x81cfe008
1584 #define INSN_NOP 0x01000000
1585 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1586 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1588 uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1589 uint8_t *p;
1590 p = (void *)(p_end - 8);
1591 #if 0
1592 /* XXX: check why it occurs */
1593 if (p <= p_start)
1594 error("empty code for %s", name);
1595 #endif
1596 start_insn = get32((uint32_t *)(p_start + 0x0));
1597 end_insn1 = get32((uint32_t *)(p + 0x0));
1598 end_insn2 = get32((uint32_t *)(p + 0x4));
1599 if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1600 (start_insn & ~0x1fff) == INSN_ADD_SP) {
1601 p_start += 0x4;
1602 start_offset += 0x4;
1603 if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1604 /* SPARC v7: ret; restore; */ ;
1605 else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1606 /* SPARC v9: return; nop; */ ;
1607 else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1608 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1609 else
1611 error("ret; restore; not found at end of %s", name);
1612 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1614 } else {
1615 error("No save at the beginning of %s", name);
1618 /* Skip a preceeding nop, if present. */
1619 if (p > p_start) {
1620 skip_insn = get32((uint32_t *)(p - 0x4));
1621 if (skip_insn == 0x01000000)
1622 p -= 4;
1625 copy_size = p - p_start;
1627 #elif defined(HOST_ARM)
1629 uint32_t insn;
1631 if ((p_end - p_start) <= 16)
1632 error("%s: function too small", name);
1633 if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1634 (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1635 get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1636 error("%s: invalid prolog", name);
1637 p_start += 12;
1638 start_offset += 12;
1639 insn = get32((uint32_t *)p_start);
1640 if ((insn & 0xffffff00) == 0xe24dd000) {
1641 /* Stack adjustment. Assume op uses the frame pointer. */
1642 p_start -= 4;
1643 start_offset -= 4;
1645 copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1646 relocs, nb_relocs);
1648 #elif defined(HOST_M68K)
1650 uint8_t *p;
1651 p = (void *)(p_end - 2);
1652 if (p == p_start)
1653 error("empty code for %s", name);
1654 // remove NOP's, probably added for alignment
1655 while ((get16((uint16_t *)p) == 0x4e71) &&
1656 (p>p_start))
1657 p -= 2;
1658 if (get16((uint16_t *)p) != 0x4e75)
1659 error("rts expected at the end of %s", name);
1660 copy_size = p - p_start;
1662 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1664 #define INSN_RETURN 0x03e00008
1665 #define INSN_NOP 0x00000000
1667 uint8_t *p = p_end;
1669 if (p < (p_start + 0x8)) {
1670 error("empty code for %s", name);
1671 } else {
1672 uint32_t end_insn1, end_insn2;
1674 p -= 0x8;
1675 end_insn1 = get32((uint32_t *)(p + 0x0));
1676 end_insn2 = get32((uint32_t *)(p + 0x4));
1677 if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1678 error("jr ra not found at end of %s", name);
1680 copy_size = p - p_start;
1682 #else
1683 #error unsupported CPU
1684 #endif
1686 /* compute the number of arguments by looking at the relocations */
1687 for(i = 0;i < MAX_ARGS; i++)
1688 args_present[i] = 0;
1690 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1691 host_ulong offset = get_rel_offset(rel);
1692 if (offset >= start_offset &&
1693 offset < start_offset + (p_end - p_start)) {
1694 sym_name = get_rel_sym_name(rel);
1695 if(!sym_name)
1696 continue;
1697 if (strstart(sym_name, "__op_param", &p) ||
1698 strstart(sym_name, "__op_gen_label", &p)) {
1699 n = strtoul(p, NULL, 10);
1700 if (n > MAX_ARGS)
1701 error("too many arguments in %s", name);
1702 args_present[n - 1] = 1;
1707 nb_args = 0;
1708 while (nb_args < MAX_ARGS && args_present[nb_args])
1709 nb_args++;
1710 for(i = nb_args; i < MAX_ARGS; i++) {
1711 if (args_present[i])
1712 error("inconsistent argument numbering in %s", name);
1715 if (gen_switch == 2) {
1716 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1717 } else if (gen_switch == 1) {
1719 /* output C code */
1720 fprintf(outfile, "case INDEX_%s: {\n", name);
1721 if (nb_args > 0) {
1722 fprintf(outfile, " long ");
1723 for(i = 0; i < nb_args; i++) {
1724 if (i != 0)
1725 fprintf(outfile, ", ");
1726 fprintf(outfile, "param%d", i + 1);
1728 fprintf(outfile, ";\n");
1730 #if defined(HOST_IA64)
1731 fprintf(outfile, " extern char %s;\n", name);
1732 #else
1733 fprintf(outfile, " extern void %s();\n", name);
1734 #endif
1736 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1737 host_ulong offset = get_rel_offset(rel);
1738 if (offset >= start_offset &&
1739 offset < start_offset + (p_end - p_start)) {
1740 sym_name = get_rel_sym_name(rel);
1741 if(!sym_name)
1742 continue;
1743 if (*sym_name &&
1744 !strstart(sym_name, "__op_param", NULL) &&
1745 !strstart(sym_name, "__op_jmp", NULL) &&
1746 !strstart(sym_name, "__op_gen_label", NULL)) {
1747 #if defined(HOST_SPARC)
1748 if (sym_name[0] == '.') {
1749 fprintf(outfile,
1750 "extern char __dot_%s __asm__(\"%s\");\n",
1751 sym_name+1, sym_name);
1752 continue;
1754 #endif
1755 #if defined(__APPLE__)
1756 /* Set __attribute((unused)) on darwin because we
1757 want to avoid warning when we don't use the symbol. */
1758 fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name);
1759 #elif defined(HOST_IA64)
1760 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1762 * PCREL21 br.call targets generally
1763 * are out of range and need to go
1764 * through an "import stub".
1766 fprintf(outfile, " extern char %s;\n",
1767 sym_name);
1768 #else
1769 fprintf(outfile, "extern char %s;\n", sym_name);
1770 #endif
1775 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1776 name, (int)(start_offset - offset), copy_size);
1778 /* emit code offset information */
1780 EXE_SYM *sym;
1781 const char *sym_name, *p;
1782 host_ulong val;
1783 int n;
1785 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1786 sym_name = get_sym_name(sym);
1787 if (strstart(sym_name, "__op_label", &p)) {
1788 uint8_t *ptr;
1789 unsigned long offset;
1791 /* test if the variable refers to a label inside
1792 the code we are generating */
1793 #ifdef CONFIG_FORMAT_COFF
1794 if (sym->st_shndx == text_shndx) {
1795 ptr = sdata[coff_text_shndx];
1796 } else if (sym->st_shndx == data_shndx) {
1797 ptr = sdata[coff_data_shndx];
1798 } else {
1799 ptr = NULL;
1801 #elif defined(CONFIG_FORMAT_MACH)
1802 if(!sym->n_sect)
1803 continue;
1804 ptr = sdata[sym->n_sect-1];
1805 #else
1806 ptr = sdata[sym->st_shndx];
1807 #endif
1808 if (!ptr)
1809 error("__op_labelN in invalid section");
1810 offset = sym->st_value;
1811 #ifdef CONFIG_FORMAT_MACH
1812 offset -= section_hdr[sym->n_sect-1].addr;
1813 #endif
1814 val = *(host_ulong *)(ptr + offset);
1815 #ifdef ELF_USES_RELOCA
1817 int reloc_shndx, nb_relocs1, j;
1819 /* try to find a matching relocation */
1820 reloc_shndx = find_reloc(sym->st_shndx);
1821 if (reloc_shndx) {
1822 nb_relocs1 = shdr[reloc_shndx].sh_size /
1823 shdr[reloc_shndx].sh_entsize;
1824 rel = (ELF_RELOC *)sdata[reloc_shndx];
1825 for(j = 0; j < nb_relocs1; j++) {
1826 if (rel->r_offset == offset) {
1827 val = rel->r_addend;
1828 break;
1830 rel++;
1834 #endif
1835 if (val >= start_offset && val <= start_offset + copy_size) {
1836 n = strtol(p, NULL, 10);
1837 fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1843 /* load parameters in variables */
1844 for(i = 0; i < nb_args; i++) {
1845 fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
1848 /* patch relocations */
1849 #if defined(HOST_I386)
1851 char relname[256];
1852 int type, is_label;
1853 int addend;
1854 int reloc_offset;
1855 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1856 if (rel->r_offset >= start_offset &&
1857 rel->r_offset < start_offset + copy_size) {
1858 sym_name = get_rel_sym_name(rel);
1859 if (!sym_name)
1860 continue;
1861 reloc_offset = rel->r_offset - start_offset;
1862 if (strstart(sym_name, "__op_jmp", &p)) {
1863 int n;
1864 n = strtol(p, NULL, 10);
1865 /* __op_jmp relocations are done at
1866 runtime to do translated block
1867 chaining: the offset of the instruction
1868 needs to be stored */
1869 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1870 n, reloc_offset);
1871 continue;
1874 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1875 addend = get32((uint32_t *)(text + rel->r_offset));
1876 #ifdef CONFIG_FORMAT_ELF
1877 type = ELF32_R_TYPE(rel->r_info);
1878 if (is_label) {
1879 switch(type) {
1880 case R_386_32:
1881 case R_386_PC32:
1882 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1883 reloc_offset, type, relname, addend);
1884 break;
1885 default:
1886 error("unsupported i386 relocation (%d)", type);
1888 } else {
1889 switch(type) {
1890 case R_386_32:
1891 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1892 reloc_offset, relname, addend);
1893 break;
1894 case R_386_PC32:
1895 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1896 reloc_offset, relname, reloc_offset, addend);
1897 break;
1898 default:
1899 error("unsupported i386 relocation (%d)", type);
1902 #elif defined(CONFIG_FORMAT_COFF)
1904 char *temp_name;
1905 int j;
1906 EXE_SYM *sym;
1907 temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1908 if (!strcmp(temp_name, ".data")) {
1909 for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1910 if (strstart(sym->st_name, sym_name, NULL)) {
1911 addend -= sym->st_value;
1916 type = rel->r_type;
1917 if (is_label) {
1918 /* TCG uses elf relocation constants */
1919 #define R_386_32 1
1920 #define R_386_PC32 2
1921 switch(type) {
1922 case DIR32:
1923 type = R_386_32;
1924 goto do_reloc;
1925 case DISP32:
1926 type = R_386_PC32;
1927 addend -= 4;
1928 do_reloc:
1929 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1930 reloc_offset, type, relname, addend);
1931 break;
1932 default:
1933 error("unsupported i386 relocation (%d)", type);
1935 } else {
1936 switch(type) {
1937 case DIR32:
1938 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1939 reloc_offset, relname, addend);
1940 break;
1941 case DISP32:
1942 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1943 reloc_offset, relname, reloc_offset, addend);
1944 break;
1945 default:
1946 error("unsupported i386 relocation (%d)", type);
1949 #else
1950 #error unsupport object format
1951 #endif
1955 #elif defined(HOST_X86_64)
1957 char relname[256];
1958 int type, is_label;
1959 int addend;
1960 int reloc_offset;
1961 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1962 if (rel->r_offset >= start_offset &&
1963 rel->r_offset < start_offset + copy_size) {
1964 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1965 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1966 type = ELF32_R_TYPE(rel->r_info);
1967 addend = rel->r_addend;
1968 reloc_offset = rel->r_offset - start_offset;
1969 if (is_label) {
1970 switch(type) {
1971 case R_X86_64_32:
1972 case R_X86_64_32S:
1973 case R_X86_64_PC32:
1974 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1975 reloc_offset, type, relname, addend);
1976 break;
1977 default:
1978 error("unsupported X86_64 relocation (%d)", type);
1980 } else {
1981 switch(type) {
1982 case R_X86_64_32:
1983 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1984 reloc_offset, relname, addend);
1985 break;
1986 case R_X86_64_32S:
1987 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1988 reloc_offset, relname, addend);
1989 break;
1990 case R_X86_64_PC32:
1991 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1992 reloc_offset, relname, reloc_offset, addend);
1993 break;
1994 default:
1995 error("unsupported X86_64 relocation (%d)", type);
2001 #elif defined(HOST_PPC)
2003 #ifdef CONFIG_FORMAT_ELF
2004 char relname[256];
2005 int type;
2006 int addend;
2007 int reloc_offset;
2008 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2009 if (rel->r_offset >= start_offset &&
2010 rel->r_offset < start_offset + copy_size) {
2011 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2012 reloc_offset = rel->r_offset - start_offset;
2013 if (strstart(sym_name, "__op_jmp", &p)) {
2014 int n;
2015 n = strtol(p, NULL, 10);
2016 /* __op_jmp relocations are done at
2017 runtime to do translated block
2018 chaining: the offset of the instruction
2019 needs to be stored */
2020 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2021 n, reloc_offset);
2022 continue;
2025 get_reloc_expr(relname, sizeof(relname), sym_name);
2026 type = ELF32_R_TYPE(rel->r_info);
2027 addend = rel->r_addend;
2028 switch(type) {
2029 case R_PPC_ADDR32:
2030 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2031 reloc_offset, relname, addend);
2032 break;
2033 case R_PPC_ADDR16_LO:
2034 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2035 reloc_offset, relname, addend);
2036 break;
2037 case R_PPC_ADDR16_HI:
2038 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2039 reloc_offset, relname, addend);
2040 break;
2041 case R_PPC_ADDR16_HA:
2042 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2043 reloc_offset, relname, addend);
2044 break;
2045 case R_PPC_REL24:
2046 /* warning: must be at 32 MB distancy */
2047 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2048 reloc_offset, reloc_offset, relname, reloc_offset, addend);
2049 break;
2050 default:
2051 error("unsupported powerpc relocation (%d)", type);
2055 #elif defined(CONFIG_FORMAT_MACH)
2056 struct scattered_relocation_info *scarel;
2057 struct relocation_info * rel;
2058 char final_sym_name[256];
2059 const char *sym_name;
2060 const char *p;
2061 int slide, sslide;
2062 int i;
2064 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2065 unsigned int offset, length, value = 0;
2066 unsigned int type, pcrel, isym = 0;
2067 unsigned int usesym = 0;
2069 if(R_SCATTERED & rel->r_address) {
2070 scarel = (struct scattered_relocation_info*)rel;
2071 offset = (unsigned int)scarel->r_address;
2072 length = scarel->r_length;
2073 pcrel = scarel->r_pcrel;
2074 type = scarel->r_type;
2075 value = scarel->r_value;
2076 } else {
2077 value = isym = rel->r_symbolnum;
2078 usesym = (rel->r_extern);
2079 offset = rel->r_address;
2080 length = rel->r_length;
2081 pcrel = rel->r_pcrel;
2082 type = rel->r_type;
2085 slide = offset - start_offset;
2087 if (!(offset >= start_offset && offset < start_offset + size))
2088 continue; /* not in our range */
2090 sym_name = get_reloc_name(rel, &sslide);
2092 if(usesym && symtab[isym].n_type & N_STAB)
2093 continue; /* don't handle STAB (debug sym) */
2095 if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2096 int n;
2097 n = strtol(p, NULL, 10);
2098 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2099 n, slide);
2100 continue; /* Nothing more to do */
2103 if(!sym_name) {
2104 fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2105 name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2106 continue; /* dunno how to handle without final_sym_name */
2109 get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2110 sym_name);
2111 switch(type) {
2112 case PPC_RELOC_BR24:
2113 if (!strstart(sym_name,"__op_gen_label",&p)) {
2114 fprintf(outfile, "{\n");
2115 fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2116 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",
2117 slide, slide, name, sslide);
2118 fprintf(outfile, "}\n");
2119 } else {
2120 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2121 slide, slide, final_sym_name, slide);
2123 break;
2124 case PPC_RELOC_HI16:
2125 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2126 slide, final_sym_name, sslide);
2127 break;
2128 case PPC_RELOC_LO16:
2129 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2130 slide, final_sym_name, sslide);
2131 break;
2132 case PPC_RELOC_HA16:
2133 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2134 slide, final_sym_name, sslide);
2135 break;
2136 default:
2137 error("unsupported powerpc relocation (%d)", type);
2140 #else
2141 #error unsupport object format
2142 #endif
2144 #elif defined(HOST_S390)
2146 char relname[256];
2147 int type;
2148 int addend;
2149 int reloc_offset;
2150 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2151 if (rel->r_offset >= start_offset &&
2152 rel->r_offset < start_offset + copy_size) {
2153 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2154 get_reloc_expr(relname, sizeof(relname), sym_name);
2155 type = ELF32_R_TYPE(rel->r_info);
2156 addend = rel->r_addend;
2157 reloc_offset = rel->r_offset - start_offset;
2158 switch(type) {
2159 case R_390_32:
2160 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2161 reloc_offset, relname, addend);
2162 break;
2163 case R_390_16:
2164 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2165 reloc_offset, relname, addend);
2166 break;
2167 case R_390_8:
2168 fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2169 reloc_offset, relname, addend);
2170 break;
2171 case R_390_PC32DBL:
2172 if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2173 fprintf(outfile,
2174 " *(uint32_t *)(gen_code_ptr + %d) += "
2175 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2176 reloc_offset, name);
2178 else
2179 fprintf(outfile,
2180 " *(uint32_t *)(gen_code_ptr + %d) = "
2181 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2182 reloc_offset, relname, addend, reloc_offset);
2183 break;
2184 default:
2185 error("unsupported s390 relocation (%d)", type);
2190 #elif defined(HOST_ALPHA)
2192 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2193 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2194 int type;
2195 long reloc_offset;
2197 type = ELF64_R_TYPE(rel->r_info);
2198 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2199 reloc_offset = rel->r_offset - start_offset;
2200 switch (type) {
2201 case R_ALPHA_GPDISP:
2202 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2203 as an immediate instead of constructing it from the pv or ra. */
2204 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2205 reloc_offset);
2206 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2207 reloc_offset + (int)rel->r_addend);
2208 break;
2209 case R_ALPHA_LITUSE:
2210 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2211 now, since some called functions (libc) need pv to be set up. */
2212 break;
2213 case R_ALPHA_HINT:
2214 /* Branch target prediction hint. Ignore for now. Should be already
2215 correct for in-function jumps. */
2216 break;
2217 case R_ALPHA_LITERAL:
2218 /* Load a literal from the GOT relative to the gp. Since there's only a
2219 single gp, nothing is to be done. */
2220 break;
2221 case R_ALPHA_GPRELHIGH:
2222 /* Handle fake relocations against __op_param symbol. Need to emit the
2223 high part of the immediate value instead. Other symbols need no
2224 special treatment. */
2225 if (strstart(sym_name, "__op_param", &p))
2226 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2227 reloc_offset, p);
2228 break;
2229 case R_ALPHA_GPRELLOW:
2230 if (strstart(sym_name, "__op_param", &p))
2231 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2232 reloc_offset, p);
2233 break;
2234 case R_ALPHA_BRSGP:
2235 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2236 set up the gp from the pv. */
2237 fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2238 reloc_offset, sym_name, reloc_offset);
2239 break;
2240 default:
2241 error("unsupported Alpha relocation (%d)", type);
2246 #elif defined(HOST_IA64)
2248 unsigned long sym_idx;
2249 long code_offset;
2250 char relname[256];
2251 int type;
2252 long addend;
2254 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2255 sym_idx = ELF64_R_SYM(rel->r_info);
2256 if (rel->r_offset < start_offset
2257 || rel->r_offset >= start_offset + copy_size)
2258 continue;
2259 sym_name = (strtab + symtab[sym_idx].st_name);
2260 code_offset = rel->r_offset - start_offset;
2261 if (strstart(sym_name, "__op_jmp", &p)) {
2262 int n;
2263 n = strtol(p, NULL, 10);
2264 /* __op_jmp relocations are done at
2265 runtime to do translated block
2266 chaining: the offset of the instruction
2267 needs to be stored */
2268 fprintf(outfile, " jmp_offsets[%d] ="
2269 "%ld + (gen_code_ptr - gen_code_buf);\n",
2270 n, code_offset);
2271 continue;
2273 get_reloc_expr(relname, sizeof(relname), sym_name);
2274 type = ELF64_R_TYPE(rel->r_info);
2275 addend = rel->r_addend;
2276 switch(type) {
2277 case R_IA64_IMM64:
2278 fprintf(outfile,
2279 " ia64_imm64(gen_code_ptr + %ld, "
2280 "%s + %ld);\n",
2281 code_offset, relname, addend);
2282 break;
2283 case R_IA64_LTOFF22X:
2284 case R_IA64_LTOFF22:
2285 fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
2286 " %s + %ld, %d);\n",
2287 code_offset, relname, addend,
2288 (type == R_IA64_LTOFF22X));
2289 break;
2290 case R_IA64_LDXMOV:
2291 fprintf(outfile,
2292 " ia64_ldxmov(gen_code_ptr + %ld,"
2293 " %s + %ld);\n", code_offset, relname, addend);
2294 break;
2296 case R_IA64_PCREL21B:
2297 if (strstart(sym_name, "__op_gen_label", NULL)) {
2298 fprintf(outfile,
2299 " ia64_imm21b(gen_code_ptr + %ld,"
2300 " (long) (%s + %ld -\n\t\t"
2301 "((long) gen_code_ptr + %ld)) >> 4);\n",
2302 code_offset, relname, addend,
2303 code_offset & ~0xfUL);
2304 } else {
2305 fprintf(outfile,
2306 " IA64_PLT(gen_code_ptr + %ld, "
2307 "%d);\t/* %s + %ld */\n",
2308 code_offset,
2309 get_plt_index(sym_name, addend),
2310 sym_name, addend);
2312 break;
2313 default:
2314 error("unsupported ia64 relocation (0x%x)",
2315 type);
2318 fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2319 copy_size - 16 + 2);
2321 #elif defined(HOST_SPARC)
2323 char relname[256];
2324 int type;
2325 int addend;
2326 int reloc_offset;
2327 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2328 if (rel->r_offset >= start_offset &&
2329 rel->r_offset < start_offset + copy_size) {
2330 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2331 get_reloc_expr(relname, sizeof(relname), sym_name);
2332 type = ELF32_R_TYPE(rel->r_info);
2333 addend = rel->r_addend;
2334 reloc_offset = rel->r_offset - start_offset;
2335 switch(type) {
2336 case R_SPARC_32:
2337 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2338 reloc_offset, relname, addend);
2339 break;
2340 case R_SPARC_HI22:
2341 fprintf(outfile,
2342 " *(uint32_t *)(gen_code_ptr + %d) = "
2343 "((*(uint32_t *)(gen_code_ptr + %d)) "
2344 " & ~0x3fffff) "
2345 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2346 reloc_offset, reloc_offset, relname, addend);
2347 break;
2348 case R_SPARC_LO10:
2349 fprintf(outfile,
2350 " *(uint32_t *)(gen_code_ptr + %d) = "
2351 "((*(uint32_t *)(gen_code_ptr + %d)) "
2352 " & ~0x3ff) "
2353 " | ((%s + %d) & 0x3ff);\n",
2354 reloc_offset, reloc_offset, relname, addend);
2355 break;
2356 case R_SPARC_WDISP30:
2357 fprintf(outfile,
2358 " *(uint32_t *)(gen_code_ptr + %d) = "
2359 "((*(uint32_t *)(gen_code_ptr + %d)) "
2360 " & ~0x3fffffff) "
2361 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2362 " & 0x3fffffff);\n",
2363 reloc_offset, reloc_offset, relname, addend,
2364 reloc_offset);
2365 break;
2366 case R_SPARC_WDISP22:
2367 fprintf(outfile,
2368 " *(uint32_t *)(gen_code_ptr + %d) = "
2369 "((*(uint32_t *)(gen_code_ptr + %d)) "
2370 " & ~0x3fffff) "
2371 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2372 " & 0x3fffff);\n",
2373 rel->r_offset - start_offset,
2374 rel->r_offset - start_offset,
2375 relname, addend,
2376 rel->r_offset - start_offset);
2377 break;
2378 default:
2379 error("unsupported sparc relocation (%d)", type);
2384 #elif defined(HOST_SPARC64)
2386 char relname[256];
2387 int type;
2388 int addend;
2389 int reloc_offset;
2390 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2391 if (rel->r_offset >= start_offset &&
2392 rel->r_offset < start_offset + copy_size) {
2393 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2394 get_reloc_expr(relname, sizeof(relname), sym_name);
2395 type = ELF32_R_TYPE(rel->r_info);
2396 addend = rel->r_addend;
2397 reloc_offset = rel->r_offset - start_offset;
2398 switch(type) {
2399 case R_SPARC_32:
2400 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2401 reloc_offset, relname, addend);
2402 break;
2403 case R_SPARC_HI22:
2404 fprintf(outfile,
2405 " *(uint32_t *)(gen_code_ptr + %d) = "
2406 "((*(uint32_t *)(gen_code_ptr + %d)) "
2407 " & ~0x3fffff) "
2408 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2409 reloc_offset, reloc_offset, relname, addend);
2410 break;
2411 case R_SPARC_LO10:
2412 fprintf(outfile,
2413 " *(uint32_t *)(gen_code_ptr + %d) = "
2414 "((*(uint32_t *)(gen_code_ptr + %d)) "
2415 " & ~0x3ff) "
2416 " | ((%s + %d) & 0x3ff);\n",
2417 reloc_offset, reloc_offset, relname, addend);
2418 break;
2419 case R_SPARC_OLO10:
2420 addend += ELF64_R_TYPE_DATA (rel->r_info);
2421 fprintf(outfile,
2422 " *(uint32_t *)(gen_code_ptr + %d) = "
2423 "((*(uint32_t *)(gen_code_ptr + %d)) "
2424 " & ~0x3ff) "
2425 " | ((%s + %d) & 0x3ff);\n",
2426 reloc_offset, reloc_offset, relname, addend);
2427 break;
2428 case R_SPARC_WDISP30:
2429 fprintf(outfile,
2430 " *(uint32_t *)(gen_code_ptr + %d) = "
2431 "((*(uint32_t *)(gen_code_ptr + %d)) "
2432 " & ~0x3fffffff) "
2433 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2434 " & 0x3fffffff);\n",
2435 reloc_offset, reloc_offset, relname, addend,
2436 reloc_offset);
2437 break;
2438 case R_SPARC_WDISP22:
2439 fprintf(outfile,
2440 " *(uint32_t *)(gen_code_ptr + %d) = "
2441 "((*(uint32_t *)(gen_code_ptr + %d)) "
2442 " & ~0x3fffff) "
2443 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2444 " & 0x3fffff);\n",
2445 reloc_offset, reloc_offset, relname, addend,
2446 reloc_offset);
2447 break;
2448 case R_SPARC_HH22:
2449 fprintf(outfile,
2450 " *(uint32_t *)(gen_code_ptr + %d) = "
2451 "((*(uint32_t *)(gen_code_ptr + %d)) "
2452 " & ~0x00000000) "
2453 " | (((%s + %d) >> 42) & 0x00000000);\n",
2454 reloc_offset, reloc_offset, relname, addend);
2455 break;
2457 case R_SPARC_LM22:
2458 fprintf(outfile,
2459 " *(uint32_t *)(gen_code_ptr + %d) = "
2460 "((*(uint32_t *)(gen_code_ptr + %d)) "
2461 " & ~0x00000000) "
2462 " | (((%s + %d) >> 10) & 0x00000000);\n",
2463 reloc_offset, reloc_offset, relname, addend);
2464 break;
2466 case R_SPARC_HM10:
2467 fprintf(outfile,
2468 " *(uint32_t *)(gen_code_ptr + %d) = "
2469 "((*(uint32_t *)(gen_code_ptr + %d)) "
2470 " & ~0x00000000) "
2471 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2472 reloc_offset, reloc_offset, relname, addend);
2473 break;
2475 default:
2476 error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2481 #elif defined(HOST_ARM)
2483 char relname[256];
2484 int type;
2485 int addend;
2486 int reloc_offset;
2487 uint32_t insn;
2489 insn = get32((uint32_t *)(p_start + 4));
2490 /* If prologue ends in sub sp, sp, #const then assume
2491 op has a stack frame and needs the frame pointer. */
2492 if ((insn & 0xffffff00) == 0xe24dd000) {
2493 int i;
2494 uint32_t opcode;
2495 opcode = 0xe28db000; /* add fp, sp, #0. */
2496 #if 0
2497 /* ??? Need to undo the extra stack adjustment at the end of the op.
2498 For now just leave the stack misaligned and hope it doesn't break anything
2499 too important. */
2500 if ((insn & 4) != 0) {
2501 /* Preserve doubleword stack alignment. */
2502 fprintf(outfile,
2503 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2504 insn + 4);
2505 opcode -= 4;
2507 #endif
2508 insn = get32((uint32_t *)(p_start - 4));
2509 /* Calculate the size of the saved registers,
2510 excluding pc. */
2511 for (i = 0; i < 15; i++) {
2512 if (insn & (1 << i))
2513 opcode += 4;
2515 fprintf(outfile,
2516 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2518 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2519 relocs, nb_relocs);
2521 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2522 if (rel->r_offset >= start_offset &&
2523 rel->r_offset < start_offset + copy_size) {
2524 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2525 /* the compiler leave some unnecessary references to the code */
2526 if (sym_name[0] == '\0')
2527 continue;
2528 get_reloc_expr(relname, sizeof(relname), sym_name);
2529 type = ELF32_R_TYPE(rel->r_info);
2530 addend = get32((uint32_t *)(text + rel->r_offset));
2531 reloc_offset = rel->r_offset - start_offset;
2532 switch(type) {
2533 case R_ARM_ABS32:
2534 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2535 reloc_offset, relname, addend);
2536 break;
2537 case R_ARM_PC24:
2538 case R_ARM_JUMP24:
2539 case R_ARM_CALL:
2540 fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2541 reloc_offset, addend, relname);
2542 break;
2543 default:
2544 error("unsupported arm relocation (%d)", type);
2549 #elif defined(HOST_M68K)
2551 char relname[256];
2552 int type;
2553 int addend;
2554 int reloc_offset;
2555 Elf32_Sym *sym;
2556 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2557 if (rel->r_offset >= start_offset &&
2558 rel->r_offset < start_offset + copy_size) {
2559 sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2560 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2561 get_reloc_expr(relname, sizeof(relname), sym_name);
2562 type = ELF32_R_TYPE(rel->r_info);
2563 addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2564 reloc_offset = rel->r_offset - start_offset;
2565 switch(type) {
2566 case R_68K_32:
2567 fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2568 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2569 reloc_offset, relname, addend );
2570 break;
2571 case R_68K_PC32:
2572 fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2573 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2574 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2575 break;
2576 default:
2577 error("unsupported m68k relocation (%d)", type);
2582 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2584 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2585 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2586 char relname[256];
2587 int type;
2588 int addend;
2589 int reloc_offset;
2591 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2592 /* the compiler leave some unnecessary references to the code */
2593 if (sym_name[0] == '\0')
2594 continue;
2595 get_reloc_expr(relname, sizeof(relname), sym_name);
2596 type = ELF32_R_TYPE(rel->r_info);
2597 addend = get32((uint32_t *)(text + rel->r_offset));
2598 reloc_offset = rel->r_offset - start_offset;
2599 switch (type) {
2600 case R_MIPS_26:
2601 fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2602 rel->r_offset, sym_name);
2603 fprintf(outfile,
2604 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2605 "(0x%x & ~0x3fffff) "
2606 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2607 " & 0x3fffff);\n",
2608 reloc_offset, addend, addend, relname, reloc_offset);
2609 break;
2610 case R_MIPS_HI16:
2611 fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2612 rel->r_offset, sym_name);
2613 fprintf(outfile,
2614 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2615 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2616 " & ~0xffff) "
2617 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2618 reloc_offset, reloc_offset, relname);
2619 break;
2620 case R_MIPS_LO16:
2621 fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2622 rel->r_offset, sym_name);
2623 fprintf(outfile,
2624 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2625 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2626 " & ~0xffff) "
2627 " | (%s & 0xffff);\n",
2628 reloc_offset, reloc_offset, relname);
2629 break;
2630 case R_MIPS_PC16:
2631 fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2632 rel->r_offset, sym_name);
2633 fprintf(outfile,
2634 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2635 "(0x%x & ~0xffff) "
2636 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2637 " & 0xffff);\n",
2638 reloc_offset, addend, addend, relname, reloc_offset);
2639 break;
2640 case R_MIPS_GOT16:
2641 case R_MIPS_CALL16:
2642 fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2643 rel->r_offset, sym_name);
2644 fprintf(outfile,
2645 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2646 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2647 " & ~0xffff) "
2648 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2649 reloc_offset, reloc_offset, relname);
2650 break;
2651 default:
2652 error("unsupported MIPS relocation (%d)", type);
2657 #else
2658 #error unsupported CPU
2659 #endif
2660 fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
2661 fprintf(outfile, "}\n");
2662 fprintf(outfile, "break;\n\n");
2663 } else {
2664 fprintf(outfile, "static inline void gen_%s(", name);
2665 if (nb_args == 0) {
2666 fprintf(outfile, "void");
2667 } else {
2668 for(i = 0; i < nb_args; i++) {
2669 if (i != 0)
2670 fprintf(outfile, ", ");
2671 fprintf(outfile, "long param%d", i + 1);
2674 fprintf(outfile, ")\n");
2675 fprintf(outfile, "{\n");
2676 for(i = 0; i < nb_args; i++) {
2677 fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1);
2679 fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2680 fprintf(outfile, "}\n\n");
2684 int gen_file(FILE *outfile, int out_type)
2686 int i;
2687 EXE_SYM *sym;
2689 if (out_type == OUT_INDEX_OP) {
2690 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2691 const char *name;
2692 name = get_sym_name(sym);
2693 if (strstart(name, OP_PREFIX, NULL)) {
2694 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2697 } else if (out_type == OUT_GEN_OP) {
2698 /* generate gen_xxx functions */
2699 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2700 const char *name;
2701 name = get_sym_name(sym);
2702 if (strstart(name, OP_PREFIX, NULL)) {
2703 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2704 if (sym->st_shndx != text_shndx)
2705 error("invalid section for opcode (0x%x)", sym->st_shndx);
2706 #endif
2707 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2711 } else {
2712 /* generate big code generation switch */
2714 #ifdef HOST_ARM
2715 #error broken
2716 /* We need to know the size of all the ops so we can figure out when
2717 to emit constant pools. This must be consistent with opc.h. */
2718 fprintf(outfile,
2719 "static const uint32_t arm_opc_size[] = {\n"
2720 " 0,\n" /* end */
2721 " 0,\n" /* nop */
2722 " 0,\n" /* nop1 */
2723 " 0,\n" /* nop2 */
2724 " 0,\n"); /* nop3 */
2725 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2726 const char *name;
2727 name = get_sym_name(sym);
2728 if (strstart(name, OP_PREFIX, NULL)) {
2729 fprintf(outfile, " %d,\n", sym->st_size);
2732 fprintf(outfile,
2733 "};\n");
2734 #endif
2736 #ifdef HOST_ARM
2737 #error broken
2738 /* Arm is tricky because it uses constant pools for loading immediate values.
2739 We assume (and require) each function is code followed by a constant pool.
2740 All the ops are small so this should be ok. For each op we figure
2741 out how much "spare" range we have in the load instructions. This allows
2742 us to insert subsequent ops in between the op and the constant pool,
2743 eliminating the neeed to jump around the pool.
2745 We currently generate:
2747 [ For this example we assume merging would move op1_pool out of range.
2748 In practice we should be able to combine many ops before the offset
2749 limits are reached. ]
2750 op1_code;
2751 op2_code;
2752 goto op3;
2753 op2_pool;
2754 op1_pool;
2755 op3:
2756 op3_code;
2757 ret;
2758 op3_pool;
2760 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2762 fprintf(outfile,
2763 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2764 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2765 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2766 /* Initialise the parmissible pool offset to an arbitary large value. */
2767 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2768 #endif
2769 #ifdef HOST_IA64
2770 #error broken
2772 long addend, not_first = 0;
2773 unsigned long sym_idx;
2774 int index, max_index;
2775 const char *sym_name;
2776 EXE_RELOC *rel;
2778 max_index = -1;
2779 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2780 sym_idx = ELF64_R_SYM(rel->r_info);
2781 sym_name = (strtab + symtab[sym_idx].st_name);
2782 if (strstart(sym_name, "__op_gen_label", NULL))
2783 continue;
2784 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2785 continue;
2787 addend = rel->r_addend;
2788 index = get_plt_index(sym_name, addend);
2789 if (index <= max_index)
2790 continue;
2791 max_index = index;
2792 fprintf(outfile, " extern void %s(void);\n", sym_name);
2795 fprintf(outfile,
2796 " struct ia64_fixup *plt_fixes = NULL, "
2797 "*ltoff_fixes = NULL;\n"
2798 " static long plt_target[] = {\n\t");
2800 max_index = -1;
2801 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2802 sym_idx = ELF64_R_SYM(rel->r_info);
2803 sym_name = (strtab + symtab[sym_idx].st_name);
2804 if (strstart(sym_name, "__op_gen_label", NULL))
2805 continue;
2806 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2807 continue;
2809 addend = rel->r_addend;
2810 index = get_plt_index(sym_name, addend);
2811 if (index <= max_index)
2812 continue;
2813 max_index = index;
2815 if (not_first)
2816 fprintf(outfile, ",\n\t");
2817 not_first = 1;
2818 if (addend)
2819 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2820 else
2821 fprintf(outfile, "(long) &%s", sym_name);
2823 fprintf(outfile, "\n };\n"
2824 " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2826 #endif
2828 #ifdef HOST_ARM
2829 #error broken
2830 /* Generate constant pool if needed */
2831 fprintf(outfile,
2832 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2833 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2834 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2835 " last_gen_code_ptr = gen_code_ptr;\n"
2836 " arm_ldr_ptr = arm_ldr_table;\n"
2837 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2838 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2839 " }\n");
2840 #endif
2842 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2843 const char *name;
2844 name = get_sym_name(sym);
2845 if (strstart(name, OP_PREFIX, NULL)) {
2846 #if 0
2847 printf("%4d: %s pos=0x%08x len=%d\n",
2848 i, name, sym->st_value, sym->st_size);
2849 #endif
2850 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2851 if (sym->st_shndx != text_shndx)
2852 error("invalid section for opcode (0x%x)", sym->st_shndx);
2853 #endif
2854 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2859 return 0;
2862 void usage(void)
2864 printf("dyngen (c) 2003 Fabrice Bellard\n"
2865 "usage: dyngen [-o outfile] [-c] objfile\n"
2866 "Generate a dynamic code generator from an object file\n"
2867 "-c output enum of operations\n"
2868 "-g output gen_op_xx() functions\n"
2870 exit(1);
2873 int main(int argc, char **argv)
2875 int c, out_type;
2876 const char *filename, *outfilename;
2877 FILE *outfile;
2879 outfilename = "out.c";
2880 out_type = OUT_CODE;
2881 for(;;) {
2882 c = getopt(argc, argv, "ho:cg");
2883 if (c == -1)
2884 break;
2885 switch(c) {
2886 case 'h':
2887 usage();
2888 break;
2889 case 'o':
2890 outfilename = optarg;
2891 break;
2892 case 'c':
2893 out_type = OUT_INDEX_OP;
2894 break;
2895 case 'g':
2896 out_type = OUT_GEN_OP;
2897 break;
2900 if (optind >= argc)
2901 usage();
2902 filename = argv[optind];
2903 outfile = fopen(outfilename, "w");
2904 if (!outfile)
2905 error("could not open '%s'", outfilename);
2907 load_object(filename);
2908 gen_file(outfile, out_type);
2909 fclose(outfile);
2910 return 0;