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