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