Add ARM RealView Emulation Baseboard.
[qemu/mini2440.git] / dyngen.c
blob2d93283d67d30b0bf619d3fe0ff5d657b2982086
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 #else
131 typedef int64_t host_long;
132 typedef uint64_t host_ulong;
133 #define swabls(x) swab64s(x)
134 #endif
136 #ifdef ELF_USES_RELOCA
137 #define SHT_RELOC SHT_RELA
138 #else
139 #define SHT_RELOC SHT_REL
140 #endif
142 #define EXE_RELOC ELF_RELOC
143 #define EXE_SYM ElfW(Sym)
145 #endif /* CONFIG_FORMAT_ELF */
147 #ifdef CONFIG_FORMAT_COFF
149 #include "a.out.h"
151 typedef int32_t host_long;
152 typedef uint32_t host_ulong;
154 #define FILENAMELEN 256
156 typedef struct coff_sym {
157 struct external_syment *st_syment;
158 char st_name[FILENAMELEN];
159 uint32_t st_value;
160 int st_size;
161 uint8_t st_type;
162 uint8_t st_shndx;
163 } coff_Sym;
165 typedef struct coff_rel {
166 struct external_reloc *r_reloc;
167 int r_offset;
168 uint8_t r_type;
169 } coff_Rel;
171 #define EXE_RELOC struct coff_rel
172 #define EXE_SYM struct coff_sym
174 #endif /* CONFIG_FORMAT_COFF */
176 #ifdef CONFIG_FORMAT_MACH
178 #include <mach-o/loader.h>
179 #include <mach-o/nlist.h>
180 #include <mach-o/reloc.h>
181 #include <mach-o/ppc/reloc.h>
183 # define check_mach_header(x) (x.magic == MH_MAGIC)
184 typedef int32_t host_long;
185 typedef uint32_t host_ulong;
187 struct nlist_extended
189 union {
190 char *n_name;
191 long n_strx;
192 } n_un;
193 unsigned char n_type;
194 unsigned char n_sect;
195 short st_desc;
196 unsigned long st_value;
197 unsigned long st_size;
200 #define EXE_RELOC struct relocation_info
201 #define EXE_SYM struct nlist_extended
203 #endif /* CONFIG_FORMAT_MACH */
205 #include "bswap.h"
207 enum {
208 OUT_GEN_OP,
209 OUT_CODE,
210 OUT_INDEX_OP,
213 /* all dynamically generated functions begin with this code */
214 #define OP_PREFIX "op_"
216 int do_swap;
218 void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
220 va_list ap;
221 va_start(ap, fmt);
222 fprintf(stderr, "dyngen: ");
223 vfprintf(stderr, fmt, ap);
224 fprintf(stderr, "\n");
225 va_end(ap);
226 exit(1);
229 void *load_data(int fd, long offset, unsigned int size)
231 char *data;
233 data = malloc(size);
234 if (!data)
235 return NULL;
236 lseek(fd, offset, SEEK_SET);
237 if (read(fd, data, size) != size) {
238 free(data);
239 return NULL;
241 return data;
244 int strstart(const char *str, const char *val, const char **ptr)
246 const char *p, *q;
247 p = str;
248 q = val;
249 while (*q != '\0') {
250 if (*p != *q)
251 return 0;
252 p++;
253 q++;
255 if (ptr)
256 *ptr = p;
257 return 1;
260 void pstrcpy(char *buf, int buf_size, const char *str)
262 int c;
263 char *q = buf;
265 if (buf_size <= 0)
266 return;
268 for(;;) {
269 c = *str++;
270 if (c == 0 || q >= buf + buf_size - 1)
271 break;
272 *q++ = c;
274 *q = '\0';
277 void swab16s(uint16_t *p)
279 *p = bswap16(*p);
282 void swab32s(uint32_t *p)
284 *p = bswap32(*p);
287 void swab64s(uint64_t *p)
289 *p = bswap64(*p);
292 uint16_t get16(uint16_t *p)
294 uint16_t val;
295 val = *p;
296 if (do_swap)
297 val = bswap16(val);
298 return val;
301 uint32_t get32(uint32_t *p)
303 uint32_t val;
304 val = *p;
305 if (do_swap)
306 val = bswap32(val);
307 return val;
310 void put16(uint16_t *p, uint16_t val)
312 if (do_swap)
313 val = bswap16(val);
314 *p = val;
317 void put32(uint32_t *p, uint32_t val)
319 if (do_swap)
320 val = bswap32(val);
321 *p = val;
324 /* executable information */
325 EXE_SYM *symtab;
326 int nb_syms;
327 int text_shndx;
328 uint8_t *text;
329 EXE_RELOC *relocs;
330 int nb_relocs;
332 #ifdef CONFIG_FORMAT_ELF
334 /* ELF file info */
335 struct elf_shdr *shdr;
336 uint8_t **sdata;
337 struct elfhdr ehdr;
338 char *strtab;
340 int elf_must_swap(struct elfhdr *h)
342 union {
343 uint32_t i;
344 uint8_t b[4];
345 } swaptest;
347 swaptest.i = 1;
348 return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
349 (swaptest.b[0] == 0);
352 void elf_swap_ehdr(struct elfhdr *h)
354 swab16s(&h->e_type); /* Object file type */
355 swab16s(&h-> e_machine); /* Architecture */
356 swab32s(&h-> e_version); /* Object file version */
357 swabls(&h-> e_entry); /* Entry point virtual address */
358 swabls(&h-> e_phoff); /* Program header table file offset */
359 swabls(&h-> e_shoff); /* Section header table file offset */
360 swab32s(&h-> e_flags); /* Processor-specific flags */
361 swab16s(&h-> e_ehsize); /* ELF header size in bytes */
362 swab16s(&h-> e_phentsize); /* Program header table entry size */
363 swab16s(&h-> e_phnum); /* Program header table entry count */
364 swab16s(&h-> e_shentsize); /* Section header table entry size */
365 swab16s(&h-> e_shnum); /* Section header table entry count */
366 swab16s(&h-> e_shstrndx); /* Section header string table index */
369 void elf_swap_shdr(struct elf_shdr *h)
371 swab32s(&h-> sh_name); /* Section name (string tbl index) */
372 swab32s(&h-> sh_type); /* Section type */
373 swabls(&h-> sh_flags); /* Section flags */
374 swabls(&h-> sh_addr); /* Section virtual addr at execution */
375 swabls(&h-> sh_offset); /* Section file offset */
376 swabls(&h-> sh_size); /* Section size in bytes */
377 swab32s(&h-> sh_link); /* Link to another section */
378 swab32s(&h-> sh_info); /* Additional section information */
379 swabls(&h-> sh_addralign); /* Section alignment */
380 swabls(&h-> sh_entsize); /* Entry size if section holds table */
383 void elf_swap_phdr(struct elf_phdr *h)
385 swab32s(&h->p_type); /* Segment type */
386 swabls(&h->p_offset); /* Segment file offset */
387 swabls(&h->p_vaddr); /* Segment virtual address */
388 swabls(&h->p_paddr); /* Segment physical address */
389 swabls(&h->p_filesz); /* Segment size in file */
390 swabls(&h->p_memsz); /* Segment size in memory */
391 swab32s(&h->p_flags); /* Segment flags */
392 swabls(&h->p_align); /* Segment alignment */
395 void elf_swap_rel(ELF_RELOC *rel)
397 swabls(&rel->r_offset);
398 swabls(&rel->r_info);
399 #ifdef ELF_USES_RELOCA
400 swabls(&rel->r_addend);
401 #endif
404 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
405 const char *name)
407 int i;
408 const char *shname;
409 struct elf_shdr *sec;
411 for(i = 0; i < shnum; i++) {
412 sec = &shdr[i];
413 if (!sec->sh_name)
414 continue;
415 shname = shstr + sec->sh_name;
416 if (!strcmp(shname, name))
417 return sec;
419 return NULL;
422 int find_reloc(int sh_index)
424 struct elf_shdr *sec;
425 int i;
427 for(i = 0; i < ehdr.e_shnum; i++) {
428 sec = &shdr[i];
429 if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
430 return i;
432 return 0;
435 static host_ulong get_rel_offset(EXE_RELOC *rel)
437 return rel->r_offset;
440 static char *get_rel_sym_name(EXE_RELOC *rel)
442 return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
445 static char *get_sym_name(EXE_SYM *sym)
447 return strtab + sym->st_name;
450 /* load an elf object file */
451 int load_object(const char *filename)
453 int fd;
454 struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec;
455 int i, j;
456 ElfW(Sym) *sym;
457 char *shstr;
458 ELF_RELOC *rel;
460 fd = open(filename, O_RDONLY);
461 if (fd < 0)
462 error("can't open file '%s'", filename);
464 /* Read ELF header. */
465 if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
466 error("unable to read file header");
468 /* Check ELF identification. */
469 if (ehdr.e_ident[EI_MAG0] != ELFMAG0
470 || ehdr.e_ident[EI_MAG1] != ELFMAG1
471 || ehdr.e_ident[EI_MAG2] != ELFMAG2
472 || ehdr.e_ident[EI_MAG3] != ELFMAG3
473 || ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
474 error("bad ELF header");
477 do_swap = elf_must_swap(&ehdr);
478 if (do_swap)
479 elf_swap_ehdr(&ehdr);
480 if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
481 error("Unsupported ELF class");
482 if (ehdr.e_type != ET_REL)
483 error("ELF object file expected");
484 if (ehdr.e_version != EV_CURRENT)
485 error("Invalid ELF version");
486 if (!elf_check_arch(ehdr.e_machine))
487 error("Unsupported CPU (e_machine=%d)", ehdr.e_machine);
489 /* read section headers */
490 shdr = load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(struct elf_shdr));
491 if (do_swap) {
492 for(i = 0; i < ehdr.e_shnum; i++) {
493 elf_swap_shdr(&shdr[i]);
497 /* read all section data */
498 sdata = malloc(sizeof(void *) * ehdr.e_shnum);
499 memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
501 for(i = 0;i < ehdr.e_shnum; i++) {
502 sec = &shdr[i];
503 if (sec->sh_type != SHT_NOBITS)
504 sdata[i] = load_data(fd, sec->sh_offset, sec->sh_size);
507 sec = &shdr[ehdr.e_shstrndx];
508 shstr = sdata[ehdr.e_shstrndx];
510 /* swap relocations */
511 for(i = 0; i < ehdr.e_shnum; i++) {
512 sec = &shdr[i];
513 if (sec->sh_type == SHT_RELOC) {
514 nb_relocs = sec->sh_size / sec->sh_entsize;
515 if (do_swap) {
516 for(j = 0, rel = (ELF_RELOC *)sdata[i]; j < nb_relocs; j++, rel++)
517 elf_swap_rel(rel);
521 /* text section */
523 text_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".text");
524 if (!text_sec)
525 error("could not find .text section");
526 text_shndx = text_sec - shdr;
527 text = sdata[text_shndx];
529 /* find text relocations, if any */
530 relocs = NULL;
531 nb_relocs = 0;
532 i = find_reloc(text_shndx);
533 if (i != 0) {
534 relocs = (ELF_RELOC *)sdata[i];
535 nb_relocs = shdr[i].sh_size / shdr[i].sh_entsize;
538 symtab_sec = find_elf_section(shdr, ehdr.e_shnum, shstr, ".symtab");
539 if (!symtab_sec)
540 error("could not find .symtab section");
541 strtab_sec = &shdr[symtab_sec->sh_link];
543 symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
544 strtab = sdata[symtab_sec->sh_link];
546 nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
547 if (do_swap) {
548 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
549 swab32s(&sym->st_name);
550 swabls(&sym->st_value);
551 swabls(&sym->st_size);
552 swab16s(&sym->st_shndx);
555 close(fd);
556 return 0;
559 #endif /* CONFIG_FORMAT_ELF */
561 #ifdef CONFIG_FORMAT_COFF
563 /* COFF file info */
564 struct external_scnhdr *shdr;
565 uint8_t **sdata;
566 struct external_filehdr fhdr;
567 struct external_syment *coff_symtab;
568 char *strtab;
569 int coff_text_shndx, coff_data_shndx;
571 int data_shndx;
573 #define STRTAB_SIZE 4
575 #define DIR32 0x06
576 #define DISP32 0x14
578 #define T_FUNCTION 0x20
579 #define C_EXTERNAL 2
581 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
583 char *q;
584 int c, i, len;
586 if (ext_sym->e.e.e_zeroes != 0) {
587 q = sym->st_name;
588 for(i = 0; i < 8; i++) {
589 c = ext_sym->e.e_name[i];
590 if (c == '\0')
591 break;
592 *q++ = c;
594 *q = '\0';
595 } else {
596 pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
599 /* now convert the name to a C name (suppress the leading '_') */
600 if (sym->st_name[0] == '_') {
601 len = strlen(sym->st_name);
602 memmove(sym->st_name, sym->st_name + 1, len - 1);
603 sym->st_name[len - 1] = '\0';
607 char *name_for_dotdata(struct coff_rel *rel)
609 int i;
610 struct coff_sym *sym;
611 uint32_t text_data;
613 text_data = *(uint32_t *)(text + rel->r_offset);
615 for (i = 0, sym = symtab; i < nb_syms; i++, sym++) {
616 if (sym->st_syment->e_scnum == data_shndx &&
617 text_data >= sym->st_value &&
618 text_data < sym->st_value + sym->st_size) {
620 return sym->st_name;
624 return NULL;
627 static char *get_sym_name(EXE_SYM *sym)
629 return sym->st_name;
632 static char *get_rel_sym_name(EXE_RELOC *rel)
634 char *name;
635 name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
636 if (!strcmp(name, ".data"))
637 name = name_for_dotdata(rel);
638 if (name[0] == '.')
639 return NULL;
640 return name;
643 static host_ulong get_rel_offset(EXE_RELOC *rel)
645 return rel->r_offset;
648 struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
650 int i;
651 const char *shname;
652 struct external_scnhdr *sec;
654 for(i = 0; i < shnum; i++) {
655 sec = &shdr[i];
656 if (!sec->s_name)
657 continue;
658 shname = sec->s_name;
659 if (!strcmp(shname, name))
660 return sec;
662 return NULL;
665 /* load a coff object file */
666 int load_object(const char *filename)
668 int fd;
669 struct external_scnhdr *sec, *text_sec, *data_sec;
670 int i;
671 struct external_syment *ext_sym;
672 struct external_reloc *coff_relocs;
673 struct external_reloc *ext_rel;
674 uint32_t *n_strtab;
675 EXE_SYM *sym;
676 EXE_RELOC *rel;
678 fd = open(filename, O_RDONLY
679 #ifdef _WIN32
680 | O_BINARY
681 #endif
683 if (fd < 0)
684 error("can't open file '%s'", filename);
686 /* Read COFF header. */
687 if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
688 error("unable to read file header");
690 /* Check COFF identification. */
691 if (fhdr.f_magic != I386MAGIC) {
692 error("bad COFF header");
694 do_swap = 0;
696 /* read section headers */
697 shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
699 /* read all section data */
700 sdata = malloc(sizeof(void *) * fhdr.f_nscns);
701 memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
703 const char *p;
704 for(i = 0;i < fhdr.f_nscns; i++) {
705 sec = &shdr[i];
706 if (!strstart(sec->s_name, ".bss", &p))
707 sdata[i] = load_data(fd, sec->s_scnptr, sec->s_size);
711 /* text section */
712 text_sec = find_coff_section(shdr, fhdr.f_nscns, ".text");
713 if (!text_sec)
714 error("could not find .text section");
715 coff_text_shndx = text_sec - shdr;
716 text = sdata[coff_text_shndx];
718 /* data section */
719 data_sec = find_coff_section(shdr, fhdr.f_nscns, ".data");
720 if (!data_sec)
721 error("could not find .data section");
722 coff_data_shndx = data_sec - shdr;
724 coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
725 for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
726 for(i=0;i<8;i++)
727 printf(" %02x", ((uint8_t *)ext_sym->e.e_name)[i]);
728 printf("\n");
732 n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
733 strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
735 nb_syms = fhdr.f_nsyms;
737 for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
738 if (strstart(ext_sym->e.e_name, ".text", NULL))
739 text_shndx = ext_sym->e_scnum;
740 if (strstart(ext_sym->e.e_name, ".data", NULL))
741 data_shndx = ext_sym->e_scnum;
744 /* set coff symbol */
745 symtab = malloc(sizeof(struct coff_sym) * nb_syms);
747 int aux_size, j;
748 for (i = 0, ext_sym = coff_symtab, sym = symtab; i < nb_syms; i++, ext_sym++, sym++) {
749 memset(sym, 0, sizeof(*sym));
750 sym->st_syment = ext_sym;
751 sym_ent_name(ext_sym, sym);
752 sym->st_value = ext_sym->e_value;
754 aux_size = *(int8_t *)ext_sym->e_numaux;
755 if (ext_sym->e_scnum == text_shndx && ext_sym->e_type == T_FUNCTION) {
756 for (j = aux_size + 1; j < nb_syms - i; j++) {
757 if ((ext_sym + j)->e_scnum == text_shndx &&
758 (ext_sym + j)->e_type == T_FUNCTION ){
759 sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
760 break;
761 } else if (j == nb_syms - i - 1) {
762 sec = &shdr[coff_text_shndx];
763 sym->st_size = sec->s_size - ext_sym->e_value;
764 break;
767 } else if (ext_sym->e_scnum == data_shndx && *(uint8_t *)ext_sym->e_sclass == C_EXTERNAL) {
768 for (j = aux_size + 1; j < nb_syms - i; j++) {
769 if ((ext_sym + j)->e_scnum == data_shndx) {
770 sym->st_size = (ext_sym + j)->e_value - ext_sym->e_value;
771 break;
772 } else if (j == nb_syms - i - 1) {
773 sec = &shdr[coff_data_shndx];
774 sym->st_size = sec->s_size - ext_sym->e_value;
775 break;
778 } else {
779 sym->st_size = 0;
782 sym->st_type = ext_sym->e_type;
783 sym->st_shndx = ext_sym->e_scnum;
787 /* find text relocations, if any */
788 sec = &shdr[coff_text_shndx];
789 coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
790 nb_relocs = sec->s_nreloc;
792 /* set coff relocation */
793 relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
794 for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
795 i++, ext_rel++, rel++) {
796 memset(rel, 0, sizeof(*rel));
797 rel->r_reloc = ext_rel;
798 rel->r_offset = *(uint32_t *)ext_rel->r_vaddr;
799 rel->r_type = *(uint16_t *)ext_rel->r_type;
801 return 0;
804 #endif /* CONFIG_FORMAT_COFF */
806 #ifdef CONFIG_FORMAT_MACH
808 /* File Header */
809 struct mach_header mach_hdr;
811 /* commands */
812 struct segment_command *segment = 0;
813 struct dysymtab_command *dysymtabcmd = 0;
814 struct symtab_command *symtabcmd = 0;
816 /* section */
817 struct section *section_hdr;
818 struct section *text_sec_hdr;
819 uint8_t **sdata;
821 /* relocs */
822 struct relocation_info *relocs;
824 /* symbols */
825 EXE_SYM *symtab;
826 struct nlist *symtab_std;
827 char *strtab;
829 /* indirect symbols */
830 uint32_t *tocdylib;
832 /* Utility functions */
834 static inline char *find_str_by_index(int index)
836 return strtab+index;
839 /* Used by dyngen common code */
840 static char *get_sym_name(EXE_SYM *sym)
842 char *name = find_str_by_index(sym->n_un.n_strx);
844 if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
845 return "debug";
847 if(!name)
848 return name;
849 if(name[0]=='_')
850 return name + 1;
851 else
852 return name;
855 /* find a section index given its segname, sectname */
856 static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
857 const char *sectname)
859 int i;
860 struct section *sec = section_hdr;
862 for(i = 0; i < shnum; i++, sec++) {
863 if (!sec->segname || !sec->sectname)
864 continue;
865 if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname))
866 return i;
868 return -1;
871 /* find a section header given its segname, sectname */
872 struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
873 const char *sectname)
875 int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
876 if(index == -1)
877 return NULL;
878 return section_hdr+index;
882 static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
884 struct scattered_relocation_info * scarel;
886 if(R_SCATTERED & rel->r_address) {
887 scarel = (struct scattered_relocation_info*)rel;
888 if(scarel->r_type != PPC_RELOC_PAIR)
889 error("fetch_next_pair_value: looking for a pair which was not found (1)");
890 *value = scarel->r_value;
891 } else {
892 if(rel->r_type != PPC_RELOC_PAIR)
893 error("fetch_next_pair_value: looking for a pair which was not found (2)");
894 *value = rel->r_address;
898 /* find a sym name given its value, in a section number */
899 static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
901 int i, ret = -1;
903 for( i = 0 ; i < nb_syms; i++ )
905 if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
906 (symtab[i].n_sect == sectnum) && (symtab[i].st_value <= value) )
908 if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
909 ret = i;
912 if( ret < 0 ) {
913 *offset = 0;
914 return 0;
915 } else {
916 *offset = value - symtab[ret].st_value;
917 return get_sym_name(&symtab[ret]);
922 * Find symbol name given a (virtual) address, and a section which is of type
923 * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
925 static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
927 unsigned int tocindex, symindex, size;
928 const char *name = 0;
930 /* Sanity check */
931 if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
932 return (char*)0;
934 if( sec_hdr->flags & S_SYMBOL_STUBS ){
935 size = sec_hdr->reserved2;
936 if(size == 0)
937 error("size = 0");
940 else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
941 sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
942 size = sizeof(unsigned long);
943 else
944 return 0;
946 /* Compute our index in toc */
947 tocindex = (address - sec_hdr->addr)/size;
948 symindex = tocdylib[sec_hdr->reserved1 + tocindex];
950 name = get_sym_name(&symtab[symindex]);
952 return name;
955 static const char * find_reloc_name_given_its_address(int address)
957 unsigned int i;
958 for(i = 0; i < segment->nsects ; i++)
960 const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
961 if((long)name != -1)
962 return name;
964 return 0;
967 static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
969 char * name = 0;
970 struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
971 int sectnum = rel->r_symbolnum;
972 int sectoffset;
973 int other_half=0;
975 /* init the slide value */
976 *sslide = 0;
978 if(R_SCATTERED & rel->r_address)
979 return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
981 if(rel->r_extern)
983 /* ignore debug sym */
984 if ( symtab[rel->r_symbolnum].n_type & N_STAB )
985 return 0;
986 return get_sym_name(&symtab[rel->r_symbolnum]);
989 /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
990 sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
992 if(sectnum==0xffffff)
993 return 0;
995 /* Sanity Check */
996 if(sectnum > segment->nsects)
997 error("sectnum > segment->nsects");
999 switch(rel->r_type)
1001 case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16);
1002 break;
1003 case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff);
1004 break;
1005 case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff);
1006 break;
1007 case PPC_RELOC_BR24:
1008 sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc );
1009 if (sectoffset & 0x02000000) sectoffset |= 0xfc000000;
1010 break;
1011 default:
1012 error("switch(rel->type) not found");
1015 if(rel->r_pcrel)
1016 sectoffset += rel->r_address;
1018 if (rel->r_type == PPC_RELOC_BR24)
1019 name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1021 /* search it in the full symbol list, if not found */
1022 if(!name)
1023 name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
1025 return name;
1028 /* Used by dyngen common code */
1029 static const char * get_rel_sym_name(EXE_RELOC * rel)
1031 int sslide;
1032 return get_reloc_name( rel, &sslide);
1035 /* Used by dyngen common code */
1036 static host_ulong get_rel_offset(EXE_RELOC *rel)
1038 struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel;
1039 if(R_SCATTERED & rel->r_address)
1040 return sca_rel->r_address;
1041 else
1042 return rel->r_address;
1045 /* load a mach-o object file */
1046 int load_object(const char *filename)
1048 int fd;
1049 unsigned int offset_to_segment = 0;
1050 unsigned int offset_to_dysymtab = 0;
1051 unsigned int offset_to_symtab = 0;
1052 struct load_command lc;
1053 unsigned int i, j;
1054 EXE_SYM *sym;
1055 struct nlist *syment;
1057 fd = open(filename, O_RDONLY);
1058 if (fd < 0)
1059 error("can't open file '%s'", filename);
1061 /* Read Mach header. */
1062 if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1063 error("unable to read file header");
1065 /* Check Mach identification. */
1066 if (!check_mach_header(mach_hdr)) {
1067 error("bad Mach header");
1070 if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1071 error("Unsupported CPU");
1073 if (mach_hdr.filetype != MH_OBJECT)
1074 error("Unsupported Mach Object");
1076 /* read segment headers */
1077 for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1079 if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command))
1080 error("unable to read load_command");
1081 if(lc.cmd == LC_SEGMENT)
1083 offset_to_segment = j;
1084 lseek(fd, offset_to_segment, SEEK_SET);
1085 segment = malloc(sizeof(struct segment_command));
1086 if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command))
1087 error("unable to read LC_SEGMENT");
1089 if(lc.cmd == LC_DYSYMTAB)
1091 offset_to_dysymtab = j;
1092 lseek(fd, offset_to_dysymtab, SEEK_SET);
1093 dysymtabcmd = malloc(sizeof(struct dysymtab_command));
1094 if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command))
1095 error("unable to read LC_DYSYMTAB");
1097 if(lc.cmd == LC_SYMTAB)
1099 offset_to_symtab = j;
1100 lseek(fd, offset_to_symtab, SEEK_SET);
1101 symtabcmd = malloc(sizeof(struct symtab_command));
1102 if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command))
1103 error("unable to read LC_SYMTAB");
1105 j+=lc.cmdsize;
1107 lseek(fd, j, SEEK_SET);
1110 if(!segment)
1111 error("unable to find LC_SEGMENT");
1113 /* read section headers */
1114 section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1116 /* read all section data */
1117 sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1118 memset(sdata, 0, sizeof(void *) * segment->nsects);
1120 /* Load the data in section data */
1121 for(i = 0; i < segment->nsects; i++) {
1122 sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
1125 /* text section */
1126 text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1127 i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
1128 if (i == -1 || !text_sec_hdr)
1129 error("could not find __TEXT,__text section");
1130 text = sdata[i];
1132 /* Make sure dysym was loaded */
1133 if(!(int)dysymtabcmd)
1134 error("could not find __DYSYMTAB segment");
1136 /* read the table of content of the indirect sym */
1137 tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1139 /* Make sure symtab was loaded */
1140 if(!(int)symtabcmd)
1141 error("could not find __SYMTAB segment");
1142 nb_syms = symtabcmd->nsyms;
1144 symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1145 strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1147 symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1149 /* Now transform the symtab, to an extended version, with the sym size, and the C name */
1150 for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
1151 struct nlist *sym_follow, *sym_next = 0;
1152 unsigned int j;
1153 memset(sym, 0, sizeof(*sym));
1155 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1156 continue;
1158 memcpy(sym, syment, sizeof(*syment));
1160 /* Find the following symbol in order to get the current symbol size */
1161 for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
1162 if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
1163 continue;
1164 if(!sym_next) {
1165 sym_next = sym_follow;
1166 continue;
1168 if(!(sym_next->n_value > sym_follow->n_value))
1169 continue;
1170 sym_next = sym_follow;
1172 if(sym_next)
1173 sym->st_size = sym_next->n_value - sym->st_value;
1174 else
1175 sym->st_size = text_sec_hdr->size - sym->st_value;
1178 /* Find Reloc */
1179 relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
1180 nb_relocs = text_sec_hdr->nreloc;
1182 close(fd);
1183 return 0;
1186 #endif /* CONFIG_FORMAT_MACH */
1188 void get_reloc_expr(char *name, int name_size, const char *sym_name)
1190 const char *p;
1192 if (strstart(sym_name, "__op_param", &p)) {
1193 snprintf(name, name_size, "param%s", p);
1194 } else if (strstart(sym_name, "__op_gen_label", &p)) {
1195 snprintf(name, name_size, "gen_labels[param%s]", p);
1196 } else {
1197 #ifdef HOST_SPARC
1198 if (sym_name[0] == '.')
1199 snprintf(name, name_size,
1200 "(long)(&__dot_%s)",
1201 sym_name + 1);
1202 else
1203 #endif
1204 snprintf(name, name_size, "(long)(&%s)", sym_name);
1208 #ifdef HOST_IA64
1210 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1212 struct plt_entry {
1213 struct plt_entry *next;
1214 const char *name;
1215 unsigned long addend;
1216 } *plt_list;
1218 static int
1219 get_plt_index (const char *name, unsigned long addend)
1221 struct plt_entry *plt, *prev= NULL;
1222 int index = 0;
1224 /* see if we already have an entry for this target: */
1225 for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next)
1226 if (strcmp(plt->name, name) == 0 && plt->addend == addend)
1227 return index;
1229 /* nope; create a new PLT entry: */
1231 plt = malloc(sizeof(*plt));
1232 if (!plt) {
1233 perror("malloc");
1234 exit(1);
1236 memset(plt, 0, sizeof(*plt));
1237 plt->name = strdup(name);
1238 plt->addend = addend;
1240 /* append to plt-list: */
1241 if (prev)
1242 prev->next = plt;
1243 else
1244 plt_list = plt;
1245 return index;
1248 #endif
1250 #ifdef HOST_ARM
1252 int arm_emit_ldr_info(const char *name, unsigned long start_offset,
1253 FILE *outfile, uint8_t *p_start, uint8_t *p_end,
1254 ELF_RELOC *relocs, int nb_relocs)
1256 uint8_t *p;
1257 uint32_t insn;
1258 int offset, min_offset, pc_offset, data_size, spare, max_pool;
1259 uint8_t data_allocated[1024];
1260 unsigned int data_index;
1261 int type;
1263 memset(data_allocated, 0, sizeof(data_allocated));
1265 p = p_start;
1266 min_offset = p_end - p_start;
1267 spare = 0x7fffffff;
1268 while (p < p_start + min_offset) {
1269 insn = get32((uint32_t *)p);
1270 /* TODO: Armv5e ldrd. */
1271 /* TODO: VFP load. */
1272 if ((insn & 0x0d5f0000) == 0x051f0000) {
1273 /* ldr reg, [pc, #im] */
1274 offset = insn & 0xfff;
1275 if (!(insn & 0x00800000))
1276 offset = -offset;
1277 max_pool = 4096;
1278 type = 0;
1279 } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
1280 /* FPA ldf. */
1281 offset = (insn & 0xff) << 2;
1282 if (!(insn & 0x00800000))
1283 offset = -offset;
1284 max_pool = 1024;
1285 type = 1;
1286 } else if ((insn & 0x0fff0000) == 0x028f0000) {
1287 /* Some gcc load a doubleword immediate with
1288 add regN, pc, #imm
1289 ldmia regN, {regN, regM}
1290 Hope and pray the compiler never generates somethin like
1291 add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
1292 int r;
1294 r = (insn & 0xf00) >> 7;
1295 offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
1296 max_pool = 1024;
1297 type = 2;
1298 } else {
1299 max_pool = 0;
1300 type = -1;
1302 if (type >= 0) {
1303 /* PC-relative load needs fixing up. */
1304 if (spare > max_pool - offset)
1305 spare = max_pool - offset;
1306 if ((offset & 3) !=0)
1307 error("%s:%04x: pc offset must be 32 bit aligned",
1308 name, start_offset + p - p_start);
1309 if (offset < 0)
1310 error("%s:%04x: Embedded literal value",
1311 name, start_offset + p - p_start);
1312 pc_offset = p - p_start + offset + 8;
1313 if (pc_offset <= (p - p_start) ||
1314 pc_offset >= (p_end - p_start))
1315 error("%s:%04x: pc offset must point inside the function code",
1316 name, start_offset + p - p_start);
1317 if (pc_offset < min_offset)
1318 min_offset = pc_offset;
1319 if (outfile) {
1320 /* The intruction position */
1321 fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
1322 p - p_start);
1323 /* The position of the constant pool data. */
1324 data_index = ((p_end - p_start) - pc_offset) >> 2;
1325 fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
1326 data_index);
1327 fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
1328 fprintf(outfile, " arm_ldr_ptr++;\n");
1331 p += 4;
1334 /* Copy and relocate the constant pool data. */
1335 data_size = (p_end - p_start) - min_offset;
1336 if (data_size > 0 && outfile) {
1337 spare += min_offset;
1338 fprintf(outfile, " arm_data_ptr -= %d;\n", data_size >> 2);
1339 fprintf(outfile, " arm_pool_ptr -= %d;\n", data_size);
1340 fprintf(outfile, " if (arm_pool_ptr > gen_code_ptr + %d)\n"
1341 " arm_pool_ptr = gen_code_ptr + %d;\n",
1342 spare, spare);
1344 data_index = 0;
1345 for (pc_offset = min_offset;
1346 pc_offset < p_end - p_start;
1347 pc_offset += 4) {
1349 ELF_RELOC *rel;
1350 int i, addend, type;
1351 const char *sym_name;
1352 char relname[1024];
1354 /* data value */
1355 addend = get32((uint32_t *)(p_start + pc_offset));
1356 relname[0] = '\0';
1357 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1358 if (rel->r_offset == (pc_offset + start_offset)) {
1359 sym_name = get_rel_sym_name(rel);
1360 /* the compiler leave some unnecessary references to the code */
1361 get_reloc_expr(relname, sizeof(relname), sym_name);
1362 type = ELF32_R_TYPE(rel->r_info);
1363 if (type != R_ARM_ABS32)
1364 error("%s: unsupported data relocation", name);
1365 break;
1368 fprintf(outfile, " arm_data_ptr[%d] = 0x%x",
1369 data_index, addend);
1370 if (relname[0] != '\0')
1371 fprintf(outfile, " + %s", relname);
1372 fprintf(outfile, ";\n");
1374 data_index++;
1378 if (p == p_start)
1379 goto arm_ret_error;
1380 p -= 4;
1381 insn = get32((uint32_t *)p);
1382 /* The last instruction must be an ldm instruction. There are several
1383 forms generated by gcc:
1384 ldmib sp, {..., pc} (implies a sp adjustment of +4)
1385 ldmia sp, {..., pc}
1386 ldmea fp, {..., pc} */
1387 if ((insn & 0xffff8000) == 0xe99d8000) {
1388 if (outfile) {
1389 fprintf(outfile,
1390 " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
1391 p - p_start);
1393 p += 4;
1394 } else if ((insn & 0xffff8000) != 0xe89d8000
1395 && (insn & 0xffff8000) != 0xe91b8000) {
1396 arm_ret_error:
1397 if (!outfile)
1398 printf("%s: invalid epilog\n", name);
1400 return p - p_start;
1402 #endif
1405 #define MAX_ARGS 3
1407 /* generate op code */
1408 void gen_code(const char *name, host_ulong offset, host_ulong size,
1409 FILE *outfile, int gen_switch)
1411 int copy_size = 0;
1412 uint8_t *p_start, *p_end;
1413 host_ulong start_offset;
1414 int nb_args, i, n;
1415 uint8_t args_present[MAX_ARGS];
1416 const char *sym_name, *p;
1417 EXE_RELOC *rel;
1419 /* Compute exact size excluding prologue and epilogue instructions.
1420 * Increment start_offset to skip epilogue instructions, then compute
1421 * copy_size the indicate the size of the remaining instructions (in
1422 * bytes).
1424 p_start = text + offset;
1425 p_end = p_start + size;
1426 start_offset = offset;
1427 #if defined(HOST_I386) || defined(HOST_X86_64)
1428 #ifdef CONFIG_FORMAT_COFF
1430 uint8_t *p;
1431 p = p_end - 1;
1432 if (p == p_start)
1433 error("empty code for %s", name);
1434 while (*p != 0xc3) {
1435 p--;
1436 if (p <= p_start)
1437 error("ret or jmp expected at the end of %s", name);
1439 copy_size = p - p_start;
1441 #else
1443 int len;
1444 len = p_end - p_start;
1445 if (len == 0)
1446 error("empty code for %s", name);
1447 if (p_end[-1] == 0xc3) {
1448 len--;
1449 } else {
1450 error("ret or jmp expected at the end of %s", name);
1452 copy_size = len;
1454 #endif
1455 #elif defined(HOST_PPC)
1457 uint8_t *p;
1458 p = (void *)(p_end - 4);
1459 if (p == p_start)
1460 error("empty code for %s", name);
1461 if (get32((uint32_t *)p) != 0x4e800020)
1462 error("blr expected at the end of %s", name);
1463 copy_size = p - p_start;
1465 #elif defined(HOST_S390)
1467 uint8_t *p;
1468 p = (void *)(p_end - 2);
1469 if (p == p_start)
1470 error("empty code for %s", name);
1471 if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
1472 error("br %%r14 expected at the end of %s", name);
1473 copy_size = p - p_start;
1475 #elif defined(HOST_ALPHA)
1477 uint8_t *p;
1478 p = p_end - 4;
1479 #if 0
1480 /* XXX: check why it occurs */
1481 if (p == p_start)
1482 error("empty code for %s", name);
1483 #endif
1484 if (get32((uint32_t *)p) != 0x6bfa8001)
1485 error("ret expected at the end of %s", name);
1486 copy_size = p - p_start;
1488 #elif defined(HOST_IA64)
1490 uint8_t *p;
1491 p = (void *)(p_end - 4);
1492 if (p == p_start)
1493 error("empty code for %s", name);
1494 /* br.ret.sptk.many b0;; */
1495 /* 08 00 84 00 */
1496 if (get32((uint32_t *)p) != 0x00840008)
1497 error("br.ret.sptk.many b0;; expected at the end of %s", name);
1498 copy_size = p_end - p_start;
1500 #elif defined(HOST_SPARC)
1502 #define INSN_SAVE 0x9de3a000
1503 #define INSN_RET 0x81c7e008
1504 #define INSN_RETL 0x81c3e008
1505 #define INSN_RESTORE 0x81e80000
1506 #define INSN_RETURN 0x81cfe008
1507 #define INSN_NOP 0x01000000
1508 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1509 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1511 uint32_t start_insn, end_insn1, end_insn2;
1512 uint8_t *p;
1513 p = (void *)(p_end - 8);
1514 if (p <= p_start)
1515 error("empty code for %s", name);
1516 start_insn = get32((uint32_t *)(p_start + 0x0));
1517 end_insn1 = get32((uint32_t *)(p + 0x0));
1518 end_insn2 = get32((uint32_t *)(p + 0x4));
1519 if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1520 (start_insn & ~0x1fff) == INSN_ADD_SP) {
1521 p_start += 0x4;
1522 start_offset += 0x4;
1523 if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1524 /* SPARC v7: ret; restore; */ ;
1525 else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1526 /* SPARC v9: return; nop; */ ;
1527 else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1528 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1529 else
1531 error("ret; restore; not found at end of %s", name);
1532 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1534 } else {
1535 error("No save at the beginning of %s", name);
1537 #if 0
1538 /* Skip a preceeding nop, if present. */
1539 if (p > p_start) {
1540 skip_insn = get32((uint32_t *)(p - 0x4));
1541 if (skip_insn == INSN_NOP)
1542 p -= 4;
1544 #endif
1545 copy_size = p - p_start;
1547 #elif defined(HOST_SPARC64)
1549 #define INSN_SAVE 0x9de3a000
1550 #define INSN_RET 0x81c7e008
1551 #define INSN_RETL 0x81c3e008
1552 #define INSN_RESTORE 0x81e80000
1553 #define INSN_RETURN 0x81cfe008
1554 #define INSN_NOP 0x01000000
1555 #define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
1556 #define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
1558 uint32_t start_insn, end_insn1, end_insn2, skip_insn;
1559 uint8_t *p;
1560 p = (void *)(p_end - 8);
1561 #if 0
1562 /* XXX: check why it occurs */
1563 if (p <= p_start)
1564 error("empty code for %s", name);
1565 #endif
1566 start_insn = get32((uint32_t *)(p_start + 0x0));
1567 end_insn1 = get32((uint32_t *)(p + 0x0));
1568 end_insn2 = get32((uint32_t *)(p + 0x4));
1569 if (((start_insn & ~0x1fff) == INSN_SAVE) ||
1570 (start_insn & ~0x1fff) == INSN_ADD_SP) {
1571 p_start += 0x4;
1572 start_offset += 0x4;
1573 if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
1574 /* SPARC v7: ret; restore; */ ;
1575 else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
1576 /* SPARC v9: return; nop; */ ;
1577 else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
1578 /* SPARC v7: retl; sub %sp, nn, %sp; */ ;
1579 else
1581 error("ret; restore; not found at end of %s", name);
1582 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1584 } else {
1585 error("No save at the beginning of %s", name);
1588 /* Skip a preceeding nop, if present. */
1589 if (p > p_start) {
1590 skip_insn = get32((uint32_t *)(p - 0x4));
1591 if (skip_insn == 0x01000000)
1592 p -= 4;
1595 copy_size = p - p_start;
1597 #elif defined(HOST_ARM)
1599 uint32_t insn;
1601 if ((p_end - p_start) <= 16)
1602 error("%s: function too small", name);
1603 if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
1604 (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
1605 get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
1606 error("%s: invalid prolog", name);
1607 p_start += 12;
1608 start_offset += 12;
1609 insn = get32((uint32_t *)p_start);
1610 if ((insn & 0xffffff00) == 0xe24dd000) {
1611 /* Stack adjustment. Assume op uses the frame pointer. */
1612 p_start -= 4;
1613 start_offset -= 4;
1615 copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1616 relocs, nb_relocs);
1618 #elif defined(HOST_M68K)
1620 uint8_t *p;
1621 p = (void *)(p_end - 2);
1622 if (p == p_start)
1623 error("empty code for %s", name);
1624 // remove NOP's, probably added for alignment
1625 while ((get16((uint16_t *)p) == 0x4e71) &&
1626 (p>p_start))
1627 p -= 2;
1628 if (get16((uint16_t *)p) != 0x4e75)
1629 error("rts expected at the end of %s", name);
1630 copy_size = p - p_start;
1632 #else
1633 #error unsupported CPU
1634 #endif
1636 /* compute the number of arguments by looking at the relocations */
1637 for(i = 0;i < MAX_ARGS; i++)
1638 args_present[i] = 0;
1640 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1641 host_ulong offset = get_rel_offset(rel);
1642 if (offset >= start_offset &&
1643 offset < start_offset + (p_end - p_start)) {
1644 sym_name = get_rel_sym_name(rel);
1645 if(!sym_name)
1646 continue;
1647 if (strstart(sym_name, "__op_param", &p) ||
1648 strstart(sym_name, "__op_gen_label", &p)) {
1649 n = strtoul(p, NULL, 10);
1650 if (n > MAX_ARGS)
1651 error("too many arguments in %s", name);
1652 args_present[n - 1] = 1;
1657 nb_args = 0;
1658 while (nb_args < MAX_ARGS && args_present[nb_args])
1659 nb_args++;
1660 for(i = nb_args; i < MAX_ARGS; i++) {
1661 if (args_present[i])
1662 error("inconsistent argument numbering in %s", name);
1665 if (gen_switch == 2) {
1666 fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);
1667 } else if (gen_switch == 1) {
1669 /* output C code */
1670 fprintf(outfile, "case INDEX_%s: {\n", name);
1671 if (nb_args > 0) {
1672 fprintf(outfile, " long ");
1673 for(i = 0; i < nb_args; i++) {
1674 if (i != 0)
1675 fprintf(outfile, ", ");
1676 fprintf(outfile, "param%d", i + 1);
1678 fprintf(outfile, ";\n");
1680 #if defined(HOST_IA64)
1681 fprintf(outfile, " extern char %s;\n", name);
1682 #else
1683 fprintf(outfile, " extern void %s();\n", name);
1684 #endif
1686 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1687 host_ulong offset = get_rel_offset(rel);
1688 if (offset >= start_offset &&
1689 offset < start_offset + (p_end - p_start)) {
1690 sym_name = get_rel_sym_name(rel);
1691 if(!sym_name)
1692 continue;
1693 if (*sym_name &&
1694 !strstart(sym_name, "__op_param", NULL) &&
1695 !strstart(sym_name, "__op_jmp", NULL) &&
1696 !strstart(sym_name, "__op_gen_label", NULL)) {
1697 #if defined(HOST_SPARC)
1698 if (sym_name[0] == '.') {
1699 fprintf(outfile,
1700 "extern char __dot_%s __asm__(\"%s\");\n",
1701 sym_name+1, sym_name);
1702 continue;
1704 #endif
1705 #if defined(__APPLE__)
1706 /* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
1707 fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
1708 #elif defined(HOST_IA64)
1709 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
1711 * PCREL21 br.call targets generally
1712 * are out of range and need to go
1713 * through an "import stub".
1715 fprintf(outfile, " extern char %s;\n",
1716 sym_name);
1717 #else
1718 fprintf(outfile, "extern char %s;\n", sym_name);
1719 #endif
1724 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1725 name, (int)(start_offset - offset), copy_size);
1727 /* emit code offset information */
1729 EXE_SYM *sym;
1730 const char *sym_name, *p;
1731 unsigned long val;
1732 int n;
1734 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
1735 sym_name = get_sym_name(sym);
1736 if (strstart(sym_name, "__op_label", &p)) {
1737 uint8_t *ptr;
1738 unsigned long offset;
1740 /* test if the variable refers to a label inside
1741 the code we are generating */
1742 #ifdef CONFIG_FORMAT_COFF
1743 if (sym->st_shndx == text_shndx) {
1744 ptr = sdata[coff_text_shndx];
1745 } else if (sym->st_shndx == data_shndx) {
1746 ptr = sdata[coff_data_shndx];
1747 } else {
1748 ptr = NULL;
1750 #elif defined(CONFIG_FORMAT_MACH)
1751 if(!sym->n_sect)
1752 continue;
1753 ptr = sdata[sym->n_sect-1];
1754 #else
1755 ptr = sdata[sym->st_shndx];
1756 #endif
1757 if (!ptr)
1758 error("__op_labelN in invalid section");
1759 offset = sym->st_value;
1760 #ifdef CONFIG_FORMAT_MACH
1761 offset -= section_hdr[sym->n_sect-1].addr;
1762 #endif
1763 val = *(unsigned long *)(ptr + offset);
1764 #ifdef ELF_USES_RELOCA
1766 int reloc_shndx, nb_relocs1, j;
1768 /* try to find a matching relocation */
1769 reloc_shndx = find_reloc(sym->st_shndx);
1770 if (reloc_shndx) {
1771 nb_relocs1 = shdr[reloc_shndx].sh_size /
1772 shdr[reloc_shndx].sh_entsize;
1773 rel = (ELF_RELOC *)sdata[reloc_shndx];
1774 for(j = 0; j < nb_relocs1; j++) {
1775 if (rel->r_offset == offset) {
1776 val = rel->r_addend;
1777 break;
1779 rel++;
1783 #endif
1784 if (val >= start_offset && val <= start_offset + copy_size) {
1785 n = strtol(p, NULL, 10);
1786 fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
1792 /* load parameres in variables */
1793 for(i = 0; i < nb_args; i++) {
1794 fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
1797 /* patch relocations */
1798 #if defined(HOST_I386)
1800 char name[256];
1801 int type;
1802 int addend;
1803 int reloc_offset;
1804 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1805 if (rel->r_offset >= start_offset &&
1806 rel->r_offset < start_offset + copy_size) {
1807 sym_name = get_rel_sym_name(rel);
1808 if (!sym_name)
1809 continue;
1810 reloc_offset = rel->r_offset - start_offset;
1811 if (strstart(sym_name, "__op_jmp", &p)) {
1812 int n;
1813 n = strtol(p, NULL, 10);
1814 /* __op_jmp relocations are done at
1815 runtime to do translated block
1816 chaining: the offset of the instruction
1817 needs to be stored */
1818 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1819 n, reloc_offset);
1820 continue;
1823 get_reloc_expr(name, sizeof(name), sym_name);
1824 addend = get32((uint32_t *)(text + rel->r_offset));
1825 #ifdef CONFIG_FORMAT_ELF
1826 type = ELF32_R_TYPE(rel->r_info);
1827 switch(type) {
1828 case R_386_32:
1829 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1830 reloc_offset, name, addend);
1831 break;
1832 case R_386_PC32:
1833 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1834 reloc_offset, name, reloc_offset, addend);
1835 break;
1836 default:
1837 error("unsupported i386 relocation (%d)", type);
1839 #elif defined(CONFIG_FORMAT_COFF)
1841 char *temp_name;
1842 int j;
1843 EXE_SYM *sym;
1844 temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx));
1845 if (!strcmp(temp_name, ".data")) {
1846 for (j = 0, sym = symtab; j < nb_syms; j++, sym++) {
1847 if (strstart(sym->st_name, sym_name, NULL)) {
1848 addend -= sym->st_value;
1853 type = rel->r_type;
1854 switch(type) {
1855 case DIR32:
1856 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1857 reloc_offset, name, addend);
1858 break;
1859 case DISP32:
1860 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1861 reloc_offset, name, reloc_offset, addend);
1862 break;
1863 default:
1864 error("unsupported i386 relocation (%d)", type);
1866 #else
1867 #error unsupport object format
1868 #endif
1872 #elif defined(HOST_X86_64)
1874 char name[256];
1875 int type;
1876 int addend;
1877 int reloc_offset;
1878 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1879 if (rel->r_offset >= start_offset &&
1880 rel->r_offset < start_offset + copy_size) {
1881 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1882 get_reloc_expr(name, sizeof(name), sym_name);
1883 type = ELF32_R_TYPE(rel->r_info);
1884 addend = rel->r_addend;
1885 reloc_offset = rel->r_offset - start_offset;
1886 switch(type) {
1887 case R_X86_64_32:
1888 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1889 reloc_offset, name, addend);
1890 break;
1891 case R_X86_64_32S:
1892 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1893 reloc_offset, name, addend);
1894 break;
1895 case R_X86_64_PC32:
1896 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1897 reloc_offset, name, reloc_offset, addend);
1898 break;
1899 default:
1900 error("unsupported X86_64 relocation (%d)", type);
1905 #elif defined(HOST_PPC)
1907 #ifdef CONFIG_FORMAT_ELF
1908 char name[256];
1909 int type;
1910 int addend;
1911 int reloc_offset;
1912 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1913 if (rel->r_offset >= start_offset &&
1914 rel->r_offset < start_offset + copy_size) {
1915 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1916 reloc_offset = rel->r_offset - start_offset;
1917 if (strstart(sym_name, "__op_jmp", &p)) {
1918 int n;
1919 n = strtol(p, NULL, 10);
1920 /* __op_jmp relocations are done at
1921 runtime to do translated block
1922 chaining: the offset of the instruction
1923 needs to be stored */
1924 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
1925 n, reloc_offset);
1926 continue;
1929 get_reloc_expr(name, sizeof(name), sym_name);
1930 type = ELF32_R_TYPE(rel->r_info);
1931 addend = rel->r_addend;
1932 switch(type) {
1933 case R_PPC_ADDR32:
1934 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1935 reloc_offset, name, addend);
1936 break;
1937 case R_PPC_ADDR16_LO:
1938 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1939 reloc_offset, name, addend);
1940 break;
1941 case R_PPC_ADDR16_HI:
1942 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1943 reloc_offset, name, addend);
1944 break;
1945 case R_PPC_ADDR16_HA:
1946 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1947 reloc_offset, name, addend);
1948 break;
1949 case R_PPC_REL24:
1950 /* warning: must be at 32 MB distancy */
1951 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
1952 reloc_offset, reloc_offset, name, reloc_offset, addend);
1953 break;
1954 default:
1955 error("unsupported powerpc relocation (%d)", type);
1959 #elif defined(CONFIG_FORMAT_MACH)
1960 struct scattered_relocation_info *scarel;
1961 struct relocation_info * rel;
1962 char final_sym_name[256];
1963 const char *sym_name;
1964 const char *p;
1965 int slide, sslide;
1966 int i;
1968 for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
1969 unsigned int offset, length, value = 0;
1970 unsigned int type, pcrel, isym = 0;
1971 unsigned int usesym = 0;
1973 if(R_SCATTERED & rel->r_address) {
1974 scarel = (struct scattered_relocation_info*)rel;
1975 offset = (unsigned int)scarel->r_address;
1976 length = scarel->r_length;
1977 pcrel = scarel->r_pcrel;
1978 type = scarel->r_type;
1979 value = scarel->r_value;
1980 } else {
1981 value = isym = rel->r_symbolnum;
1982 usesym = (rel->r_extern);
1983 offset = rel->r_address;
1984 length = rel->r_length;
1985 pcrel = rel->r_pcrel;
1986 type = rel->r_type;
1989 slide = offset - start_offset;
1991 if (!(offset >= start_offset && offset < start_offset + size))
1992 continue; /* not in our range */
1994 sym_name = get_reloc_name(rel, &sslide);
1996 if(usesym && symtab[isym].n_type & N_STAB)
1997 continue; /* don't handle STAB (debug sym) */
1999 if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
2000 int n;
2001 n = strtol(p, NULL, 10);
2002 fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
2003 n, slide);
2004 continue; /* Nothing more to do */
2007 if(!sym_name)
2009 fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
2010 name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
2011 continue; /* dunno how to handle without final_sym_name */
2014 get_reloc_expr(final_sym_name, sizeof(final_sym_name),
2015 sym_name);
2016 switch(type) {
2017 case PPC_RELOC_BR24:
2018 if (!strstart(sym_name,"__op_gen_label",&p)) {
2019 fprintf(outfile, "{\n");
2020 fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
2021 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",
2022 slide, slide, name, sslide );
2023 fprintf(outfile, "}\n");
2024 } else {
2025 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
2026 slide, slide, final_sym_name, slide);
2028 break;
2029 case PPC_RELOC_HI16:
2030 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
2031 slide, final_sym_name, sslide);
2032 break;
2033 case PPC_RELOC_LO16:
2034 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
2035 slide, final_sym_name, sslide);
2036 break;
2037 case PPC_RELOC_HA16:
2038 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
2039 slide, final_sym_name, sslide);
2040 break;
2041 default:
2042 error("unsupported powerpc relocation (%d)", type);
2045 #else
2046 #error unsupport object format
2047 #endif
2049 #elif defined(HOST_S390)
2051 char name[256];
2052 int type;
2053 int addend;
2054 int reloc_offset;
2055 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2056 if (rel->r_offset >= start_offset &&
2057 rel->r_offset < start_offset + copy_size) {
2058 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2059 get_reloc_expr(name, sizeof(name), sym_name);
2060 type = ELF32_R_TYPE(rel->r_info);
2061 addend = rel->r_addend;
2062 reloc_offset = rel->r_offset - start_offset;
2063 switch(type) {
2064 case R_390_32:
2065 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2066 reloc_offset, name, addend);
2067 break;
2068 case R_390_16:
2069 fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
2070 reloc_offset, name, addend);
2071 break;
2072 case R_390_8:
2073 fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
2074 reloc_offset, name, addend);
2075 break;
2076 default:
2077 error("unsupported s390 relocation (%d)", type);
2082 #elif defined(HOST_ALPHA)
2084 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
2085 if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
2086 int type;
2087 long reloc_offset;
2089 type = ELF64_R_TYPE(rel->r_info);
2090 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2091 reloc_offset = rel->r_offset - start_offset;
2092 switch (type) {
2093 case R_ALPHA_GPDISP:
2094 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
2095 as an immediate instead of constructing it from the pv or ra. */
2096 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
2097 reloc_offset);
2098 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
2099 reloc_offset + (int)rel->r_addend);
2100 break;
2101 case R_ALPHA_LITUSE:
2102 /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
2103 now, since some called functions (libc) need pv to be set up. */
2104 break;
2105 case R_ALPHA_HINT:
2106 /* Branch target prediction hint. Ignore for now. Should be already
2107 correct for in-function jumps. */
2108 break;
2109 case R_ALPHA_LITERAL:
2110 /* Load a literal from the GOT relative to the gp. Since there's only a
2111 single gp, nothing is to be done. */
2112 break;
2113 case R_ALPHA_GPRELHIGH:
2114 /* Handle fake relocations against __op_param symbol. Need to emit the
2115 high part of the immediate value instead. Other symbols need no
2116 special treatment. */
2117 if (strstart(sym_name, "__op_param", &p))
2118 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
2119 reloc_offset, p);
2120 break;
2121 case R_ALPHA_GPRELLOW:
2122 if (strstart(sym_name, "__op_param", &p))
2123 fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
2124 reloc_offset, p);
2125 break;
2126 case R_ALPHA_BRSGP:
2127 /* PC-relative jump. Tweak offset to skip the two instructions that try to
2128 set up the gp from the pv. */
2129 fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n",
2130 reloc_offset, sym_name, reloc_offset);
2131 break;
2132 default:
2133 error("unsupported Alpha relocation (%d)", type);
2138 #elif defined(HOST_IA64)
2140 unsigned long sym_idx;
2141 long code_offset;
2142 char name[256];
2143 int type;
2144 long addend;
2146 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2147 sym_idx = ELF64_R_SYM(rel->r_info);
2148 if (rel->r_offset < start_offset
2149 || rel->r_offset >= start_offset + copy_size)
2150 continue;
2151 sym_name = (strtab + symtab[sym_idx].st_name);
2152 code_offset = rel->r_offset - start_offset;
2153 if (strstart(sym_name, "__op_jmp", &p)) {
2154 int n;
2155 n = strtol(p, NULL, 10);
2156 /* __op_jmp relocations are done at
2157 runtime to do translated block
2158 chaining: the offset of the instruction
2159 needs to be stored */
2160 fprintf(outfile, " jmp_offsets[%d] ="
2161 "%ld + (gen_code_ptr - gen_code_buf);\n",
2162 n, code_offset);
2163 continue;
2165 get_reloc_expr(name, sizeof(name), sym_name);
2166 type = ELF64_R_TYPE(rel->r_info);
2167 addend = rel->r_addend;
2168 switch(type) {
2169 case R_IA64_IMM64:
2170 fprintf(outfile,
2171 " ia64_imm64(gen_code_ptr + %ld, "
2172 "%s + %ld);\n",
2173 code_offset, name, addend);
2174 break;
2175 case R_IA64_LTOFF22X:
2176 case R_IA64_LTOFF22:
2177 fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
2178 " %s + %ld, %d);\n",
2179 code_offset, name, addend,
2180 (type == R_IA64_LTOFF22X));
2181 break;
2182 case R_IA64_LDXMOV:
2183 fprintf(outfile,
2184 " ia64_ldxmov(gen_code_ptr + %ld,"
2185 " %s + %ld);\n", code_offset, name, addend);
2186 break;
2188 case R_IA64_PCREL21B:
2189 if (strstart(sym_name, "__op_gen_label", NULL)) {
2190 fprintf(outfile,
2191 " ia64_imm21b(gen_code_ptr + %ld,"
2192 " (long) (%s + %ld -\n\t\t"
2193 "((long) gen_code_ptr + %ld)) >> 4);\n",
2194 code_offset, name, addend,
2195 code_offset & ~0xfUL);
2196 } else {
2197 fprintf(outfile,
2198 " IA64_PLT(gen_code_ptr + %ld, "
2199 "%d);\t/* %s + %ld */\n",
2200 code_offset,
2201 get_plt_index(sym_name, addend),
2202 sym_name, addend);
2204 break;
2205 default:
2206 error("unsupported ia64 relocation (0x%x)",
2207 type);
2210 fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2211 copy_size - 16 + 2);
2213 #elif defined(HOST_SPARC)
2215 char name[256];
2216 int type;
2217 int addend;
2218 int reloc_offset;
2219 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2220 if (rel->r_offset >= start_offset &&
2221 rel->r_offset < start_offset + copy_size) {
2222 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
2223 get_reloc_expr(name, sizeof(name), sym_name);
2224 type = ELF32_R_TYPE(rel->r_info);
2225 addend = rel->r_addend;
2226 reloc_offset = rel->r_offset - start_offset;
2227 switch(type) {
2228 case R_SPARC_32:
2229 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2230 reloc_offset, name, addend);
2231 break;
2232 case R_SPARC_HI22:
2233 fprintf(outfile,
2234 " *(uint32_t *)(gen_code_ptr + %d) = "
2235 "((*(uint32_t *)(gen_code_ptr + %d)) "
2236 " & ~0x3fffff) "
2237 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2238 reloc_offset, reloc_offset, name, addend);
2239 break;
2240 case R_SPARC_LO10:
2241 fprintf(outfile,
2242 " *(uint32_t *)(gen_code_ptr + %d) = "
2243 "((*(uint32_t *)(gen_code_ptr + %d)) "
2244 " & ~0x3ff) "
2245 " | ((%s + %d) & 0x3ff);\n",
2246 reloc_offset, reloc_offset, name, addend);
2247 break;
2248 case R_SPARC_WDISP30:
2249 fprintf(outfile,
2250 " *(uint32_t *)(gen_code_ptr + %d) = "
2251 "((*(uint32_t *)(gen_code_ptr + %d)) "
2252 " & ~0x3fffffff) "
2253 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2254 " & 0x3fffffff);\n",
2255 reloc_offset, reloc_offset, name, addend,
2256 reloc_offset);
2257 break;
2258 case R_SPARC_WDISP22:
2259 fprintf(outfile,
2260 " *(uint32_t *)(gen_code_ptr + %d) = "
2261 "((*(uint32_t *)(gen_code_ptr + %d)) "
2262 " & ~0x3fffff) "
2263 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2264 " & 0x3fffff);\n",
2265 rel->r_offset - start_offset,
2266 rel->r_offset - start_offset,
2267 name, addend,
2268 rel->r_offset - start_offset);
2269 break;
2270 default:
2271 error("unsupported sparc relocation (%d)", type);
2276 #elif defined(HOST_SPARC64)
2278 char name[256];
2279 int type;
2280 int addend;
2281 int reloc_offset;
2282 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2283 if (rel->r_offset >= start_offset &&
2284 rel->r_offset < start_offset + copy_size) {
2285 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
2286 get_reloc_expr(name, sizeof(name), sym_name);
2287 type = ELF32_R_TYPE(rel->r_info);
2288 addend = rel->r_addend;
2289 reloc_offset = rel->r_offset - start_offset;
2290 switch(type) {
2291 case R_SPARC_32:
2292 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2293 reloc_offset, name, addend);
2294 break;
2295 case R_SPARC_HI22:
2296 fprintf(outfile,
2297 " *(uint32_t *)(gen_code_ptr + %d) = "
2298 "((*(uint32_t *)(gen_code_ptr + %d)) "
2299 " & ~0x3fffff) "
2300 " | (((%s + %d) >> 10) & 0x3fffff);\n",
2301 reloc_offset, reloc_offset, name, addend);
2302 break;
2303 case R_SPARC_LO10:
2304 fprintf(outfile,
2305 " *(uint32_t *)(gen_code_ptr + %d) = "
2306 "((*(uint32_t *)(gen_code_ptr + %d)) "
2307 " & ~0x3ff) "
2308 " | ((%s + %d) & 0x3ff);\n",
2309 reloc_offset, reloc_offset, name, addend);
2310 break;
2311 case R_SPARC_OLO10:
2312 addend += ELF64_R_TYPE_DATA (rel->r_info);
2313 fprintf(outfile,
2314 " *(uint32_t *)(gen_code_ptr + %d) = "
2315 "((*(uint32_t *)(gen_code_ptr + %d)) "
2316 " & ~0x3ff) "
2317 " | ((%s + %d) & 0x3ff);\n",
2318 reloc_offset, reloc_offset, name, addend);
2319 break;
2320 case R_SPARC_WDISP30:
2321 fprintf(outfile,
2322 " *(uint32_t *)(gen_code_ptr + %d) = "
2323 "((*(uint32_t *)(gen_code_ptr + %d)) "
2324 " & ~0x3fffffff) "
2325 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2326 " & 0x3fffffff);\n",
2327 reloc_offset, reloc_offset, name, addend,
2328 reloc_offset);
2329 break;
2330 case R_SPARC_WDISP22:
2331 fprintf(outfile,
2332 " *(uint32_t *)(gen_code_ptr + %d) = "
2333 "((*(uint32_t *)(gen_code_ptr + %d)) "
2334 " & ~0x3fffff) "
2335 " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
2336 " & 0x3fffff);\n",
2337 reloc_offset, reloc_offset, name, addend,
2338 reloc_offset);
2339 break;
2340 default:
2341 error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
2346 #elif defined(HOST_ARM)
2348 char name[256];
2349 int type;
2350 int addend;
2351 int reloc_offset;
2352 uint32_t insn;
2354 insn = get32((uint32_t *)(p_start + 4));
2355 /* If prologue ends in sub sp, sp, #const then assume
2356 op has a stack frame and needs the frame pointer. */
2357 if ((insn & 0xffffff00) == 0xe24dd000) {
2358 int i;
2359 uint32_t opcode;
2360 opcode = 0xe28db000; /* add fp, sp, #0. */
2361 #if 0
2362 /* ??? Need to undo the extra stack adjustment at the end of the op.
2363 For now just leave the stack misaligned and hope it doesn't break anything
2364 too important. */
2365 if ((insn & 4) != 0) {
2366 /* Preserve doubleword stack alignment. */
2367 fprintf(outfile,
2368 " *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
2369 insn + 4);
2370 opcode -= 4;
2372 #endif
2373 insn = get32((uint32_t *)(p_start - 4));
2374 /* Calculate the size of the saved registers,
2375 excluding pc. */
2376 for (i = 0; i < 15; i++) {
2377 if (insn & (1 << i))
2378 opcode += 4;
2380 fprintf(outfile,
2381 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2383 arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
2384 relocs, nb_relocs);
2386 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2387 if (rel->r_offset >= start_offset &&
2388 rel->r_offset < start_offset + copy_size) {
2389 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2390 /* the compiler leave some unnecessary references to the code */
2391 if (sym_name[0] == '\0')
2392 continue;
2393 get_reloc_expr(name, sizeof(name), sym_name);
2394 type = ELF32_R_TYPE(rel->r_info);
2395 addend = get32((uint32_t *)(text + rel->r_offset));
2396 reloc_offset = rel->r_offset - start_offset;
2397 switch(type) {
2398 case R_ARM_ABS32:
2399 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
2400 reloc_offset, name, addend);
2401 break;
2402 case R_ARM_PC24:
2403 case R_ARM_JUMP24:
2404 case R_ARM_CALL:
2405 fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
2406 reloc_offset, addend, name);
2407 break;
2408 default:
2409 error("unsupported arm relocation (%d)", type);
2414 #elif defined(HOST_M68K)
2416 char name[256];
2417 int type;
2418 int addend;
2419 int reloc_offset;
2420 Elf32_Sym *sym;
2421 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2422 if (rel->r_offset >= start_offset &&
2423 rel->r_offset < start_offset + copy_size) {
2424 sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
2425 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
2426 get_reloc_expr(name, sizeof(name), sym_name);
2427 type = ELF32_R_TYPE(rel->r_info);
2428 addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
2429 reloc_offset = rel->r_offset - start_offset;
2430 switch(type) {
2431 case R_68K_32:
2432 fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
2433 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
2434 reloc_offset, name, addend );
2435 break;
2436 case R_68K_PC32:
2437 fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
2438 fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
2439 reloc_offset, name, reloc_offset, /*sym->st_value+*/ addend);
2440 break;
2441 default:
2442 error("unsupported m68k relocation (%d)", type);
2447 #else
2448 #error unsupported CPU
2449 #endif
2450 fprintf(outfile, " gen_code_ptr += %d;\n", copy_size);
2451 fprintf(outfile, "}\n");
2452 fprintf(outfile, "break;\n\n");
2453 } else {
2454 fprintf(outfile, "static inline void gen_%s(", name);
2455 if (nb_args == 0) {
2456 fprintf(outfile, "void");
2457 } else {
2458 for(i = 0; i < nb_args; i++) {
2459 if (i != 0)
2460 fprintf(outfile, ", ");
2461 fprintf(outfile, "long param%d", i + 1);
2464 fprintf(outfile, ")\n");
2465 fprintf(outfile, "{\n");
2466 for(i = 0; i < nb_args; i++) {
2467 fprintf(outfile, " *gen_opparam_ptr++ = param%d;\n", i + 1);
2469 fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2470 fprintf(outfile, "}\n\n");
2474 int gen_file(FILE *outfile, int out_type)
2476 int i;
2477 EXE_SYM *sym;
2479 if (out_type == OUT_INDEX_OP) {
2480 fprintf(outfile, "DEF(end, 0, 0)\n");
2481 fprintf(outfile, "DEF(nop, 0, 0)\n");
2482 fprintf(outfile, "DEF(nop1, 1, 0)\n");
2483 fprintf(outfile, "DEF(nop2, 2, 0)\n");
2484 fprintf(outfile, "DEF(nop3, 3, 0)\n");
2485 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2486 const char *name;
2487 name = get_sym_name(sym);
2488 if (strstart(name, OP_PREFIX, NULL)) {
2489 gen_code(name, sym->st_value, sym->st_size, outfile, 2);
2492 } else if (out_type == OUT_GEN_OP) {
2493 /* generate gen_xxx functions */
2494 fprintf(outfile, "#include \"dyngen-op.h\"\n");
2495 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2496 const char *name;
2497 name = get_sym_name(sym);
2498 if (strstart(name, OP_PREFIX, NULL)) {
2499 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2500 if (sym->st_shndx != text_shndx)
2501 error("invalid section for opcode (0x%x)", sym->st_shndx);
2502 #endif
2503 gen_code(name, sym->st_value, sym->st_size, outfile, 0);
2507 } else {
2508 /* generate big code generation switch */
2510 #ifdef HOST_ARM
2511 /* We need to know the size of all the ops so we can figure out when
2512 to emit constant pools. This must be consistent with opc.h. */
2513 fprintf(outfile,
2514 "static const uint32_t arm_opc_size[] = {\n"
2515 " 0,\n" /* end */
2516 " 0,\n" /* nop */
2517 " 0,\n" /* nop1 */
2518 " 0,\n" /* nop2 */
2519 " 0,\n"); /* nop3 */
2520 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2521 const char *name;
2522 name = get_sym_name(sym);
2523 if (strstart(name, OP_PREFIX, NULL)) {
2524 fprintf(outfile, " %d,\n", sym->st_size);
2527 fprintf(outfile,
2528 "};\n");
2529 #endif
2531 fprintf(outfile,
2532 "int dyngen_code(uint8_t *gen_code_buf,\n"
2533 " uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2534 " const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2535 "{\n"
2536 " uint8_t *gen_code_ptr;\n"
2537 " const uint16_t *opc_ptr;\n"
2538 " const uint32_t *opparam_ptr;\n");
2540 #ifdef HOST_ARM
2541 /* Arm is tricky because it uses constant pools for loading immediate values.
2542 We assume (and require) each function is code followed by a constant pool.
2543 All the ops are small so this should be ok. For each op we figure
2544 out how much "spare" range we have in the load instructions. This allows
2545 us to insert subsequent ops in between the op and the constant pool,
2546 eliminating the neeed to jump around the pool.
2548 We currently generate:
2550 [ For this example we assume merging would move op1_pool out of range.
2551 In practice we should be able to combine many ops before the offset
2552 limits are reached. ]
2553 op1_code;
2554 op2_code;
2555 goto op3;
2556 op2_pool;
2557 op1_pool;
2558 op3:
2559 op3_code;
2560 ret;
2561 op3_pool;
2563 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2565 fprintf(outfile,
2566 " uint8_t *last_gen_code_ptr = gen_code_buf;\n"
2567 " LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
2568 " uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2569 /* Initialise the parmissible pool offset to an arbitary large value. */
2570 " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
2571 #endif
2572 #ifdef HOST_IA64
2574 long addend, not_first = 0;
2575 unsigned long sym_idx;
2576 int index, max_index;
2577 const char *sym_name;
2578 EXE_RELOC *rel;
2580 max_index = -1;
2581 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2582 sym_idx = ELF64_R_SYM(rel->r_info);
2583 sym_name = (strtab + symtab[sym_idx].st_name);
2584 if (strstart(sym_name, "__op_gen_label", NULL))
2585 continue;
2586 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2587 continue;
2589 addend = rel->r_addend;
2590 index = get_plt_index(sym_name, addend);
2591 if (index <= max_index)
2592 continue;
2593 max_index = index;
2594 fprintf(outfile, " extern void %s(void);\n", sym_name);
2597 fprintf(outfile,
2598 " struct ia64_fixup *plt_fixes = NULL, "
2599 "*ltoff_fixes = NULL;\n"
2600 " static long plt_target[] = {\n\t");
2602 max_index = -1;
2603 for (i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
2604 sym_idx = ELF64_R_SYM(rel->r_info);
2605 sym_name = (strtab + symtab[sym_idx].st_name);
2606 if (strstart(sym_name, "__op_gen_label", NULL))
2607 continue;
2608 if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
2609 continue;
2611 addend = rel->r_addend;
2612 index = get_plt_index(sym_name, addend);
2613 if (index <= max_index)
2614 continue;
2615 max_index = index;
2617 if (not_first)
2618 fprintf(outfile, ",\n\t");
2619 not_first = 1;
2620 if (addend)
2621 fprintf(outfile, "(long) &%s + %ld", sym_name, addend);
2622 else
2623 fprintf(outfile, "(long) &%s", sym_name);
2625 fprintf(outfile, "\n };\n"
2626 " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2628 #endif
2630 fprintf(outfile,
2631 "\n"
2632 " gen_code_ptr = gen_code_buf;\n"
2633 " opc_ptr = opc_buf;\n"
2634 " opparam_ptr = opparam_buf;\n");
2636 /* Generate prologue, if needed. */
2638 fprintf(outfile,
2639 " for(;;) {\n");
2641 #ifdef HOST_ARM
2642 /* Generate constant pool if needed */
2643 fprintf(outfile,
2644 " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2645 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2646 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
2647 " last_gen_code_ptr = gen_code_ptr;\n"
2648 " arm_ldr_ptr = arm_ldr_table;\n"
2649 " arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
2650 " arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
2651 " }\n");
2652 #endif
2654 fprintf(outfile,
2655 " switch(*opc_ptr++) {\n");
2657 for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2658 const char *name;
2659 name = get_sym_name(sym);
2660 if (strstart(name, OP_PREFIX, NULL)) {
2661 #if 0
2662 printf("%4d: %s pos=0x%08x len=%d\n",
2663 i, name, sym->st_value, sym->st_size);
2664 #endif
2665 #if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
2666 if (sym->st_shndx != text_shndx)
2667 error("invalid section for opcode (0x%x)", sym->st_shndx);
2668 #endif
2669 gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2673 fprintf(outfile,
2674 " case INDEX_op_nop:\n"
2675 " break;\n"
2676 " case INDEX_op_nop1:\n"
2677 " opparam_ptr++;\n"
2678 " break;\n"
2679 " case INDEX_op_nop2:\n"
2680 " opparam_ptr += 2;\n"
2681 " break;\n"
2682 " case INDEX_op_nop3:\n"
2683 " opparam_ptr += 3;\n"
2684 " break;\n"
2685 " default:\n"
2686 " goto the_end;\n"
2687 " }\n");
2690 fprintf(outfile,
2691 " }\n"
2692 " the_end:\n"
2694 #ifdef HOST_IA64
2695 fprintf(outfile,
2696 " {\n"
2697 " extern char code_gen_buffer[];\n"
2698 " ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2699 "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2700 "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2701 "plt_target, plt_offset);\n }\n");
2702 #endif
2704 /* generate some code patching */
2705 #ifdef HOST_ARM
2706 fprintf(outfile,
2707 "if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2708 " gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2709 "arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2710 #endif
2711 /* flush instruction cache */
2712 fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2714 fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n");
2715 fprintf(outfile, "}\n\n");
2719 return 0;
2722 void usage(void)
2724 printf("dyngen (c) 2003 Fabrice Bellard\n"
2725 "usage: dyngen [-o outfile] [-c] objfile\n"
2726 "Generate a dynamic code generator from an object file\n"
2727 "-c output enum of operations\n"
2728 "-g output gen_op_xx() functions\n"
2730 exit(1);
2733 int main(int argc, char **argv)
2735 int c, out_type;
2736 const char *filename, *outfilename;
2737 FILE *outfile;
2739 outfilename = "out.c";
2740 out_type = OUT_CODE;
2741 for(;;) {
2742 c = getopt(argc, argv, "ho:cg");
2743 if (c == -1)
2744 break;
2745 switch(c) {
2746 case 'h':
2747 usage();
2748 break;
2749 case 'o':
2750 outfilename = optarg;
2751 break;
2752 case 'c':
2753 out_type = OUT_INDEX_OP;
2754 break;
2755 case 'g':
2756 out_type = OUT_GEN_OP;
2757 break;
2760 if (optind >= argc)
2761 usage();
2762 filename = argv[optind];
2763 outfile = fopen(outfilename, "w");
2764 if (!outfile)
2765 error("could not open '%s'", outfilename);
2767 load_object(filename);
2768 gen_file(outfile, out_type);
2769 fclose(outfile);
2770 return 0;