Don't race while creating a VCPU
[qemu-kvm/fedora.git] / dyngen.c
blobe914403d40fa953fe6f60ba3246ea38ce527e65a
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_HPPA)
122 #define ELF_CLASS ELFCLASS32
123 #define ELF_ARCH EM_PARISC
124 #define elf_check_arch(x) ((x) == EM_PARISC)
125 #define ELF_USES_RELOCA
127 #elif defined(HOST_MIPS)
129 #define ELF_CLASS ELFCLASS32
130 #define ELF_ARCH EM_MIPS
131 #define elf_check_arch(x) ((x) == EM_MIPS)
132 #define ELF_USES_RELOC
134 #elif defined(HOST_MIPS64)
136 /* Assume n32 ABI here, which is ELF32. */
137 #define ELF_CLASS ELFCLASS32
138 #define ELF_ARCH EM_MIPS
139 #define elf_check_arch(x) ((x) == EM_MIPS)
140 #define ELF_USES_RELOCA
142 #else
143 #error unsupported CPU - please update the code
144 #endif
146 #include "elf.h"
148 #if ELF_CLASS == ELFCLASS32
149 typedef int32_t host_long;
150 typedef uint32_t host_ulong;
151 #define swabls(x) swab32s(x)
152 #define swablss(x) swab32ss(x)
153 #else
154 typedef int64_t host_long;
155 typedef uint64_t host_ulong;
156 #define swabls(x) swab64s(x)
157 #define swablss(x) swab64ss(x)
158 #endif
160 #ifdef ELF_USES_RELOCA
161 #define SHT_RELOC SHT_RELA
162 #else
163 #define SHT_RELOC SHT_REL
164 #endif
166 #define EXE_RELOC ELF_RELOC
167 #define EXE_SYM ElfW(Sym)
169 #endif /* CONFIG_FORMAT_ELF */
171 #ifdef CONFIG_FORMAT_COFF
173 typedef int32_t host_long;
174 typedef uint32_t host_ulong;
176 #include "a.out.h"
178 #define FILENAMELEN 256
180 typedef struct coff_sym {
181 struct external_syment *st_syment;
182 char st_name[FILENAMELEN];
183 uint32_t st_value;
184 int st_size;
185 uint8_t st_type;
186 uint8_t st_shndx;
187 } coff_Sym;
189 typedef struct coff_rel {
190 struct external_reloc *r_reloc;
191 int r_offset;
192 uint8_t r_type;
193 } coff_Rel;
195 #define EXE_RELOC struct coff_rel
196 #define EXE_SYM struct coff_sym
198 #endif /* CONFIG_FORMAT_COFF */
200 #ifdef CONFIG_FORMAT_MACH
202 #include <mach-o/loader.h>
203 #include <mach-o/nlist.h>
204 #include <mach-o/reloc.h>
205 #include <mach-o/ppc/reloc.h>
207 # define check_mach_header(x) (x.magic == MH_MAGIC)
208 typedef int32_t host_long;
209 typedef uint32_t host_ulong;
211 struct nlist_extended
213 union {
214 char *n_name;
215 long n_strx;
216 } n_un;
217 unsigned char n_type;
218 unsigned char n_sect;
219 short st_desc;
220 unsigned long st_value;
221 unsigned long st_size;
224 #define EXE_RELOC struct relocation_info
225 #define EXE_SYM struct nlist_extended
227 #endif /* CONFIG_FORMAT_MACH */
229 #include "bswap.h"
231 enum {
232 OUT_GEN_OP,
233 OUT_CODE,
234 OUT_INDEX_OP,
237 /* all dynamically generated functions begin with this code */
238 #define OP_PREFIX "op_"
240 int do_swap;
242 static void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
244 va_list ap;
245 va_start(ap, fmt);
246 fprintf(stderr, "dyngen: ");
247 vfprintf(stderr, fmt, ap);
248 fprintf(stderr, "\n");
249 va_end(ap);
250 exit(1);
253 static void *load_data(int fd, long offset, unsigned int size)
255 char *data;
257 data = malloc(size);
258 if (!data)
259 return NULL;
260 lseek(fd, offset, SEEK_SET);
261 if (read(fd, data, size) != size) {
262 free(data);
263 return NULL;
265 return data;
268 int strstart(const char *str, const char *val, const char **ptr)
270 const char *p, *q;
271 p = str;
272 q = val;
273 while (*q != '\0') {
274 if (*p != *q)
275 return 0;
276 p++;
277 q++;
279 if (ptr)
280 *ptr = p;
281 return 1;
284 void pstrcpy(char *buf, int buf_size, const char *str)
286 int c;
287 char *q = buf;
289 if (buf_size <= 0)
290 return;
292 for(;;) {
293 c = *str++;
294 if (c == 0 || q >= buf + buf_size - 1)
295 break;
296 *q++ = c;
298 *q = '\0';
301 void swab16s(uint16_t *p)
303 *p = bswap16(*p);
306 void swab32s(uint32_t *p)
308 *p = bswap32(*p);
311 void swab32ss(int32_t *p)
313 *p = bswap32(*p);
316 void swab64s(uint64_t *p)
318 *p = bswap64(*p);
321 void swab64ss(int64_t *p)
323 *p = bswap64(*p);
326 uint16_t get16(uint16_t *p)
328 uint16_t val;
329 val = *p;
330 if (do_swap)
331 val = bswap16(val);
332 return val;
335 uint32_t get32(uint32_t *p)
337 uint32_t val;
338 val = *p;
339 if (do_swap)
340 val = bswap32(val);
341 return val;
344 void put16(uint16_t *p, uint16_t val)
346 if (do_swap)
347 val = bswap16(val);
348 *p = val;
351 void put32(uint32_t *p, uint32_t val)
353 if (do_swap)
354 val = bswap32(val);
355 *p = val;
358 /* executable information */
359 EXE_SYM *symtab;
360 int nb_syms;
361 int text_shndx;
362 uint8_t *text;
363 EXE_RELOC *relocs;
364 int nb_relocs;
366 #ifdef CONFIG_FORMAT_ELF
368 /* ELF file info */
369 struct elf_shdr *shdr;
370 uint8_t **sdata;
371 struct elfhdr ehdr;
372 char *strtab;
374 int elf_must_swap(struct elfhdr *h)
376 union {
377 uint32_t i;
378 uint8_t b[4];
379 } swaptest;
381 swaptest.i = 1;
382 return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
383 (swaptest.b[0] == 0);
386 void elf_swap_ehdr(struct elfhdr *h)
388 swab16s(&h->e_type); /* Object file type */
389 swab16s(&h-> e_machine); /* Architecture */
390 swab32s(&h-> e_version); /* Object file version */
391 swabls(&h-> e_entry); /* Entry point virtual address */
392 swabls(&h-> e_phoff); /* Program header table file offset */
393 swabls(&h-> e_shoff); /* Section header table file offset */
394 swab32s(&h-> e_flags); /* Processor-specific flags */
395 swab16s(&h-> e_ehsize); /* ELF header size in bytes */
396 swab16s(&h-> e_phentsize); /* Program header table entry size */
397 swab16s(&h-> e_phnum); /* Program header table entry count */
398 swab16s(&h-> e_shentsize); /* Section header table entry size */
399 swab16s(&h-> e_shnum); /* Section header table entry count */
400 swab16s(&h-> e_shstrndx); /* Section header string table index */
403 void elf_swap_shdr(struct elf_shdr *h)
405 swab32s(&h-> sh_name); /* Section name (string tbl index) */
406 swab32s(&h-> sh_type); /* Section type */
407 swabls(&h-> sh_flags); /* Section flags */
408 swabls(&h-> sh_addr); /* Section virtual addr at execution */
409 swabls(&h-> sh_offset); /* Section file offset */
410 swabls(&h-> sh_size); /* Section size in bytes */
411 swab32s(&h-> sh_link); /* Link to another section */
412 swab32s(&h-> sh_info); /* Additional section information */
413 swabls(&h-> sh_addralign); /* Section alignment */
414 swabls(&h-> sh_entsize); /* Entry size if section holds table */
417 void elf_swap_phdr(struct elf_phdr *h)
419 swab32s(&h->p_type); /* Segment type */
420 swabls(&h->p_offset); /* Segment file offset */
421 swabls(&h->p_vaddr); /* Segment virtual address */
422 swabls(&h->p_paddr); /* Segment physical address */
423 swabls(&h->p_filesz); /* Segment size in file */
424 swabls(&h->p_memsz); /* Segment size in memory */
425 swab32s(&h->p_flags); /* Segment flags */
426 swabls(&h->p_align); /* Segment alignment */
429 void elf_swap_rel(ELF_RELOC *rel)
431 swabls(&rel->r_offset);
432 swabls(&rel->r_info);
433 #ifdef ELF_USES_RELOCA
434 swablss(&rel->r_addend);
435 #endif
438 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
439 const char *name)
441 int i;
442 const char *shname;
443 struct elf_shdr *sec;
445 for(i = 0; i < shnum; i++) {
446 sec = &shdr[i];
447 if (!sec->sh_name)
448 continue;
449 shname = shstr + sec->sh_name;
450 if (!strcmp(shname, name))
451 return sec;
453 return NULL;
456 int find_reloc(int sh_index)
458 struct elf_shdr *sec;
459 int i;
461 for(i = 0; i < ehdr.e_shnum; i++) {
462 sec = &shdr[i];
463 if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
464 return i;
466 return 0;
469 static host_ulong get_rel_offset(EXE_RELOC *rel)
471 return rel->r_offset;
474 static char *get_rel_sym_name(EXE_RELOC *rel)
476 return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
479 static char *get_sym_name(EXE_SYM *sym)
481 return strtab + sym->st_name;
484 /* load an elf object file */
485 int load_object(const char *filename)
487 int fd;
488 struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
489 int i, j;
490 ElfW(Sym) *sym;
491 char *shstr;
492 ELF_RELOC *rel;
494 fd = open(filename, O_RDONLY);
495 if (fd < 0)
496 error("can't open file '%s'", filename);
498 /* Read ELF header. */
499 if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
500 error("unable to read file header");
502 /* Check ELF identification. */
503 if (ehdr.e_ident[EI_MAG0] != ELFMAG0
504 || ehdr.e_ident[EI_MAG1] != ELFMAG1
505 || ehdr.e_ident[EI_MAG2] != ELFMAG2
506 || ehdr.e_ident[EI_MAG3] != ELFMAG3
507 || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
508 error("bad ELF header");
511 do_swap = elf_must_swap(&ehdr);
512 if (do_swap)
513 elf_swap_ehdr(&ehdr);
514 if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
515 error("Unsupported ELF class");
516 if (ehdr.e_type != ET_REL)
517 error("ELF object file expected");
518 if (ehdr.e_version != EV_CURRENT)
519 error("Invalid ELF version");
520 if (!elf_check_arch(ehdr.e_machine))
521 error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
523 /* read section headers */
524 shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
525 if (do_swap) {
526 for(i = 0; i < ehdr.e_shnum; i++) {
527 elf_swap_shdr(&shdr[i]);
531 /* read all section data */
532 sdata = malloc(sizeof(void *) * ehdr.e_shnum);
533 memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
535 for(i = 0;i < ehdr.e_shnum; i++) {
536 sec = &shdr[i];
537 if (sec->sh_type != SHT_NOBITS)
538 sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
541 sec = &shdr[ehdr.e_shstrndx];
542 shstr = (char *)sdata[ehdr.e_shstrndx];
544 /* swap relocations */
545 for(i = 0; i < ehdr.e_shnum; i++) {
546 sec = &shdr[i];
547 if (sec->sh_type == SHT_RELOC) {
548 nb_relocs = sec->sh_size / sec->sh_entsize;
549 if (do_swap) {
550 for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
551 elf_swap_rel(rel);
555 /* text section */
557 text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
558 if (!text_sec)
559 error("could not find .text section");
560 text_shndx = text_sec - shdr;
561 text = sdata[text_shndx];
563 /* find text relocations, if any */
564 relocs = NULL;
565 nb_relocs = 0;
566 i = find_reloc(text_shndx);
567 if (i != 0) {
568 relocs = (ELF_RELOC *)sdata[i];
569 nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
572 symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
573 if (!symtab_sec)
574 error("could not find .symtab section");
575 strtab_sec = &shdr[symtab_sec->sh_link];
577 symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
578 strtab = (char *)sdata[symtab_sec->sh_link];
580 nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
581 if (do_swap) {
582 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
583 swab32s(&sym->st_name);
584 swabls(&sym->st_value);
585 swabls(&sym->st_size);
586 swab16s(&sym->st_shndx);
589 close(fd);
590 return 0;
593 #endif /* CONFIG_FORMAT_ELF */
595 #ifdef CONFIG_FORMAT_COFF
597 /* COFF file info */
598 struct external_scnhdr *shdr;
599 uint8_t **sdata;
600 struct external_filehdr fhdr;
601 struct external_syment *coff_symtab;
602 char *strtab;
603 int coff_text_shndx, coff_data_shndx;
605 int data_shndx;
607 #define STRTAB_SIZE 4
609 #define DIR32 0x06
610 #define DISP32 0x14
612 #define T_FUNCTION 0x20
613 #define C_EXTERNAL 2
615 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
617 char *q;
618 int c, i, len;
620 if (ext_sym->e.e.e_zeroes != 0) {
621 q = sym->st_name;
622 for(i = 0; i < 8; i++) {
623 c = ext_sym->e.e_name[i];
624 if (c == '\0')
625 break;
626 *q++ = c;
628 *q = '\0';
629 } else {
630 pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
633 /* now convert the name to a C name (suppress the leading '_') */
634 if (sym->st_name[0] == '_') {
635 len = strlen(sym->st_name);
636 memmove(sym->st_name, sym->st_name + 1, len - 1);
637 sym->st_name[len - 1] = '\0';
641 char *name_for_dotdata(struct coff_rel *rel)
643 int i;
644 struct coff_sym *sym;
645 uint32_t text_data;
647 text_data = *(uint32_t *)(text + rel->r_offset);
649 for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
650 if (sym->st_syment->e_scnum == data_shndx &&
651 text_data >= sym->st_value &&
652 text_data < sym->st_value + sym->st_size) {
654 return sym->st_name;
658 return NULL;
661 static char *get_sym_name(EXE_SYM *sym)
663 return sym->st_name;
666 static char *get_rel_sym_name(EXE_RELOC *rel)
668 char *name;
669 name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
670 if (!strcmp(name, ".data"))
671 name = name_for_dotdata(rel);
672 if (name[0] == '.')
673 return NULL;
674 return name;
677 static host_ulong get_rel_offset(EXE_RELOC *rel)
679 return rel->r_offset;
682 struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
684 int i;
685 const char *shname;
686 struct external_scnhdr *sec;
688 for(i = 0; i < shnum; i++) {
689 sec = &shdr[i];
690 if (!sec->s_name)
691 continue;
692 shname = sec->s_name;
693 if (!strcmp(shname, name))
694 return sec;
696 return NULL;
699 /* load a coff object file */
700 int load_object(const char *filename)
702 int fd;
703 struct external_scnhdr *sec, *text_sec, *data_sec;
704 int i;
705 struct external_syment *ext_sym;
706 struct external_reloc *coff_relocs;
707 struct external_reloc *ext_rel;
708 uint32_t *n_strtab;
709 EXE_SYM *sym;
710 EXE_RELOC *rel;
711 const char *p;
712 int aux_size, j;
714 fd = open(filename, O_RDONLY
715 #ifdef _WIN32
716 | O_BINARY
717 #endif
719 if (fd < 0)
720 error("can't open file '%s'", filename);
722 /* Read COFF header. */
723 if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
724 error("unable to read file header");
726 /* Check COFF identification. */
727 if (fhdr.f_magic != I386MAGIC) {
728 error("bad COFF header");
730 do_swap = 0;
732 /* read section headers */
733 shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
735 /* read all section data */
736 sdata = malloc(sizeof(void *) * fhdr.f_nscns);
737 memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
739 for(i = 0;i < fhdr.f_nscns; i++) {
740 sec = &shdr[i];
741 if (!strstart(sec->s_name, ".bss", &p))
742 sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
746 /* text section */
747 text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
748 if (!text_sec)
749 error("could not find .text section");
750 coff_text_shndx = text_sec - shdr;
751 text = sdata[coff_text_shndx];
753 /* data section */
754 data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
755 if (!data_sec)
756 error("could not find .data section");
757 coff_data_shndx = data_sec - shdr;
759 coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
760 for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
761 for(i=0;i<8;i++)
762 printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
763 printf("\n");
767 n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
768 strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
770 nb_syms = fhdr.f_nsyms;
772 for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
773 if (strstart(ext_sym->e.e_name, ".text", NULL))
774 text_shndx = ext_sym->e_scnum;
775 if (strstart(ext_sym->e.e_name, ".data", NULL))
776 data_shndx = ext_sym->e_scnum;
779 /* set coff symbol */
780 symtab = malloc(sizeof(struct coff_sym) * nb_syms);
782 for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
783 memset(sym, 0, sizeof(*sym));
784 sym->st_syment = ext_sym;
785 sym_ent_name(ext_sym, sym);
786 sym->st_value = ext_sym->e_value;
788 aux_size = *(int8_t *)ext_sym->e_numaux;
789 if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
790 for (j = aux_size + 1; j < nb_syms - i; j++) {
791 if ((ext_sym + j)->e_scnum == text_shndx &&
792 (ext_sym + j)->e_type == T_FUNCTION ){
793 sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
794 break;
795 } else if (j == nb_syms - i - 1) {
796 sec = &shdr[coff_text_shndx];
797 sym->st_size = sec->s_size - ext_sym->e_value;
798 break;
801 } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
802 for (j = aux_size + 1; j < nb_syms - i; j++) {
803 if ((ext_sym + j)->e_scnum == data_shndx) {
804 sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
805 break;
806 } else if (j == nb_syms - i - 1) {
807 sec = &shdr[coff_data_shndx];
808 sym->st_size = sec->s_size - ext_sym->e_value;
809 break;
812 } else {
813 sym->st_size = 0;
816 sym->st_type = ext_sym->e_type;
817 sym->st_shndx = ext_sym->e_scnum;
821 /* find text relocations, if any */
822 sec = &shdr[coff_text_shndx];
823 coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
824 nb_relocs = sec->s_nreloc;
826 /* set coff relocation */
827 relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
828 for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
829 i++, ext_rel++, rel++) {
830 memset(rel, 0, sizeof(*rel));
831 rel->r_reloc = ext_rel;
832 rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
833 rel->r_type = *(uint16_t *)ext_rel->r_type;
835 return 0;
838 #endif /* CONFIG_FORMAT_COFF */
840 #ifdef CONFIG_FORMAT_MACH
842 /* File Header */
843 struct mach_header mach_hdr;
845 /* commands */
846 struct segment_command *segment = 0;
847 struct dysymtab_command *dysymtabcmd = 0;
848 struct symtab_command *symtabcmd = 0;
850 /* section */
851 struct section *section_hdr;
852 struct section *text_sec_hdr;
853 uint8_t **sdata;
855 /* relocs */
856 struct relocation_info *relocs;
858 /* symbols */
859 EXE_SYM *symtab;
860 struct nlist *symtab_std;
861 char *strtab;
863 /* indirect symbols */
864 uint32_t *tocdylib;
866 /* Utility functions */
868 static inline char *find_str_by_index(int index)
870 return strtab+index;
873 /* Used by dyngen common code */
874 static char *get_sym_name(EXE_SYM *sym)
876 char *name = find_str_by_index(sym->n_un.n_strx);
878 if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
879 return "debug";
881 if(!name)
882 return name;
883 if(name[0]=='_')
884 return name + 1;
885 else
886 return name;
889 /* find a section index given its segname, sectname */
890 static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
891 const char *sectname)
893 int i;
894 struct section *sec = section_hdr;
896 for(i = 0; i < shnum; i++, sec++) {
897 if (!sec->segname || !sec->sectname)
898 continue;
899 if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
900 return i;
902 return -1;
905 /* find a section header given its segname, sectname */
906 struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
907 const char *sectname)
909 int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
910 if(index == -1)
911 return NULL;
912 return section_hdr+index;
916 static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
918 struct scattered_relocation_info * scarel;
920 if(R_SCATTERED & rel->r_address) {
921 scarel = (struct scattered_relocation_info*)rel;
922 if(scarel->r_type != PPC_RELOC_PAIR)
923 error("fetch_next_pair_value: looking for a pair which was not found (1)");
924 *value = scarel->r_value;
925 } else {
926 if(rel->r_type != PPC_RELOC_PAIR)
927 error("fetch_next_pair_value: looking for a pair which was not found (2)");
928 *value = rel->r_address;
932 /* find a sym name given its value, in a section number */
933 static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
935 int i, ret = -1;
937 for( i = 0 ; i < nb_syms; i++ )
939 if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
940 (symtab[i].n_sect == sectnum) && (symtab[i].st_value <= value) )
942 if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
943 ret = i;
946 if( ret < 0 ) {
947 *offset = 0;
948 return 0;
949 } else {
950 *offset = value - symtab[ret].st_value;
951 return get_sym_name(&symtab[ret]);
956 * Find symbol name given a (virtual) address, and a section which is of type
957 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
959 static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
961 unsigned int tocindex, symindex, size;
962 const char *name = 0;
964 /* Sanity check */
965 if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
966 return (char*)0;
968 if( sec_hdr->flags & S_SYMBOL_STUBS ){
969 size = sec_hdr->reserved2;
970 if(size == 0)
971 error("size = 0");
974 else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
975 sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
976 size = sizeof(unsigned long);
977 else
978 return 0;
980 /* Compute our index in toc */
981 tocindex = (address - sec_hdr->addr)/size;
982 symindex = tocdylib[sec_hdr->reserved1 + tocindex];
984 name = get_sym_name(&symtab[symindex]);
986 return name;
989 static const char * find_reloc_name_given_its_address(int address)
991 unsigned int i;
992 for(i = 0; i < segment->nsects ; i++)
994 const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
995 if((long)name != -1)
996 return name;
998 return 0;
1001 static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
1003 char * name = 0;
1004 struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1005 int sectnum = rel->r_symbolnum;
1006 int sectoffset;
1007 int other_half=0;
1009 /* init the slide value */
1010 *sslide = 0;
1012 if(R_SCATTERED & rel->r_address)
1013 return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
1015 if(rel->r_extern)
1017 /* ignore debug sym */
1018 if ( symtab[rel->r_symbolnum].n_type & N_STAB )
1019 return 0;
1020 return get_sym_name(&symtab[rel->r_symbolnum]);
1023 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
1024 sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
1026 if(sectnum==0xffffff)
1027 return 0;
1029 /* Sanity Check */
1030 if(sectnum > segment->nsects)
1031 error("sectnum > segment->nsects");
1033 switch(rel->r_type)
1035 case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1036 break;
1037 case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1038 break;
1039 case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1040 break;
1041 case PPC_RELOC_BR24:
1042 sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1043 if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1044 break;
1045 default:
1046 error("switch(rel->type) not found");
1049 if(rel->r_pcrel)
1050 sectoffset += rel->r_address;
1052 if (rel->r_type == PPC_RELOC_BR24)
1053 name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1055 /* search it in the full symbol list, if not found */
1056 if(!name)
1057 name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1059 return name;
1062 /* Used by dyngen common code */
1063 static const char * get_rel_sym_name(EXE_RELOC * rel)
1065 int sslide;
1066 return get_reloc_name( rel, &sslide);
1069 /* Used by dyngen common code */
1070 static host_ulong get_rel_offset(EXE_RELOC *rel)
1072 struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1073 if(R_SCATTERED & rel->r_address)
1074 return sca_rel->r_address;
1075 else
1076 return rel->r_address;
1079 /* load a mach-o object file */
1080 int load_object(const char *filename)
1082 int fd;
1083 unsigned int offset_to_segment = 0;
1084 unsigned int offset_to_dysymtab = 0;
1085 unsigned int offset_to_symtab = 0;
1086 struct load_command lc;
1087 unsigned int i, j;
1088 EXE_SYM *sym;
1089 struct nlist *syment;
1091 fd = open(filename, O_RDONLY);
1092 if (fd < 0)
1093 error("can't open file '%s'", filename);
1095 /* Read Mach header. */
1096 if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1097 error("unable to read file header");
1099 /* Check Mach identification. */
1100 if (!check_mach_header(mach_hdr)) {
1101 error("bad Mach header");
1104 if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1105 error("Unsupported CPU");
1107 if (mach_hdr.filetype != MH_OBJECT)
1108 error("Unsupported Mach Object");
1110 /* read segment headers */
1111 for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1113 if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1114 error("unable to read load_command");
1115 if(lc.cmd == LC_SEGMENT)
1117 offset_to_segment = j;
1118 lseek(fd, offset_to_segment, SEEK_SET);
1119 segment = malloc(sizeof(struct segment_command));
1120 if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1121 error("unable to read LC_SEGMENT");
1123 if(lc.cmd == LC_DYSYMTAB)
1125 offset_to_dysymtab = j;
1126 lseek(fd, offset_to_dysymtab, SEEK_SET);
1127 dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1128 if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1129 error("unable to read LC_DYSYMTAB");
1131 if(lc.cmd == LC_SYMTAB)
1133 offset_to_symtab = j;
1134 lseek(fd, offset_to_symtab, SEEK_SET);
1135 symtabcmd = malloc(sizeof(struct symtab_command));
1136 if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1137 error("unable to read LC_SYMTAB");
1139 j+=lc.cmdsize;
1141 lseek(fd, j, SEEK_SET);
1144 if(!segment)
1145 error("unable to find LC_SEGMENT");
1147 /* read section headers */
1148 section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1150 /* read all section data */
1151 sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1152 memset(sdata, 0, sizeof(void *) * segment->nsects);
1154 /* Load the data in section data */
1155 for(i = 0; i < segment->nsects; i++) {
1156 sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1159 /* text section */
1160 text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1161 i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1162 if (i == -1 || !text_sec_hdr)
1163 error("could not find __TEXT,__text section");
1164 text = sdata[i];
1166 /* Make sure dysym was loaded */
1167 if(!(int)dysymtabcmd)
1168 error("could not find __DYSYMTAB segment");
1170 /* read the table of content of the indirect sym */
1171 tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1173 /* Make sure symtab was loaded */
1174 if(!(int)symtabcmd)
1175 error("could not find __SYMTAB segment");
1176 nb_syms = symtabcmd->nsyms;
1178 symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1179 strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1181 symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1183 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1184 for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1185 struct nlist *sym_follow, *sym_next = 0;
1186 unsigned int j;
1187 memset(sym, 0, sizeof(*sym));
1189 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1190 continue;
1192 memcpy(sym, syment, sizeof(*syment));
1194 /* Find the following symbol in order to get the current symbol size */
1195 for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1196 if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1197 continue;
1198 if(!sym_next) {
1199 sym_next = sym_follow;
1200 continue;
1202 if(!(sym_next->n_value > sym_follow->n_value))
1203 continue;
1204 sym_next = sym_follow;
1206 if(sym_next)
1207 sym->st_size = sym_next->n_value - sym->st_value;
1208 else
1209 sym->st_size = text_sec_hdr->size - sym->st_value;
1212 /* Find Reloc */
1213 relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1214 nb_relocs = text_sec_hdr->nreloc;
1216 close(fd);
1217 return 0;
1220 #endif /* CONFIG_FORMAT_MACH */
1222 /* return true if the expression is a label reference */
1223 int get_reloc_expr(char *name, int name_size, const char *sym_name)
1225 const char *p;
1227 if (strstart(sym_name, "__op_param", &p)) {
1228 snprintf(name, name_size, "param%s", p);
1229 } else if (strstart(sym_name, "__op_gen_label", &p)) {
1230 snprintf(name, name_size, "param%s", p);
1231 return 1;
1232 } else {
1233 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1234 if (sym_name[0] == '.')
1235 snprintf(name, name_size,
1236 "(long)(&__dot_%s)",
1237 sym_name + 1);
1238 else
1239 #endif
1240 snprintf(name, name_size, "(long)(&%s)", sym_name);
1242 return 0;
1245 #ifdef HOST_IA64
1247 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1249 struct plt_entry {
1250 struct plt_entry *next;
1251 const char *name;
1252 unsigned long addend;
1253 } *plt_list;
1255 static int
1256 get_plt_index (const char *name, unsigned long addend)
1258 struct plt_entry *plt, *prev= NULL;
1259 int index = 0;
1261 /* see if we already have an entry for this target: */
1262 for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1263 if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1264 return index;
1266 /* nope; create a new PLT entry: */
1268 plt = malloc(sizeof(*plt));
1269 if (!plt) {
1270 perror("malloc");
1271 exit(1);
1273 memset(plt, 0, sizeof(*plt));
1274 plt->name = strdup(name);
1275 plt->addend = addend;
1277 /* append to plt-list: */
1278 if (prev)
1279 prev->next = plt;
1280 else
1281 plt_list = plt;
1282 return index;
1285 #endif
1287 #ifdef HOST_ARM
1289 int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1290 FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1291 ELF_RELOC *relocs, int nb_relocs)
1293 uint8_t *p;
1294 uint32_t insn;
1295 int offset, min_offset, pc_offset, data_size, spare, max_pool;
1296 uint8_t data_allocated[1024];
1297 unsigned int data_index;
1298 int type;
1300 memset(data_allocated, 0, sizeof(data_allocated));
1302 p = p_start;
1303 min_offset = p_end - p_start;
1304 spare = 0x7fffffff;
1305 while (p < p_start + min_offset) {
1306 insn = get32((uint32_t *)p);
1307 /* TODO: Armv5e ldrd. */
1308 /* TODO: VFP load. */
1309 if ((insn & 0x0d5f0000) == 0x051f0000) {
1310 /* ldr reg, [pc, #im] */
1311 offset = insn & 0xfff;
1312 if (!(insn & 0x00800000))
1313 offset = -offset;
1314 max_pool = 4096;
1315 type = 0;
1316 } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1317 /* FPA ldf. */
1318 offset = (insn & 0xff) << 2;
1319 if (!(insn & 0x00800000))
1320 offset = -offset;
1321 max_pool = 1024;
1322 type = 1;
1323 } else if ((insn & 0x0fff0000) == 0x028f0000) {
1324 /* Some gcc load a doubleword immediate with
1325 add regN, pc, #imm
1326 ldmia regN, {regN, regM}
1327 Hope and pray the compiler never generates somethin like
1328 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1329 int r;
1331 r = (insn & 0xf00) >> 7;
1332 offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1333 max_pool = 1024;
1334 type = 2;
1335 } else {
1336 max_pool = 0;
1337 type = -1;
1339 if (type >= 0) {
1340 /* PC-relative load needs fixing up. */
1341 if (spare > max_pool - offset)
1342 spare = max_pool - offset;
1343 if ((offset & 3) !=0)
1344 error("%s:%04x: pc offset must be 32 bit aligned",
1345 name, start_offset + p - p_start);
1346 if (offset < 0)
1347 error("%s:%04x: Embedded literal value",
1348 name, start_offset + p - p_start);
1349 pc_offset = p - p_start + offset + 8;
1350 if (pc_offset <= (p - p_start) ||
1351 pc_offset >= (p_end - p_start))
1352 error("%s:%04x: pc offset must point inside the function code",
1353 name, start_offset + p - p_start);
1354 if (pc_offset < min_offset)
1355 min_offset = pc_offset;
1356 if (outfile) {
1357 /* The intruction position */
1358 fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1359 p - p_start);
1360 /* The position of the constant pool data. */
1361 data_index = ((p_end - p_start) - pc_offset) >> 2;
1362 fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1363 data_index);
1364 fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
1365 fprintf(outfile, " arm_ldr_ptr++;\n");
1368 p += 4;
1371 /* Copy and relocate the constant pool data. */
1372 data_size = (p_end - p_start) - min_offset;
1373 if (data_size > 0 && outfile) {
1374 spare += min_offset;
1375 fprintf(outfile, " arm_data_ptr -= %d;\n", data_size >> 2);
1376 fprintf(outfile, " arm_pool_ptr -= %d;\n", data_size);
1377 fprintf(outfile, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1378 " arm_pool_ptr = gen_code_ptr + %d;\n",
1379 spare, spare);
1381 data_index = 0;
1382 for (pc_offset = min_offset;
1383 pc_offset < p_end - p_start;
1384 pc_offset += 4) {
1386 ELF_RELOC *rel;
1387 int i, addend, type;
1388 const char *sym_name;
1389 char relname[1024];
1391 /* data value */
1392 addend = get32((uint32_t *)(p_start + pc_offset));
1393 relname[0] = '\0';
1394 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1395 if (rel->r_offset == (pc_offset + start_offset)) {
1396 sym_name = get_rel_sym_name(rel);
1397 /* the compiler leave some unnecessary references to the code */
1398 get_reloc_expr(relname, sizeof(relname), sym_name);
1399 type = ELF32_R_TYPE(rel->r_info);
1400 if (type != R_ARM_ABS32)
1401 error("%s: unsupported data relocation", name);
1402 break;
1405 fprintf(outfile, " arm_data_ptr[%d] = 0x%x",
1406 data_index, addend);
1407 if (relname[0] != '\0')
1408 fprintf(outfile, " + %s", relname);
1409 fprintf(outfile, ";\n");
1411 data_index++;
1415 if (p == p_start)
1416 goto arm_ret_error;
1417 p -= 4;
1418 insn = get32((uint32_t *)p);
1419 /* The last instruction must be an ldm instruction. There are several
1420 forms generated by gcc:
1421 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1422 ldmia sp, {..., pc}
1423 ldmea fp, {..., pc} */
1424 if ((insn & 0xffff8000) == 0xe99d8000) {
1425 if (outfile) {
1426 fprintf(outfile,
1427 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1428 p - p_start);
1430 p += 4;
1431 } else if ((insn & 0xffff8000) != 0xe89d8000
1432 && (insn & 0xffff8000) != 0xe91b8000) {
1433 arm_ret_error:
1434 if (!outfile)
1435 printf("%s: invalid epilog\n", name);
1437 return p - p_start;
1439 #endif
1442 #define MAX_ARGS 3
1444 /* generate op code */
1445 void gen_code(const char *name, host_ulong offset, host_ulong size,
1446 FILE *outfile, int gen_switch)
1448 int copy_size = 0;
1449 uint8_t *p_start, *p_end;
1450 host_ulong start_offset;
1451 int nb_args, i, n;
1452 uint8_t args_present[MAX_ARGS];
1453 const char *sym_name, *p;
1454 EXE_RELOC *rel;
1456 /* Compute exact size excluding prologue and epilogue instructions.
1457 * Increment start_offset to skip epilogue instructions, then compute
1458 * copy_size the indicate the size of the remaining instructions (in
1459 * bytes).
1461 p_start = text + offset;
1462 p_end = p_start + size;
1463 start_offset = offset;
1464 #if defined(HOST_I386) || defined(HOST_X86_64)
1465 #ifdef CONFIG_FORMAT_COFF
1467 uint8_t *p;
1468 p = p_end - 1;
1469 if (p == p_start)
1470 error("empty code for %s", name);
1471 while (*p != 0xc3) {
1472 p--;
1473 if (p <= p_start)
1474 error("ret or jmp expected at the end of %s", name);
1476 copy_size = p - p_start;
1478 #else
1480 int len;
1481 len = p_end - p_start;
1482 if (len == 0)
1483 error("empty code for %s", name);
1484 if (p_end[-1] == 0xc3) {
1485 len--;
1486 } else {
1487 error("ret or jmp expected at the end of %s", name);
1489 copy_size = len;
1491 #endif
1492 #elif defined(HOST_PPC)
1494 uint8_t *p;
1495 p = (void *)(p_end - 4);
1496 if (p == p_start)
1497 error("empty code for %s", name);
1498 if (get32((uint32_t *)p) != 0x4e800020)
1499 error("blr expected at the end of %s", name);
1500 copy_size = p - p_start;
1502 #elif defined(HOST_S390)
1504 uint8_t *p;
1505 p = (void *)(p_end - 2);
1506 if (p == p_start)
1507 error("empty code for %s", name);
1508 if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
1509 error("br expected at the end of %s", name);
1510 copy_size = p - p_start;
1512 #elif defined(HOST_ALPHA)
1514 uint8_t *p;
1515 p = p_end - 4;
1516 #if 0
1517 /* XXX: check why it occurs */
1518 if (p == p_start)
1519 error("empty code for %s", name);
1520 #endif
1521 if (get32((uint32_t *)p) != 0x6bfa8001)
1522 error("ret expected at the end of %s", name);
1523 copy_size = p - p_start;
1525 #elif defined(HOST_IA64)
1527 uint8_t *p;
1528 p = (void *)(p_end - 4);
1529 if (p == p_start)
1530 error("empty code for %s", name);
1531 /* br.ret.sptk.many b0;; */
1532 /* 08 00 84 00 */
1533 if (get32((uint32_t *)p) != 0x00840008)
1534 error("br.ret.sptk.many b0;; expected at the end of %s", name);
1535 copy_size = p_end - p_start;
1537 #elif defined(HOST_SPARC)
1539 #define INSN_SAVE 0x9de3a000
1540 #define INSN_RET 0x81c7e008
1541 #define INSN_RETL 0x81c3e008
1542 #define INSN_RESTORE 0x81e80000
1543 #define INSN_RETURN 0x81cfe008
1544 #define INSN_NOP 0x01000000
1545 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1546 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1548 uint32_t start_insn, end_insn1, end_insn2;
1549 uint8_t *p;
1550 p = (void *)(p_end - 8);
1551 if (p <= p_start)
1552 error("empty code for %s", name);
1553 start_insn = get32((uint32_t *)(p_start + 0x0));
1554 end_insn1 = get32((uint32_t *)(p + 0x0));
1555 end_insn2 = get32((uint32_t *)(p + 0x4));
1556 if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1557 (start_insn & ~0x1fff) == INSN_ADD_SP) {
1558 p_start += 0x4;
1559 start_offset += 0x4;
1560 if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1561 /* SPARC v7: ret; restore; */ ;
1562 else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1563 /* SPARC v9: return; nop; */ ;
1564 else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1565 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1566 else
1568 error("ret; restore; not found at end of %s", name);
1569 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1571 } else {
1572 error("No save at the beginning of %s", name);
1574 #if 0
1575 /* Skip a preceeding nop, if present. */
1576 if (p > p_start) {
1577 skip_insn = get32((uint32_t *)(p - 0x4));
1578 if (skip_insn == INSN_NOP)
1579 p -= 4;
1581 #endif
1582 copy_size = p - p_start;
1584 #elif defined(HOST_SPARC64)
1586 #define INSN_SAVE 0x9de3a000
1587 #define INSN_RET 0x81c7e008
1588 #define INSN_RETL 0x81c3e008
1589 #define INSN_RESTORE 0x81e80000
1590 #define INSN_RETURN 0x81cfe008
1591 #define INSN_NOP 0x01000000
1592 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1593 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1595 uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1596 uint8_t *p;
1597 p = (void *)(p_end - 8);
1598 #if 0
1599 /* XXX: check why it occurs */
1600 if (p <= p_start)
1601 error("empty code for %s", name);
1602 #endif
1603 start_insn = get32((uint32_t *)(p_start + 0x0));
1604 end_insn1 = get32((uint32_t *)(p + 0x0));
1605 end_insn2 = get32((uint32_t *)(p + 0x4));
1606 if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1607 (start_insn & ~0x1fff) == INSN_ADD_SP) {
1608 p_start += 0x4;
1609 start_offset += 0x4;
1610 if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1611 /* SPARC v7: ret; restore; */ ;
1612 else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1613 /* SPARC v9: return; nop; */ ;
1614 else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1615 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1616 else
1618 error("ret; restore; not found at end of %s", name);
1619 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1621 } else {
1622 error("No save at the beginning of %s", name);
1625 #if 0
1626 /* Skip a preceeding nop, if present. */
1627 if (p > p_start) {
1628 skip_insn = get32((uint32_t *)(p - 0x4));
1629 if (skip_insn == 0x01000000)
1630 p -= 4;
1632 #endif
1634 copy_size = p - p_start;
1636 #elif defined(HOST_ARM)
1638 uint32_t insn;
1640 if ((p_end - p_start) <= 16)
1641 error("%s: function too small", name);
1642 if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1643 (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1644 get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1645 error("%s: invalid prolog", name);
1646 p_start += 12;
1647 start_offset += 12;
1648 insn = get32((uint32_t *)p_start);
1649 if ((insn & 0xffffff00) == 0xe24dd000) {
1650 /* Stack adjustment. Assume op uses the frame pointer. */
1651 p_start -= 4;
1652 start_offset -= 4;
1654 copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1655 relocs, nb_relocs);
1657 #elif defined(HOST_M68K)
1659 uint8_t *p;
1660 p = (void *)(p_end - 2);
1661 if (p == p_start)
1662 error("empty code for %s", name);
1663 // remove NOP's, probably added for alignment
1664 while ((get16((uint16_t *)p) == 0x4e71) &&
1665 (p>p_start))
1666 p -= 2;
1667 if (get16((uint16_t *)p) != 0x4e75)
1668 error("rts expected at the end of %s", name);
1669 copy_size = p - p_start;
1671 #elif defined(HOST_HPPA)
1673 uint8_t *p;
1674 p = p_start;
1675 while (p < p_end) {
1676 uint32_t insn = get32((uint32_t *)p);
1677 if (insn == 0x6bc23fd9 || /* stw rp,-14(sp) */
1678 insn == 0x08030241 || /* copy r3,r1 */
1679 insn == 0x081e0243 || /* copy sp,r3 */
1680 (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1681 (insn & 0xffffc000) == 0x6fc10000) /* stwm r1,x(sp) */
1682 p += 4;
1683 else
1684 break;
1686 start_offset += p - p_start;
1687 p_start = p;
1688 p = p_end - 4;
1690 while (p > p_start) {
1691 uint32_t insn = get32((uint32_t *)p);
1692 if ((insn & 0xffffc000) == 0x347e0000 || /* ldo x(r3),sp */
1693 (insn & 0xffe0c000) == 0x4fc00000 || /* ldwm x(sp),rx */
1694 (insn & 0xffffc000) == 0x37de0000 || /* ldo x(sp),sp */
1695 insn == 0x48623fd9 || /* ldw -14(r3),rp */
1696 insn == 0xe840c000 || /* bv r0(rp) */
1697 insn == 0xe840c002) /* bv,n r0(rp) */
1698 p -= 4;
1699 else
1700 break;
1702 p += 4;
1703 if (p <= p_start)
1704 error("empty code for %s", name);
1706 copy_size = p - p_start;
1708 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
1710 #define INSN_RETURN 0x03e00008
1711 #define INSN_NOP 0x00000000
1713 uint8_t *p = p_end;
1715 if (p < (p_start + 0x8)) {
1716 error("empty code for %s", name);
1717 } else {
1718 uint32_t end_insn1, end_insn2;
1720 p -= 0x8;
1721 end_insn1 = get32((uint32_t *)(p + 0x0));
1722 end_insn2 = get32((uint32_t *)(p + 0x4));
1723 if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
1724 error("jr ra not found at end of %s", name);
1726 copy_size = p - p_start;
1728 #else
1729 #error unsupported CPU
1730 #endif
1732 /* compute the number of arguments by looking at the relocations */
1733 for(i = 0;i < MAX_ARGS; i++)
1734 args_present[i] = 0;
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 (strstart(sym_name, "__op_param", &p) ||
1744 strstart(sym_name, "__op_gen_label", &p)) {
1745 n = strtoul(p, NULL, 10);
1746 if (n > MAX_ARGS)
1747 error("too many arguments in %s", name);
1748 args_present[n - 1] = 1;
1753 nb_args = 0;
1754 while (nb_args < MAX_ARGS && args_present[nb_args])
1755 nb_args++;
1756 for(i = nb_args; i < MAX_ARGS; i++) {
1757 if (args_present[i])
1758 error("inconsistent argument numbering in %s", name);
1761 if (gen_switch == 2) {
1762 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1763 } else if (gen_switch == 1) {
1765 /* output C code */
1766 fprintf(outfile, "case INDEX_%s: {\n", name);
1767 if (nb_args > 0) {
1768 fprintf(outfile, " long ");
1769 for(i = 0; i < nb_args; i++) {
1770 if (i != 0)
1771 fprintf(outfile, ", ");
1772 fprintf(outfile, "param%d", i + 1);
1774 fprintf(outfile, ";\n");
1776 #if defined(HOST_IA64)
1777 fprintf(outfile, " extern char %s;\n", name);
1778 #else
1779 fprintf(outfile, " extern void %s();\n", name);
1780 #endif
1782 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1783 host_ulong offset = get_rel_offset(rel);
1784 if (offset >= start_offset &&
1785 offset < start_offset + (p_end - p_start)) {
1786 sym_name = get_rel_sym_name(rel);
1787 if(!sym_name)
1788 continue;
1789 if (*sym_name &&
1790 !strstart(sym_name, "__op_param", NULL) &&
1791 !strstart(sym_name, "__op_jmp", NULL) &&
1792 !strstart(sym_name, "__op_gen_label", NULL)) {
1793 #if defined(HOST_SPARC) || defined(HOST_HPPA)
1794 if (sym_name[0] == '.') {
1795 fprintf(outfile,
1796 "extern char __dot_%s __asm__(\"%s\");\n",
1797 sym_name+1, sym_name);
1798 continue;
1800 #endif
1801 #if defined(__APPLE__)
1802 /* Set __attribute((unused)) on darwin because we
1803 want to avoid warning when we don't use the symbol. */
1804 fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name);
1805 #elif defined(HOST_IA64)
1806 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1808 * PCREL21 br.call targets generally
1809 * are out of range and need to go
1810 * through an "import stub".
1812 fprintf(outfile, " extern char %s;\n",
1813 sym_name);
1814 #else
1815 fprintf(outfile, "extern char %s;\n", sym_name);
1816 #endif
1821 #ifdef __hppa__
1822 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)__canonicalize_funcptr_for_compare(%s)+%d), %d);\n",
1823 name, (int)(start_offset - offset), copy_size);
1824 #else
1825 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1826 name, (int)(start_offset - offset), copy_size);
1827 #endif
1829 /* emit code offset information */
1831 EXE_SYM *sym;
1832 const char *sym_name, *p;
1833 host_ulong val;
1834 int n;
1836 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1837 sym_name = get_sym_name(sym);
1838 if (strstart(sym_name, "__op_label", &p)) {
1839 uint8_t *ptr;
1840 unsigned long offset;
1842 /* test if the variable refers to a label inside
1843 the code we are generating */
1844 #ifdef CONFIG_FORMAT_COFF
1845 if (sym->st_shndx == text_shndx) {
1846 ptr = sdata[coff_text_shndx];
1847 } else if (sym->st_shndx == data_shndx) {
1848 ptr = sdata[coff_data_shndx];
1849 } else {
1850 ptr = NULL;
1852 #elif defined(CONFIG_FORMAT_MACH)
1853 if(!sym->n_sect)
1854 continue;
1855 ptr = sdata[sym->n_sect-1];
1856 #else
1857 ptr = sdata[sym->st_shndx];
1858 #endif
1859 if (!ptr)
1860 error("__op_labelN in invalid section");
1861 offset = sym->st_value;
1862 #ifdef CONFIG_FORMAT_MACH
1863 offset -= section_hdr[sym->n_sect-1].addr;
1864 #endif
1865 val = *(host_ulong *)(ptr + offset);
1866 #ifdef ELF_USES_RELOCA
1868 int reloc_shndx, nb_relocs1, j;
1870 /* try to find a matching relocation */
1871 reloc_shndx = find_reloc(sym->st_shndx);
1872 if (reloc_shndx) {
1873 nb_relocs1 = shdr[reloc_shndx].sh_size /
1874 shdr[reloc_shndx].sh_entsize;
1875 rel = (ELF_RELOC *)sdata[reloc_shndx];
1876 for(j = 0; j < nb_relocs1; j++) {
1877 if (rel->r_offset == offset) {
1878 val = rel->r_addend;
1879 break;
1881 rel++;
1885 #endif
1886 if (val >= start_offset && val <= start_offset + copy_size) {
1887 n = strtol(p, NULL, 10);
1888 fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1894 /* load parameters in variables */
1895 for(i = 0; i < nb_args; i++) {
1896 fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
1899 /* patch relocations */
1900 #if defined(HOST_I386)
1902 char relname[256];
1903 int type, is_label;
1904 int addend;
1905 int reloc_offset;
1906 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1907 if (rel->r_offset >= start_offset &&
1908 rel->r_offset < start_offset + copy_size) {
1909 sym_name = get_rel_sym_name(rel);
1910 if (!sym_name)
1911 continue;
1912 reloc_offset = rel->r_offset - start_offset;
1913 if (strstart(sym_name, "__op_jmp", &p)) {
1914 int n;
1915 n = strtol(p, NULL, 10);
1916 /* __op_jmp relocations are done at
1917 runtime to do translated block
1918 chaining: the offset of the instruction
1919 needs to be stored */
1920 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1921 n, reloc_offset);
1922 continue;
1925 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1926 addend = get32((uint32_t *)(text + rel->r_offset));
1927 #ifdef CONFIG_FORMAT_ELF
1928 type = ELF32_R_TYPE(rel->r_info);
1929 if (is_label) {
1930 switch(type) {
1931 case R_386_32:
1932 case R_386_PC32:
1933 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1934 reloc_offset, type, relname, addend);
1935 break;
1936 default:
1937 error("unsupported i386 relocation (%d)", type);
1939 } else {
1940 switch(type) {
1941 case R_386_32:
1942 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1943 reloc_offset, relname, addend);
1944 break;
1945 case R_386_PC32:
1946 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1947 reloc_offset, relname, reloc_offset, addend);
1948 break;
1949 default:
1950 error("unsupported i386 relocation (%d)", type);
1953 #elif defined(CONFIG_FORMAT_COFF)
1955 char *temp_name;
1956 int j;
1957 EXE_SYM *sym;
1958 temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1959 if (!strcmp(temp_name, ".data")) {
1960 for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1961 if (strstart(sym->st_name, sym_name, NULL)) {
1962 addend -= sym->st_value;
1967 type = rel->r_type;
1968 if (is_label) {
1969 /* TCG uses elf relocation constants */
1970 #define R_386_32 1
1971 #define R_386_PC32 2
1972 switch(type) {
1973 case DIR32:
1974 type = R_386_32;
1975 goto do_reloc;
1976 case DISP32:
1977 type = R_386_PC32;
1978 addend -= 4;
1979 do_reloc:
1980 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
1981 reloc_offset, type, relname, addend);
1982 break;
1983 default:
1984 error("unsupported i386 relocation (%d)", type);
1986 } else {
1987 switch(type) {
1988 case DIR32:
1989 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1990 reloc_offset, relname, addend);
1991 break;
1992 case DISP32:
1993 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1994 reloc_offset, relname, reloc_offset, addend);
1995 break;
1996 default:
1997 error("unsupported i386 relocation (%d)", type);
2000 #else
2001 #error unsupport object format
2002 #endif
2006 #elif defined(HOST_X86_64)
2008 char relname[256];
2009 int type, is_label;
2010 int addend;
2011 int reloc_offset;
2012 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2013 if (rel->r_offset >= start_offset &&
2014 rel->r_offset < start_offset + copy_size) {
2015 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2016 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2017 type = ELF32_R_TYPE(rel->r_info);
2018 addend = rel->r_addend;
2019 reloc_offset = rel->r_offset - start_offset;
2020 if (is_label) {
2021 switch(type) {
2022 case R_X86_64_32:
2023 case R_X86_64_32S:
2024 case R_X86_64_PC32:
2025 fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2026 reloc_offset, type, relname, addend);
2027 break;
2028 default:
2029 error("unsupported X86_64 relocation (%d)", type);
2031 } else {
2032 switch(type) {
2033 case R_X86_64_32:
2034 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
2035 reloc_offset, relname, addend);
2036 break;
2037 case R_X86_64_32S:
2038 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
2039 reloc_offset, relname, addend);
2040 break;
2041 case R_X86_64_PC32:
2042 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
2043 reloc_offset, relname, reloc_offset, addend);
2044 break;
2045 default:
2046 error("unsupported X86_64 relocation (%d)", type);
2052 #elif defined(HOST_PPC)
2054 #ifdef CONFIG_FORMAT_ELF
2055 char relname[256];
2056 int type;
2057 int addend;
2058 int reloc_offset;
2059 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2060 if (rel->r_offset >= start_offset &&
2061 rel->r_offset < start_offset + copy_size) {
2062 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2063 reloc_offset = rel->r_offset - start_offset;
2064 if (strstart(sym_name, "__op_jmp", &p)) {
2065 int n;
2066 n = strtol(p, NULL, 10);
2067 /* __op_jmp relocations are done at
2068 runtime to do translated block
2069 chaining: the offset of the instruction
2070 needs to be stored */
2071 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2072 n, reloc_offset);
2073 continue;
2076 get_reloc_expr(relname, sizeof(relname), sym_name);
2077 type = ELF32_R_TYPE(rel->r_info);
2078 addend = rel->r_addend;
2079 switch(type) {
2080 case R_PPC_ADDR32:
2081 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2082 reloc_offset, relname, addend);
2083 break;
2084 case R_PPC_ADDR16_LO:
2085 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
2086 reloc_offset, relname, addend);
2087 break;
2088 case R_PPC_ADDR16_HI:
2089 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
2090 reloc_offset, relname, addend);
2091 break;
2092 case R_PPC_ADDR16_HA:
2093 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
2094 reloc_offset, relname, addend);
2095 break;
2096 case R_PPC_REL24:
2097 /* warning: must be at 32 MB distancy */
2098 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
2099 reloc_offset, reloc_offset, relname, reloc_offset, addend);
2100 break;
2101 default:
2102 error("unsupported powerpc relocation (%d)", type);
2106 #elif defined(CONFIG_FORMAT_MACH)
2107 struct scattered_relocation_info *scarel;
2108 struct relocation_info * rel;
2109 char final_sym_name[256];
2110 const char *sym_name;
2111 const char *p;
2112 int slide, sslide;
2113 int i;
2115 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2116 unsigned int offset, length, value = 0;
2117 unsigned int type, pcrel, isym = 0;
2118 unsigned int usesym = 0;
2120 if(R_SCATTERED & rel->r_address) {
2121 scarel = (struct scattered_relocation_info*)rel;
2122 offset = (unsigned int)scarel->r_address;
2123 length = scarel->r_length;
2124 pcrel = scarel->r_pcrel;
2125 type = scarel->r_type;
2126 value = scarel->r_value;
2127 } else {
2128 value = isym = rel->r_symbolnum;
2129 usesym = (rel->r_extern);
2130 offset = rel->r_address;
2131 length = rel->r_length;
2132 pcrel = rel->r_pcrel;
2133 type = rel->r_type;
2136 slide = offset - start_offset;
2138 if (!(offset >= start_offset && offset < start_offset + size))
2139 continue; /* not in our range */
2141 sym_name = get_reloc_name(rel, &sslide);
2143 if(usesym && symtab[isym].n_type & N_STAB)
2144 continue; /* don't handle STAB (debug sym) */
2146 if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2147 int n;
2148 n = strtol(p, NULL, 10);
2149 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2150 n, slide);
2151 continue; /* Nothing more to do */
2154 if(!sym_name) {
2155 fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2156 name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2157 continue; /* dunno how to handle without final_sym_name */
2160 get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2161 sym_name);
2162 switch(type) {
2163 case PPC_RELOC_BR24:
2164 if (!strstart(sym_name,"__op_gen_label",&p)) {
2165 fprintf(outfile, "{\n");
2166 fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2167 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",
2168 slide, slide, name, sslide);
2169 fprintf(outfile, "}\n");
2170 } else {
2171 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2172 slide, slide, final_sym_name, slide);
2174 break;
2175 case PPC_RELOC_HI16:
2176 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2177 slide, final_sym_name, sslide);
2178 break;
2179 case PPC_RELOC_LO16:
2180 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2181 slide, final_sym_name, sslide);
2182 break;
2183 case PPC_RELOC_HA16:
2184 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2185 slide, final_sym_name, sslide);
2186 break;
2187 default:
2188 error("unsupported powerpc relocation (%d)", type);
2191 #else
2192 #error unsupport object format
2193 #endif
2195 #elif defined(HOST_S390)
2197 char relname[256];
2198 int type;
2199 int addend;
2200 int reloc_offset;
2201 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2202 if (rel->r_offset >= start_offset &&
2203 rel->r_offset < start_offset + copy_size) {
2204 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2205 get_reloc_expr(relname, sizeof(relname), sym_name);
2206 type = ELF32_R_TYPE(rel->r_info);
2207 addend = rel->r_addend;
2208 reloc_offset = rel->r_offset - start_offset;
2209 switch(type) {
2210 case R_390_32:
2211 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2212 reloc_offset, relname, addend);
2213 break;
2214 case R_390_16:
2215 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2216 reloc_offset, relname, addend);
2217 break;
2218 case R_390_8:
2219 fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2220 reloc_offset, relname, addend);
2221 break;
2222 case R_390_PC32DBL:
2223 if (ELF32_ST_TYPE(symtab[ELFW(R_SYM)(rel->r_info)].st_info) == STT_SECTION) {
2224 fprintf(outfile,
2225 " *(uint32_t *)(gen_code_ptr + %d) += "
2226 "((long)&%s - (long)gen_code_ptr) >> 1;\n",
2227 reloc_offset, name);
2229 else
2230 fprintf(outfile,
2231 " *(uint32_t *)(gen_code_ptr + %d) = "
2232 "(%s + %d - ((uint32_t)gen_code_ptr + %d)) >> 1;\n",
2233 reloc_offset, relname, addend, reloc_offset);
2234 break;
2235 default:
2236 error("unsupported s390 relocation (%d)", type);
2241 #elif defined(HOST_ALPHA)
2243 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2244 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2245 int type;
2246 long reloc_offset;
2248 type = ELF64_R_TYPE(rel->r_info);
2249 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2250 reloc_offset = rel->r_offset - start_offset;
2251 switch (type) {
2252 case R_ALPHA_GPDISP:
2253 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2254 as an immediate instead of constructing it from the pv or ra. */
2255 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2256 reloc_offset);
2257 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2258 reloc_offset + (int)rel->r_addend);
2259 break;
2260 case R_ALPHA_LITUSE:
2261 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2262 now, since some called functions (libc) need pv to be set up. */
2263 break;
2264 case R_ALPHA_HINT:
2265 /* Branch target prediction hint. Ignore for now. Should be already
2266 correct for in-function jumps. */
2267 break;
2268 case R_ALPHA_LITERAL:
2269 /* Load a literal from the GOT relative to the gp. Since there's only a
2270 single gp, nothing is to be done. */
2271 break;
2272 case R_ALPHA_GPRELHIGH:
2273 /* Handle fake relocations against __op_param symbol. Need to emit the
2274 high part of the immediate value instead. Other symbols need no
2275 special treatment. */
2276 if (strstart(sym_name, "__op_param", &p))
2277 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2278 reloc_offset, p);
2279 break;
2280 case R_ALPHA_GPRELLOW:
2281 if (strstart(sym_name, "__op_param", &p))
2282 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2283 reloc_offset, p);
2284 break;
2285 case R_ALPHA_BRSGP:
2286 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2287 set up the gp from the pv. */
2288 fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2289 reloc_offset, sym_name, reloc_offset);
2290 break;
2291 default:
2292 error("unsupported Alpha relocation (%d)", type);
2297 #elif defined(HOST_IA64)
2299 unsigned long sym_idx;
2300 long code_offset;
2301 char relname[256];
2302 int type;
2303 long addend;
2305 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2306 sym_idx = ELF64_R_SYM(rel->r_info);
2307 if (rel->r_offset < start_offset
2308 || rel->r_offset >= start_offset + copy_size)
2309 continue;
2310 sym_name = (strtab + symtab[sym_idx].st_name);
2311 code_offset = rel->r_offset - start_offset;
2312 if (strstart(sym_name, "__op_jmp", &p)) {
2313 int n;
2314 n = strtol(p, NULL, 10);
2315 /* __op_jmp relocations are done at
2316 runtime to do translated block
2317 chaining: the offset of the instruction
2318 needs to be stored */
2319 fprintf(outfile, " jmp_offsets[%d] ="
2320 "%ld + (gen_code_ptr - gen_code_buf);\n",
2321 n, code_offset);
2322 continue;
2324 get_reloc_expr(relname, sizeof(relname), sym_name);
2325 type = ELF64_R_TYPE(rel->r_info);
2326 addend = rel->r_addend;
2327 switch(type) {
2328 case R_IA64_IMM64:
2329 fprintf(outfile,
2330 " ia64_imm64(gen_code_ptr + %ld, "
2331 "%s + %ld);\n",
2332 code_offset, relname, addend);
2333 break;
2334 case R_IA64_LTOFF22X:
2335 case R_IA64_LTOFF22:
2336 fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
2337 " %s + %ld, %d);\n",
2338 code_offset, relname, addend,
2339 (type == R_IA64_LTOFF22X));
2340 break;
2341 case R_IA64_LDXMOV:
2342 fprintf(outfile,
2343 " ia64_ldxmov(gen_code_ptr + %ld,"
2344 " %s + %ld);\n", code_offset, relname, addend);
2345 break;
2347 case R_IA64_PCREL21B:
2348 if (strstart(sym_name, "__op_gen_label", NULL)) {
2349 fprintf(outfile,
2350 " ia64_imm21b(gen_code_ptr + %ld,"
2351 " (long) (%s + %ld -\n\t\t"
2352 "((long) gen_code_ptr + %ld)) >> 4);\n",
2353 code_offset, relname, addend,
2354 code_offset & ~0xfUL);
2355 } else {
2356 fprintf(outfile,
2357 " IA64_PLT(gen_code_ptr + %ld, "
2358 "%d);\t/* %s + %ld */\n",
2359 code_offset,
2360 get_plt_index(sym_name, addend),
2361 sym_name, addend);
2363 break;
2364 default:
2365 error("unsupported ia64 relocation (0x%x)",
2366 type);
2369 fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2370 copy_size - 16 + 2);
2372 #elif defined(HOST_SPARC)
2374 char relname[256];
2375 int type;
2376 int addend;
2377 int reloc_offset;
2378 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2379 if (rel->r_offset >= start_offset &&
2380 rel->r_offset < start_offset + copy_size) {
2381 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2382 get_reloc_expr(relname, sizeof(relname), sym_name);
2383 type = ELF32_R_TYPE(rel->r_info);
2384 addend = rel->r_addend;
2385 reloc_offset = rel->r_offset - start_offset;
2386 switch(type) {
2387 case R_SPARC_32:
2388 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2389 reloc_offset, relname, addend);
2390 break;
2391 case R_SPARC_HI22:
2392 fprintf(outfile,
2393 " *(uint32_t *)(gen_code_ptr + %d) = "
2394 "((*(uint32_t *)(gen_code_ptr + %d)) "
2395 " & ~0x3fffff) "
2396 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2397 reloc_offset, reloc_offset, relname, addend);
2398 break;
2399 case R_SPARC_LO10:
2400 fprintf(outfile,
2401 " *(uint32_t *)(gen_code_ptr + %d) = "
2402 "((*(uint32_t *)(gen_code_ptr + %d)) "
2403 " & ~0x3ff) "
2404 " | ((%s + %d) & 0x3ff);\n",
2405 reloc_offset, reloc_offset, relname, addend);
2406 break;
2407 case R_SPARC_WDISP30:
2408 fprintf(outfile,
2409 " *(uint32_t *)(gen_code_ptr + %d) = "
2410 "((*(uint32_t *)(gen_code_ptr + %d)) "
2411 " & ~0x3fffffff) "
2412 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2413 " & 0x3fffffff);\n",
2414 reloc_offset, reloc_offset, relname, addend,
2415 reloc_offset);
2416 break;
2417 case R_SPARC_WDISP22:
2418 fprintf(outfile,
2419 " *(uint32_t *)(gen_code_ptr + %d) = "
2420 "((*(uint32_t *)(gen_code_ptr + %d)) "
2421 " & ~0x3fffff) "
2422 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2423 " & 0x3fffff);\n",
2424 rel->r_offset - start_offset,
2425 rel->r_offset - start_offset,
2426 relname, addend,
2427 rel->r_offset - start_offset);
2428 break;
2429 default:
2430 error("unsupported sparc relocation (%d)", type);
2435 #elif defined(HOST_SPARC64)
2437 char relname[256];
2438 int type;
2439 int addend;
2440 int reloc_offset;
2441 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2442 if (rel->r_offset >= start_offset &&
2443 rel->r_offset < start_offset + copy_size) {
2444 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2445 get_reloc_expr(relname, sizeof(relname), sym_name);
2446 type = ELF32_R_TYPE(rel->r_info);
2447 addend = rel->r_addend;
2448 reloc_offset = rel->r_offset - start_offset;
2449 switch(type) {
2450 case R_SPARC_32:
2451 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2452 reloc_offset, relname, addend);
2453 break;
2454 case R_SPARC_HI22:
2455 fprintf(outfile,
2456 " *(uint32_t *)(gen_code_ptr + %d) = "
2457 "((*(uint32_t *)(gen_code_ptr + %d)) "
2458 " & ~0x3fffff) "
2459 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2460 reloc_offset, reloc_offset, relname, addend);
2461 break;
2462 case R_SPARC_LO10:
2463 fprintf(outfile,
2464 " *(uint32_t *)(gen_code_ptr + %d) = "
2465 "((*(uint32_t *)(gen_code_ptr + %d)) "
2466 " & ~0x3ff) "
2467 " | ((%s + %d) & 0x3ff);\n",
2468 reloc_offset, reloc_offset, relname, addend);
2469 break;
2470 case R_SPARC_OLO10:
2471 addend += ELF64_R_TYPE_DATA (rel->r_info);
2472 fprintf(outfile,
2473 " *(uint32_t *)(gen_code_ptr + %d) = "
2474 "((*(uint32_t *)(gen_code_ptr + %d)) "
2475 " & ~0x3ff) "
2476 " | ((%s + %d) & 0x3ff);\n",
2477 reloc_offset, reloc_offset, relname, addend);
2478 break;
2479 case R_SPARC_WDISP30:
2480 fprintf(outfile,
2481 " *(uint32_t *)(gen_code_ptr + %d) = "
2482 "((*(uint32_t *)(gen_code_ptr + %d)) "
2483 " & ~0x3fffffff) "
2484 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2485 " & 0x3fffffff);\n",
2486 reloc_offset, reloc_offset, relname, addend,
2487 reloc_offset);
2488 break;
2489 case R_SPARC_WDISP22:
2490 fprintf(outfile,
2491 " *(uint32_t *)(gen_code_ptr + %d) = "
2492 "((*(uint32_t *)(gen_code_ptr + %d)) "
2493 " & ~0x3fffff) "
2494 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2495 " & 0x3fffff);\n",
2496 reloc_offset, reloc_offset, relname, addend,
2497 reloc_offset);
2498 break;
2499 case R_SPARC_HH22:
2500 fprintf(outfile,
2501 " *(uint32_t *)(gen_code_ptr + %d) = "
2502 "((*(uint32_t *)(gen_code_ptr + %d)) "
2503 " & ~0x00000000) "
2504 " | (((%s + %d) >> 42) & 0x00000000);\n",
2505 reloc_offset, reloc_offset, relname, addend);
2506 break;
2508 case R_SPARC_LM22:
2509 fprintf(outfile,
2510 " *(uint32_t *)(gen_code_ptr + %d) = "
2511 "((*(uint32_t *)(gen_code_ptr + %d)) "
2512 " & ~0x00000000) "
2513 " | (((%s + %d) >> 10) & 0x00000000);\n",
2514 reloc_offset, reloc_offset, relname, addend);
2515 break;
2517 case R_SPARC_HM10:
2518 fprintf(outfile,
2519 " *(uint32_t *)(gen_code_ptr + %d) = "
2520 "((*(uint32_t *)(gen_code_ptr + %d)) "
2521 " & ~0x00000000) "
2522 " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
2523 reloc_offset, reloc_offset, relname, addend);
2524 break;
2526 default:
2527 error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
2532 #elif defined(HOST_ARM)
2534 char relname[256];
2535 int type;
2536 int addend;
2537 int reloc_offset;
2538 uint32_t insn;
2540 insn = get32((uint32_t *)(p_start + 4));
2541 /* If prologue ends in sub sp, sp, #const then assume
2542 op has a stack frame and needs the frame pointer. */
2543 if ((insn & 0xffffff00) == 0xe24dd000) {
2544 int i;
2545 uint32_t opcode;
2546 opcode = 0xe28db000; /* add fp, sp, #0. */
2547 #if 0
2548 /* ??? Need to undo the extra stack adjustment at the end of the op.
2549 For now just leave the stack misaligned and hope it doesn't break anything
2550 too important. */
2551 if ((insn & 4) != 0) {
2552 /* Preserve doubleword stack alignment. */
2553 fprintf(outfile,
2554 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2555 insn + 4);
2556 opcode -= 4;
2558 #endif
2559 insn = get32((uint32_t *)(p_start - 4));
2560 /* Calculate the size of the saved registers,
2561 excluding pc. */
2562 for (i = 0; i < 15; i++) {
2563 if (insn & (1 << i))
2564 opcode += 4;
2566 fprintf(outfile,
2567 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2569 arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
2570 relocs, nb_relocs);
2572 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2573 if (rel->r_offset >= start_offset &&
2574 rel->r_offset < start_offset + copy_size) {
2575 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2576 /* the compiler leave some unnecessary references to the code */
2577 if (sym_name[0] == '\0')
2578 continue;
2579 get_reloc_expr(relname, sizeof(relname), sym_name);
2580 type = ELF32_R_TYPE(rel->r_info);
2581 addend = get32((uint32_t *)(text + rel->r_offset));
2582 reloc_offset = rel->r_offset - start_offset;
2583 switch(type) {
2584 case R_ARM_ABS32:
2585 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2586 reloc_offset, relname, addend);
2587 break;
2588 case R_ARM_PC24:
2589 case R_ARM_JUMP24:
2590 case R_ARM_CALL:
2591 fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2592 reloc_offset, addend, relname);
2593 break;
2594 default:
2595 error("unsupported arm relocation (%d)", type);
2600 #elif defined(HOST_M68K)
2602 char relname[256];
2603 int type;
2604 int addend;
2605 int reloc_offset;
2606 Elf32_Sym *sym;
2607 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2608 if (rel->r_offset >= start_offset &&
2609 rel->r_offset < start_offset + copy_size) {
2610 sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2611 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2612 get_reloc_expr(relname, sizeof(relname), sym_name);
2613 type = ELF32_R_TYPE(rel->r_info);
2614 addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2615 reloc_offset = rel->r_offset - start_offset;
2616 switch(type) {
2617 case R_68K_32:
2618 fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2619 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2620 reloc_offset, relname, addend );
2621 break;
2622 case R_68K_PC32:
2623 fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2624 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2625 reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
2626 break;
2627 default:
2628 error("unsupported m68k relocation (%d)", type);
2633 #elif defined(HOST_HPPA)
2635 char relname[256];
2636 int type, is_label;
2637 int addend;
2638 int reloc_offset;
2639 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2640 if (rel->r_offset >= start_offset &&
2641 rel->r_offset < start_offset + copy_size) {
2642 sym_name = get_rel_sym_name(rel);
2643 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2644 is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
2645 type = ELF32_R_TYPE(rel->r_info);
2646 addend = rel->r_addend;
2647 reloc_offset = rel->r_offset - start_offset;
2649 if (is_label) {
2650 switch (type) {
2651 case R_PARISC_PCREL17F:
2652 fprintf(outfile,
2653 " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
2654 reloc_offset, type, relname, addend);
2655 break;
2656 default:
2657 error("unsupported hppa label relocation (%d)", type);
2659 } else {
2660 switch (type) {
2661 case R_PARISC_DIR21L:
2662 fprintf(outfile,
2663 " hppa_patch21l((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2664 reloc_offset, relname, addend);
2665 break;
2666 case R_PARISC_DIR14R:
2667 fprintf(outfile,
2668 " hppa_patch14r((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2669 reloc_offset, relname, addend);
2670 break;
2671 case R_PARISC_PCREL17F:
2672 if (strstart(sym_name, "__op_gen_label", NULL)) {
2673 fprintf(outfile,
2674 " hppa_patch17f((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2675 reloc_offset, relname, addend);
2676 } else {
2677 fprintf(outfile,
2678 " HPPA_RECORD_BRANCH(hppa_stubs, (uint32_t *)(gen_code_ptr + %d), %s);\n",
2679 reloc_offset, relname);
2681 break;
2682 case R_PARISC_DPREL21L:
2683 if (strstart(sym_name, "__op_param", &p))
2684 fprintf(outfile,
2685 " hppa_load_imm21l((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2686 reloc_offset, p, addend);
2687 else
2688 fprintf(outfile,
2689 " hppa_patch21l_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2690 reloc_offset, relname, addend);
2691 break;
2692 case R_PARISC_DPREL14R:
2693 if (strstart(sym_name, "__op_param", &p))
2694 fprintf(outfile,
2695 " hppa_load_imm14r((uint32_t *)(gen_code_ptr + %d), param%s, %d);\n",
2696 reloc_offset, p, addend);
2697 else
2698 fprintf(outfile,
2699 " hppa_patch14r_dprel((uint32_t *)(gen_code_ptr + %d), %s, %d);\n",
2700 reloc_offset, relname, addend);
2701 break;
2702 default:
2703 error("unsupported hppa relocation (%d)", type);
2709 #elif defined(HOST_MIPS) || defined(HOST_MIPS64)
2711 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2712 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2713 char relname[256];
2714 int type;
2715 int addend;
2716 int reloc_offset;
2718 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2719 /* the compiler leave some unnecessary references to the code */
2720 if (sym_name[0] == '\0')
2721 continue;
2722 get_reloc_expr(relname, sizeof(relname), sym_name);
2723 type = ELF32_R_TYPE(rel->r_info);
2724 addend = get32((uint32_t *)(text + rel->r_offset));
2725 reloc_offset = rel->r_offset - start_offset;
2726 switch (type) {
2727 case R_MIPS_26:
2728 fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
2729 rel->r_offset, sym_name);
2730 fprintf(outfile,
2731 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2732 "(0x%x & ~0x3fffff) "
2733 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2734 " & 0x3fffff);\n",
2735 reloc_offset, addend, addend, relname, reloc_offset);
2736 break;
2737 case R_MIPS_HI16:
2738 fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
2739 rel->r_offset, sym_name);
2740 fprintf(outfile,
2741 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2742 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2743 " & ~0xffff) "
2744 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2745 reloc_offset, reloc_offset, relname);
2746 break;
2747 case R_MIPS_LO16:
2748 fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
2749 rel->r_offset, sym_name);
2750 fprintf(outfile,
2751 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2752 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2753 " & ~0xffff) "
2754 " | (%s & 0xffff);\n",
2755 reloc_offset, reloc_offset, relname);
2756 break;
2757 case R_MIPS_PC16:
2758 fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
2759 rel->r_offset, sym_name);
2760 fprintf(outfile,
2761 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2762 "(0x%x & ~0xffff) "
2763 "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
2764 " & 0xffff);\n",
2765 reloc_offset, addend, addend, relname, reloc_offset);
2766 break;
2767 case R_MIPS_GOT16:
2768 case R_MIPS_CALL16:
2769 fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
2770 rel->r_offset, sym_name);
2771 fprintf(outfile,
2772 " *(uint32_t *)(gen_code_ptr + 0x%x) = "
2773 "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
2774 " & ~0xffff) "
2775 " | (((%s - 0x8000) >> 16) & 0xffff);\n",
2776 reloc_offset, reloc_offset, relname);
2777 break;
2778 default:
2779 error("unsupported MIPS relocation (%d)", type);
2784 #else
2785 #error unsupported CPU
2786 #endif
2787 fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
2788 fprintf(outfile, "}\n");
2789 fprintf(outfile, "break;\n\n");
2790 } else {
2791 fprintf(outfile, "static inline void gen_%s(", name);
2792 if (nb_args == 0) {
2793 fprintf(outfile, "void");
2794 } else {
2795 for(i = 0; i < nb_args; i++) {
2796 if (i != 0)
2797 fprintf(outfile, ", ");
2798 fprintf(outfile, "long param%d", i + 1);
2801 fprintf(outfile, ")\n");
2802 fprintf(outfile, "{\n");
2803 for(i = 0; i < nb_args; i++) {
2804 fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1);
2806 fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2807 fprintf(outfile, "}\n\n");
2811 int gen_file(FILE *outfile, int out_type)
2813 int i;
2814 EXE_SYM *sym;
2816 if (out_type == OUT_INDEX_OP) {
2817 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2818 const char *name;
2819 name = get_sym_name(sym);
2820 if (strstart(name, OP_PREFIX, NULL)) {
2821 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2824 } else if (out_type == OUT_GEN_OP) {
2825 /* generate gen_xxx functions */
2826 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2827 const char *name;
2828 name = get_sym_name(sym);
2829 if (strstart(name, OP_PREFIX, NULL)) {
2830 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2831 if (sym->st_shndx != text_shndx)
2832 error("invalid section for opcode (0x%x)", sym->st_shndx);
2833 #endif
2834 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2838 } else {
2839 /* generate big code generation switch */
2841 #ifdef HOST_ARM
2842 #error broken
2843 /* We need to know the size of all the ops so we can figure out when
2844 to emit constant pools. This must be consistent with opc.h. */
2845 fprintf(outfile,
2846 "static const uint32_t arm_opc_size[] = {\n"
2847 " 0,\n" /* end */
2848 " 0,\n" /* nop */
2849 " 0,\n" /* nop1 */
2850 " 0,\n" /* nop2 */
2851 " 0,\n"); /* nop3 */
2852 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2853 const char *name;
2854 name = get_sym_name(sym);
2855 if (strstart(name, OP_PREFIX, NULL)) {
2856 fprintf(outfile, " %d,\n", sym->st_size);
2859 fprintf(outfile,
2860 "};\n");
2861 #endif
2863 #ifdef HOST_ARM
2864 #error broken
2865 /* Arm is tricky because it uses constant pools for loading immediate values.
2866 We assume (and require) each function is code followed by a constant pool.
2867 All the ops are small so this should be ok. For each op we figure
2868 out how much "spare" range we have in the load instructions. This allows
2869 us to insert subsequent ops in between the op and the constant pool,
2870 eliminating the neeed to jump around the pool.
2872 We currently generate:
2874 [ For this example we assume merging would move op1_pool out of range.
2875 In practice we should be able to combine many ops before the offset
2876 limits are reached. ]
2877 op1_code;
2878 op2_code;
2879 goto op3;
2880 op2_pool;
2881 op1_pool;
2882 op3:
2883 op3_code;
2884 ret;
2885 op3_pool;
2887 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2889 fprintf(outfile,
2890 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2891 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2892 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2893 /* Initialise the parmissible pool offset to an arbitary large value. */
2894 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2895 #endif
2896 #ifdef HOST_IA64
2898 long addend, not_first = 0;
2899 unsigned long sym_idx;
2900 int index, max_index;
2901 const char *sym_name;
2902 EXE_RELOC *rel;
2904 max_index = -1;
2905 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2906 sym_idx = ELF64_R_SYM(rel->r_info);
2907 sym_name = (strtab + symtab[sym_idx].st_name);
2908 if (strstart(sym_name, "__op_gen_label", NULL))
2909 continue;
2910 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2911 continue;
2913 addend = rel->r_addend;
2914 index = get_plt_index(sym_name, addend);
2915 if (index <= max_index)
2916 continue;
2917 max_index = index;
2918 fprintf(outfile, " extern void %s(void);\n", sym_name);
2921 fprintf(outfile,
2922 " struct ia64_fixup *plt_fixes = NULL, "
2923 "*ltoff_fixes = NULL;\n"
2924 " static long plt_target[] = {\n\t");
2926 max_index = -1;
2927 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2928 sym_idx = ELF64_R_SYM(rel->r_info);
2929 sym_name = (strtab + symtab[sym_idx].st_name);
2930 if (strstart(sym_name, "__op_gen_label", NULL))
2931 continue;
2932 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2933 continue;
2935 addend = rel->r_addend;
2936 index = get_plt_index(sym_name, addend);
2937 if (index <= max_index)
2938 continue;
2939 max_index = index;
2941 if (not_first)
2942 fprintf(outfile, ",\n\t");
2943 not_first = 1;
2944 if (addend)
2945 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2946 else
2947 fprintf(outfile, "(long) &%s", sym_name);
2949 fprintf(outfile, "\n };\n"
2950 " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2952 #endif
2954 #ifdef HOST_ARM
2955 #error broken
2956 /* Generate constant pool if needed */
2957 fprintf(outfile,
2958 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2959 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2960 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2961 " last_gen_code_ptr = gen_code_ptr;\n"
2962 " arm_ldr_ptr = arm_ldr_table;\n"
2963 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2964 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2965 " }\n");
2966 #endif
2968 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2969 const char *name;
2970 name = get_sym_name(sym);
2971 if (strstart(name, OP_PREFIX, NULL)) {
2972 #if 0
2973 printf("%4d: %s pos=0x%08x len=%d\n",
2974 i, name, sym->st_value, sym->st_size);
2975 #endif
2976 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2977 if (sym->st_shndx != text_shndx)
2978 error("invalid section for opcode (0x%x)", sym->st_shndx);
2979 #endif
2980 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2985 return 0;
2988 void usage(void)
2990 printf("dyngen (c) 2003 Fabrice Bellard\n"
2991 "usage: dyngen [-o outfile] [-c] objfile\n"
2992 "Generate a dynamic code generator from an object file\n"
2993 "-c output enum of operations\n"
2994 "-g output gen_op_xx() functions\n"
2996 exit(1);
2999 int main(int argc, char **argv)
3001 int c, out_type;
3002 const char *filename, *outfilename;
3003 FILE *outfile;
3005 outfilename = "out.c";
3006 out_type = OUT_CODE;
3007 for(;;) {
3008 c = getopt(argc, argv, "ho:cg");
3009 if (c == -1)
3010 break;
3011 switch(c) {
3012 case 'h':
3013 usage();
3014 break;
3015 case 'o':
3016 outfilename = optarg;
3017 break;
3018 case 'c':
3019 out_type = OUT_INDEX_OP;
3020 break;
3021 case 'g':
3022 out_type = OUT_GEN_OP;
3023 break;
3026 if (optind >= argc)
3027 usage();
3028 filename = argv[optind];
3029 outfile = fopen(outfilename, "w");
3030 if (!outfile)
3031 error("could not open '%s'", outfilename);
3033 load_object(filename);
3034 gen_file(outfile, out_type);
3035 fclose(outfile);
3036 return 0;