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