]> git.proxmox.com Git - mirror_qemu.git/blob - dyngen.c
Rewrite Arm host support.
[mirror_qemu.git] / dyngen.c
1 /*
2 * Generic Dynamic compiler generator
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * The COFF object format support was extracted from Kazu's QEMU port
7 * to Win32.
8 *
9 * Mach-O Support by Matt Reda and Pierre d'Herbemont
10 *
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.
15 *
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.
20 *
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.
24 */
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>
32
33 #include "config-host.h"
34
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
44
45 #ifdef CONFIG_FORMAT_ELF
46
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)
51
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
56
57 #elif defined(HOST_X86_64)
58
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
63
64 #elif defined(HOST_PPC)
65
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
70
71 #elif defined(HOST_S390)
72
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
77
78 #elif defined(HOST_ALPHA)
79
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
84
85 #elif defined(HOST_IA64)
86
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
91
92 #elif defined(HOST_SPARC)
93
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
98
99 #elif defined(HOST_SPARC64)
100
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
105
106 #elif defined(HOST_ARM)
107
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
112
113 #elif defined(HOST_M68K)
114
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
119
120 #else
121 #error unsupported CPU - please update the code
122 #endif
123
124 #include "elf.h"
125
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
135
136 #ifdef ELF_USES_RELOCA
137 #define SHT_RELOC SHT_RELA
138 #else
139 #define SHT_RELOC SHT_REL
140 #endif
141
142 #define EXE_RELOC ELF_RELOC
143 #define EXE_SYM ElfW(Sym)
144
145 #endif /* CONFIG_FORMAT_ELF */
146
147 #ifdef CONFIG_FORMAT_COFF
148
149 #include "a.out.h"
150
151 typedef int32_t host_long;
152 typedef uint32_t host_ulong;
153
154 #define FILENAMELEN 256
155
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;
164
165 typedef struct coff_rel {
166 struct external_reloc *r_reloc;
167 int r_offset;
168 uint8_t r_type;
169 } coff_Rel;
170
171 #define EXE_RELOC struct coff_rel
172 #define EXE_SYM struct coff_sym
173
174 #endif /* CONFIG_FORMAT_COFF */
175
176 #ifdef CONFIG_FORMAT_MACH
177
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>
182
183 # define check_mach_header(x) (x.magic == MH_MAGIC)
184 typedef int32_t host_long;
185 typedef uint32_t host_ulong;
186
187 struct nlist_extended
188 {
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;
198 };
199
200 #define EXE_RELOC struct relocation_info
201 #define EXE_SYM struct nlist_extended
202
203 #endif /* CONFIG_FORMAT_MACH */
204
205 #include "bswap.h"
206
207 enum {
208 OUT_GEN_OP,
209 OUT_CODE,
210 OUT_INDEX_OP,
211 };
212
213 /* all dynamically generated functions begin with this code */
214 #define OP_PREFIX "op_"
215
216 int do_swap;
217
218 void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...)
219 {
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);
227 }
228
229 void *load_data(int fd, long offset, unsigned int size)
230 {
231 char *data;
232
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;
240 }
241 return data;
242 }
243
244 int strstart(const char *str, const char *val, const char **ptr)
245 {
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++;
254 }
255 if (ptr)
256 *ptr = p;
257 return 1;
258 }
259
260 void pstrcpy(char *buf, int buf_size, const char *str)
261 {
262 int c;
263 char *q = buf;
264
265 if (buf_size <= 0)
266 return;
267
268 for(;;) {
269 c = *str++;
270 if (c == 0 || q >= buf + buf_size - 1)
271 break;
272 *q++ = c;
273 }
274 *q = '\0';
275 }
276
277 void swab16s(uint16_t *p)
278 {
279 *p = bswap16(*p);
280 }
281
282 void swab32s(uint32_t *p)
283 {
284 *p = bswap32(*p);
285 }
286
287 void swab64s(uint64_t *p)
288 {
289 *p = bswap64(*p);
290 }
291
292 uint16_t get16(uint16_t *p)
293 {
294 uint16_t val;
295 val = *p;
296 if (do_swap)
297 val = bswap16(val);
298 return val;
299 }
300
301 uint32_t get32(uint32_t *p)
302 {
303 uint32_t val;
304 val = *p;
305 if (do_swap)
306 val = bswap32(val);
307 return val;
308 }
309
310 void put16(uint16_t *p, uint16_t val)
311 {
312 if (do_swap)
313 val = bswap16(val);
314 *p = val;
315 }
316
317 void put32(uint32_t *p, uint32_t val)
318 {
319 if (do_swap)
320 val = bswap32(val);
321 *p = val;
322 }
323
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;
331
332 #ifdef CONFIG_FORMAT_ELF
333
334 /* ELF file info */
335 struct elf_shdr *shdr;
336 uint8_t **sdata;
337 struct elfhdr ehdr;
338 char *strtab;
339
340 int elf_must_swap(struct elfhdr *h)
341 {
342 union {
343 uint32_t i;
344 uint8_t b[4];
345 } swaptest;
346
347 swaptest.i = 1;
348 return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
349 (swaptest.b[0] == 0);
350 }
351
352 void elf_swap_ehdr(struct elfhdr *h)
353 {
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 */
367 }
368
369 void elf_swap_shdr(struct elf_shdr *h)
370 {
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 */
381 }
382
383 void elf_swap_phdr(struct elf_phdr *h)
384 {
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 */
393 }
394
395 void elf_swap_rel(ELF_RELOC *rel)
396 {
397 swabls(&rel->r_offset);
398 swabls(&rel->r_info);
399 #ifdef ELF_USES_RELOCA
400 swabls(&rel->r_addend);
401 #endif
402 }
403
404 struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
405 const char *name)
406 {
407 int i;
408 const char *shname;
409 struct elf_shdr *sec;
410
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;
418 }
419 return NULL;
420 }
421
422 int find_reloc(int sh_index)
423 {
424 struct elf_shdr *sec;
425 int i;
426
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;
431 }
432 return 0;
433 }
434
435 static host_ulong get_rel_offset(EXE_RELOC *rel)
436 {
437 return rel->r_offset;
438 }
439
440 static char *get_rel_sym_name(EXE_RELOC *rel)
441 {
442 return strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
443 }
444
445 static char *get_sym_name(EXE_SYM *sym)
446 {
447 return strtab + sym->st_name;
448 }
449
450 /* load an elf object file */
451 int load_object(const char *filename)
452 {
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;
459
460 fd = open(filename, O_RDONLY);
461 if (fd < 0)
462 error("can't open file '%s'", filename);
463
464 /* Read ELF header. */
465 if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
466 error("unable to read file header");
467
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");
475 }
476
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);
488
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]);
494 }
495 }
496
497 /* read all section data */
498 sdata = malloc(sizeof(void *) * ehdr.e_shnum);
499 memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
500
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);
505 }
506
507 sec = &shdr[ehdr.e_shstrndx];
508 shstr = sdata[ehdr.e_shstrndx];
509
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);
518 }
519 }
520 }
521 /* text section */
522
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];
528
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;
536 }
537
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];
542
543 symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
544 strtab = sdata[symtab_sec->sh_link];
545
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);
553 }
554 }
555 close(fd);
556 return 0;
557 }
558
559 #endif /* CONFIG_FORMAT_ELF */
560
561 #ifdef CONFIG_FORMAT_COFF
562
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;
570
571 int data_shndx;
572
573 #define STRTAB_SIZE 4
574
575 #define DIR32 0x06
576 #define DISP32 0x14
577
578 #define T_FUNCTION 0x20
579 #define C_EXTERNAL 2
580
581 void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
582 {
583 char *q;
584 int c, i, len;
585
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;
593 }
594 *q = '\0';
595 } else {
596 pstrcpy(sym->st_name, sizeof(sym->st_name), strtab + ext_sym->e.e.e_offset);
597 }
598
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';
604 }
605 }
606
607 char *name_for_dotdata(struct coff_rel *rel)
608 {
609 int i;
610 struct coff_sym *sym;
611 uint32_t text_data;
612
613 text_data = *(uint32_t *)(text + rel->r_offset);
614
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) {
619
620 return sym->st_name;
621
622 }
623 }
624 return NULL;
625 }
626
627 static char *get_sym_name(EXE_SYM *sym)
628 {
629 return sym->st_name;
630 }
631
632 static char *get_rel_sym_name(EXE_RELOC *rel)
633 {
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;
641 }
642
643 static host_ulong get_rel_offset(EXE_RELOC *rel)
644 {
645 return rel->r_offset;
646 }
647
648 struct external_scnhdr *find_coff_section(struct external_scnhdr *shdr, int shnum, const char *name)
649 {
650 int i;
651 const char *shname;
652 struct external_scnhdr *sec;
653
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;
661 }
662 return NULL;
663 }
664
665 /* load a coff object file */
666 int load_object(const char *filename)
667 {
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;
677
678 fd = open(filename, O_RDONLY
679 #ifdef _WIN32
680 | O_BINARY
681 #endif
682 );
683 if (fd < 0)
684 error("can't open file '%s'", filename);
685
686 /* Read COFF header. */
687 if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
688 error("unable to read file header");
689
690 /* Check COFF identification. */
691 if (fhdr.f_magic != I386MAGIC) {
692 error("bad COFF header");
693 }
694 do_swap = 0;
695
696 /* read section headers */
697 shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
698
699 /* read all section data */
700 sdata = malloc(sizeof(void *) * fhdr.f_nscns);
701 memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
702
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);
708 }
709
710
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];
717
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;
723
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");
729 }
730
731
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);
734
735 nb_syms = fhdr.f_nsyms;
736
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;
742 }
743
744 /* set coff symbol */
745 symtab = malloc(sizeof(struct coff_sym) * nb_syms);
746
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;
753
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;
765 }
766 }
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;
776 }
777 }
778 } else {
779 sym->st_size = 0;
780 }
781
782 sym->st_type = ext_sym->e_type;
783 sym->st_shndx = ext_sym->e_scnum;
784 }
785
786
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;
791
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;
800 }
801 return 0;
802 }
803
804 #endif /* CONFIG_FORMAT_COFF */
805
806 #ifdef CONFIG_FORMAT_MACH
807
808 /* File Header */
809 struct mach_header mach_hdr;
810
811 /* commands */
812 struct segment_command *segment = 0;
813 struct dysymtab_command *dysymtabcmd = 0;
814 struct symtab_command *symtabcmd = 0;
815
816 /* section */
817 struct section *section_hdr;
818 struct section *text_sec_hdr;
819 uint8_t **sdata;
820
821 /* relocs */
822 struct relocation_info *relocs;
823
824 /* symbols */
825 EXE_SYM *symtab;
826 struct nlist *symtab_std;
827 char *strtab;
828
829 /* indirect symbols */
830 uint32_t *tocdylib;
831
832 /* Utility functions */
833
834 static inline char *find_str_by_index(int index)
835 {
836 return strtab+index;
837 }
838
839 /* Used by dyngen common code */
840 static char *get_sym_name(EXE_SYM *sym)
841 {
842 char *name = find_str_by_index(sym->n_un.n_strx);
843
844 if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
845 return "debug";
846
847 if(!name)
848 return name;
849 if(name[0]=='_')
850 return name + 1;
851 else
852 return name;
853 }
854
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)
858 {
859 int i;
860 struct section *sec = section_hdr;
861
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;
867 }
868 return -1;
869 }
870
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)
874 {
875 int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
876 if(index == -1)
877 return NULL;
878 return section_hdr+index;
879 }
880
881
882 static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
883 {
884 struct scattered_relocation_info * scarel;
885
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;
895 }
896 }
897
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 )
900 {
901 int i, ret = -1;
902
903 for( i = 0 ; i < nb_syms; i++ )
904 {
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) )
907 {
908 if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) )
909 ret = i;
910 }
911 }
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]);
918 }
919 }
920
921 /*
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
924 */
925 static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
926 {
927 unsigned int tocindex, symindex, size;
928 const char *name = 0;
929
930 /* Sanity check */
931 if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
932 return (char*)0;
933
934 if( sec_hdr->flags & S_SYMBOL_STUBS ){
935 size = sec_hdr->reserved2;
936 if(size == 0)
937 error("size = 0");
938
939 }
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;
945
946 /* Compute our index in toc */
947 tocindex = (address - sec_hdr->addr)/size;
948 symindex = tocdylib[sec_hdr->reserved1 + tocindex];
949
950 name = get_sym_name(&symtab[symindex]);
951
952 return name;
953 }
954
955 static const char * find_reloc_name_given_its_address(int address)
956 {
957 unsigned int i;
958 for(i = 0; i < segment->nsects ; i++)
959 {
960 const char * name = find_reloc_name_in_sec_ptr(address, &section_hdr[i]);
961 if((long)name != -1)
962 return name;
963 }
964 return 0;
965 }
966
967 static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
968 {
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;
974
975 /* init the slide value */
976 *sslide = 0;
977
978 if(R_SCATTERED & rel->r_address)
979 return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
980
981 if(rel->r_extern)
982 {
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]);
987 }
988
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;
991
992 if(sectnum==0xffffff)
993 return 0;
994
995 /* Sanity Check */
996 if(sectnum > segment->nsects)
997 error("sectnum > segment->nsects");
998
999 switch(rel->r_type)
1000 {
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");
1013 }
1014
1015 if(rel->r_pcrel)
1016 sectoffset += rel->r_address;
1017
1018 if (rel->r_type == PPC_RELOC_BR24)
1019 name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
1020
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);
1024
1025 return name;
1026 }
1027
1028 /* Used by dyngen common code */
1029 static const char * get_rel_sym_name(EXE_RELOC * rel)
1030 {
1031 int sslide;
1032 return get_reloc_name( rel, &sslide);
1033 }
1034
1035 /* Used by dyngen common code */
1036 static host_ulong get_rel_offset(EXE_RELOC *rel)
1037 {
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;
1043 }
1044
1045 /* load a mach-o object file */
1046 int load_object(const char *filename)
1047 {
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;
1056
1057 fd = open(filename, O_RDONLY);
1058 if (fd < 0)
1059 error("can't open file '%s'", filename);
1060
1061 /* Read Mach header. */
1062 if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
1063 error("unable to read file header");
1064
1065 /* Check Mach identification. */
1066 if (!check_mach_header(mach_hdr)) {
1067 error("bad Mach header");
1068 }
1069
1070 if (mach_hdr.cputype != CPU_TYPE_POWERPC)
1071 error("Unsupported CPU");
1072
1073 if (mach_hdr.filetype != MH_OBJECT)
1074 error("Unsupported Mach Object");
1075
1076 /* read segment headers */
1077 for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
1078 {
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)
1082 {
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");
1088 }
1089 if(lc.cmd == LC_DYSYMTAB)
1090 {
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");
1096 }
1097 if(lc.cmd == LC_SYMTAB)
1098 {
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");
1104 }
1105 j+=lc.cmdsize;
1106
1107 lseek(fd, j, SEEK_SET);
1108 }
1109
1110 if(!segment)
1111 error("unable to find LC_SEGMENT");
1112
1113 /* read section headers */
1114 section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section));
1115
1116 /* read all section data */
1117 sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
1118 memset(sdata, 0, sizeof(void *) * segment->nsects);
1119
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);
1123 }
1124
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];
1131
1132 /* Make sure dysym was loaded */
1133 if(!(int)dysymtabcmd)
1134 error("could not find __DYSYMTAB segment");
1135
1136 /* read the table of content of the indirect sym */
1137 tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
1138
1139 /* Make sure symtab was loaded */
1140 if(!(int)symtabcmd)
1141 error("could not find __SYMTAB segment");
1142 nb_syms = symtabcmd->nsyms;
1143
1144 symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
1145 strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
1146
1147 symtab = malloc(sizeof(EXE_SYM) * nb_syms);
1148
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));
1154
1155 if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
1156 continue;
1157
1158 memcpy(sym, syment, sizeof(*syment));
1159
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;
1167 }
1168 if(!(sym_next->n_value > sym_follow->n_value))
1169 continue;
1170 sym_next = sym_follow;
1171 }
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;
1176 }
1177
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;
1181
1182 close(fd);
1183 return 0;
1184 }
1185
1186 #endif /* CONFIG_FORMAT_MACH */
1187
1188 void get_reloc_expr(char *name, int name_size, const char *sym_name)
1189 {
1190 const char *p;
1191
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);
1205 }
1206 }
1207
1208 #ifdef HOST_IA64
1209
1210 #define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */
1211
1212 struct plt_entry {
1213 struct plt_entry *next;
1214 const char *name;
1215 unsigned long addend;
1216 } *plt_list;
1217
1218 static int
1219 get_plt_index (const char *name, unsigned long addend)
1220 {
1221 struct plt_entry *plt, *prev= NULL;
1222 int index = 0;
1223
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;
1228
1229 /* nope; create a new PLT entry: */
1230
1231 plt = malloc(sizeof(*plt));
1232 if (!plt) {
1233 perror("malloc");
1234 exit(1);
1235 }
1236 memset(plt, 0, sizeof(*plt));
1237 plt->name = strdup(name);
1238 plt->addend = addend;
1239
1240 /* append to plt-list: */
1241 if (prev)
1242 prev->next = plt;
1243 else
1244 plt_list = plt;
1245 return index;
1246 }
1247
1248 #endif
1249
1250 #ifdef HOST_ARM
1251
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)
1255 {
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;
1262
1263 memset(data_allocated, 0, sizeof(data_allocated));
1264
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;
1293
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;
1301 }
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");
1329 }
1330 }
1331 p += 4;
1332 }
1333
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);
1343
1344 data_index = 0;
1345 for (pc_offset = min_offset;
1346 pc_offset < p_end - p_start;
1347 pc_offset += 4) {
1348
1349 ELF_RELOC *rel;
1350 int i, addend, type;
1351 const char *sym_name;
1352 char relname[1024];
1353
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;
1366 }
1367 }
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");
1373
1374 data_index++;
1375 }
1376 }
1377
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);
1392 }
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);
1399 }
1400 return p - p_start;
1401 }
1402 #endif
1403
1404
1405 #define MAX_ARGS 3
1406
1407 /* generate op code */
1408 void gen_code(const char *name, host_ulong offset, host_ulong size,
1409 FILE *outfile, int gen_switch)
1410 {
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;
1418
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).
1423 */
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
1429 {
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);
1438 }
1439 copy_size = p - p_start;
1440 }
1441 #else
1442 {
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);
1451 }
1452 copy_size = len;
1453 }
1454 #endif
1455 #elif defined(HOST_PPC)
1456 {
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;
1464 }
1465 #elif defined(HOST_S390)
1466 {
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;
1474 }
1475 #elif defined(HOST_ALPHA)
1476 {
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;
1487 }
1488 #elif defined(HOST_IA64)
1489 {
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;
1499 }
1500 #elif defined(HOST_SPARC)
1501 {
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
1510
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
1530
1531 error("ret; restore; not found at end of %s", name);
1532 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1533 ;
1534 } else {
1535 error("No save at the beginning of %s", name);
1536 }
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;
1543 }
1544 #endif
1545 copy_size = p - p_start;
1546 }
1547 #elif defined(HOST_SPARC64)
1548 {
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
1557
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
1580
1581 error("ret; restore; not found at end of %s", name);
1582 } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
1583 ;
1584 } else {
1585 error("No save at the beginning of %s", name);
1586 }
1587
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;
1593 }
1594
1595 copy_size = p - p_start;
1596 }
1597 #elif defined(HOST_ARM)
1598 {
1599 uint32_t insn;
1600
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;
1614 }
1615 copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
1616 relocs, nb_relocs);
1617 }
1618 #elif defined(HOST_M68K)
1619 {
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;
1631 }
1632 #else
1633 #error unsupported CPU
1634 #endif
1635
1636 /* compute the number of arguments by looking at the relocations */
1637 for(i = 0;i < MAX_ARGS; i++)
1638 args_present[i] = 0;
1639
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;
1653 }
1654 }
1655 }
1656
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);
1663 }
1664
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) {
1668
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);
1677 }
1678 fprintf(outfile, ";\n");
1679 }
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
1685
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;
1703 }
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)
1710 /*
1711 * PCREL21 br.call targets generally
1712 * are out of range and need to go
1713 * through an "import stub".
1714 */
1715 fprintf(outfile, " extern char %s;\n",
1716 sym_name);
1717 #else
1718 fprintf(outfile, "extern char %s;\n", sym_name);
1719 #endif
1720 }
1721 }
1722 }
1723
1724 fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
1725 name, (int)(start_offset - offset), copy_size);
1726
1727 /* emit code offset information */
1728 {
1729 EXE_SYM *sym;
1730 const char *sym_name, *p;
1731 unsigned long val;
1732 int n;
1733
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;
1739
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;
1749 }
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
1765 {
1766 int reloc_shndx, nb_relocs1, j;
1767
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;
1778 }
1779 rel++;
1780 }
1781 }
1782 }
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));
1787 }
1788 }
1789 }
1790 }
1791
1792 /* load parameres in variables */
1793 for(i = 0; i < nb_args; i++) {
1794 fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
1795 }
1796
1797 /* patch relocations */
1798 #if defined(HOST_I386)
1799 {
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;
1821 }
1822
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);
1838 }
1839 #elif defined(CONFIG_FORMAT_COFF)
1840 {
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;
1849 }
1850 }
1851 }
1852 }
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);
1865 }
1866 #else
1867 #error unsupport object format
1868 #endif
1869 }
1870 }
1871 }
1872 #elif defined(HOST_X86_64)
1873 {
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);
1901 }
1902 }
1903 }
1904 }
1905 #elif defined(HOST_PPC)
1906 {
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;
1927 }
1928
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);
1956 }
1957 }
1958 }
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;
1967
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;
1972
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;
1987 }
1988
1989 slide = offset - start_offset;
1990
1991 if (!(offset >= start_offset && offset < start_offset + size))
1992 continue; /* not in our range */
1993
1994 sym_name = get_reloc_name(rel, &sslide);
1995
1996 if(usesym && symtab[isym].n_type & N_STAB)
1997 continue; /* don't handle STAB (debug sym) */
1998
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 */
2005 }
2006
2007 if(!sym_name)
2008 {
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 */
2012 }
2013
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);
2027 }
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);
2043 }
2044 }
2045 #else
2046 #error unsupport object format
2047 #endif
2048 }
2049 #elif defined(HOST_S390)
2050 {
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);
2078 }
2079 }
2080 }
2081 }
2082 #elif defined(HOST_ALPHA)
2083 {
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;
2088
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);
2134 }
2135 }
2136 }
2137 }
2138 #elif defined(HOST_IA64)
2139 {
2140 unsigned long sym_idx;
2141 long code_offset;
2142 char name[256];
2143 int type;
2144 long addend;
2145
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;
2164 }
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;
2187
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);
2203 }
2204 break;
2205 default:
2206 error("unsupported ia64 relocation (0x%x)",
2207 type);
2208 }
2209 }
2210 fprintf(outfile, " ia64_nop_b(gen_code_ptr + %d);\n",
2211 copy_size - 16 + 2);
2212 }
2213 #elif defined(HOST_SPARC)
2214 {
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);
2272 }
2273 }
2274 }
2275 }
2276 #elif defined(HOST_SPARC64)
2277 {
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);
2342 }
2343 }
2344 }
2345 }
2346 #elif defined(HOST_ARM)
2347 {
2348 char name[256];
2349 int type;
2350 int addend;
2351 int reloc_offset;
2352 uint32_t insn;
2353
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;
2371 }
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;
2379 }
2380 fprintf(outfile,
2381 " *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
2382 }
2383 arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
2384 relocs, nb_relocs);
2385
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);
2410 }
2411 }
2412 }
2413 }
2414 #elif defined(HOST_M68K)
2415 {
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);
2443 }
2444 }
2445 }
2446 }
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);
2462 }
2463 }
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);
2468 }
2469 fprintf(outfile, " *gen_opc_ptr++ = INDEX_%s;\n", name);
2470 fprintf(outfile, "}\n\n");
2471 }
2472 }
2473
2474 int gen_file(FILE *outfile, int out_type)
2475 {
2476 int i;
2477 EXE_SYM *sym;
2478
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);
2490 }
2491 }
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);
2504 }
2505 }
2506
2507 } else {
2508 /* generate big code generation switch */
2509
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);
2525 }
2526 }
2527 fprintf(outfile,
2528 "};\n");
2529 #endif
2530
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");
2539
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.
2547
2548 We currently generate:
2549
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;
2562
2563 Ideally we'd put op1_pool before op2_pool, but that requires two passes.
2564 */
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
2573 {
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;
2579
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;
2588
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);
2595 }
2596
2597 fprintf(outfile,
2598 " struct ia64_fixup *plt_fixes = NULL, "
2599 "*ltoff_fixes = NULL;\n"
2600 " static long plt_target[] = {\n\t");
2601
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;
2610
2611 addend = rel->r_addend;
2612 index = get_plt_index(sym_name, addend);
2613 if (index <= max_index)
2614 continue;
2615 max_index = index;
2616
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);
2624 }
2625 fprintf(outfile, "\n };\n"
2626 " unsigned int plt_offset[%u] = { 0 };\n", max_index + 1);
2627 }
2628 #endif
2629
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");
2635
2636 /* Generate prologue, if needed. */
2637
2638 fprintf(outfile,
2639 " for(;;) {\n");
2640
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
2653
2654 fprintf(outfile,
2655 " switch(*opc_ptr++) {\n");
2656
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);
2670 }
2671 }
2672
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");
2688
2689
2690 fprintf(outfile,
2691 " }\n"
2692 " the_end:\n"
2693 );
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
2703
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");
2713
2714 fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n");
2715 fprintf(outfile, "}\n\n");
2716
2717 }
2718
2719 return 0;
2720 }
2721
2722 void usage(void)
2723 {
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"
2729 );
2730 exit(1);
2731 }
2732
2733 int main(int argc, char **argv)
2734 {
2735 int c, out_type;
2736 const char *filename, *outfilename;
2737 FILE *outfile;
2738
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;
2758 }
2759 }
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);
2766
2767 load_object(filename);
2768 gen_file(outfile, out_type);
2769 fclose(outfile);
2770 return 0;
2771 }