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