170 |
swabls(&h->p_align); /* Segment alignment */ |
swabls(&h->p_align); /* Segment alignment */ |
171 |
} |
} |
172 |
|
|
173 |
|
/* ELF file info */ |
174 |
int do_swap; |
int do_swap; |
175 |
|
struct elf_shdr *shdr; |
176 |
|
struct elfhdr ehdr; |
177 |
|
ElfW(Sym) *symtab; |
178 |
|
int nb_syms; |
179 |
|
char *strtab; |
180 |
|
/* data section */ |
181 |
|
uint8_t *data_data; |
182 |
|
int data_shndx; |
183 |
|
|
184 |
uint16_t get16(uint16_t *p) |
uint16_t get16(uint16_t *p) |
185 |
{ |
{ |
279 |
/* generate op code */ |
/* generate op code */ |
280 |
void gen_code(const char *name, host_ulong offset, host_ulong size, |
void gen_code(const char *name, host_ulong offset, host_ulong size, |
281 |
FILE *outfile, uint8_t *text, ELF_RELOC *relocs, int nb_relocs, int reloc_sh_type, |
FILE *outfile, uint8_t *text, ELF_RELOC *relocs, int nb_relocs, int reloc_sh_type, |
282 |
ElfW(Sym) *symtab, char *strtab, int gen_switch) |
int gen_switch) |
283 |
{ |
{ |
284 |
int copy_size = 0; |
int copy_size = 0; |
285 |
uint8_t *p_start, *p_end; |
uint8_t *p_start, *p_end; |
300 |
switch(ELF_ARCH) { |
switch(ELF_ARCH) { |
301 |
case EM_386: |
case EM_386: |
302 |
{ |
{ |
303 |
uint8_t *p; |
int len; |
304 |
p = p_end - 1; |
len = p_end - p_start; |
305 |
if (p == p_start) |
if (len == 0) |
306 |
error("empty code for %s", name); |
error("empty code for %s", name); |
307 |
if (p[0] != 0xc3) |
if (p_end[-1] == 0xc3) { |
308 |
error("ret expected at the end of %s", name); |
len--; |
309 |
copy_size = p - p_start; |
} else { |
310 |
|
error("ret or jmp expected at the end of %s", name); |
311 |
|
} |
312 |
|
copy_size = len; |
313 |
} |
} |
314 |
break; |
break; |
315 |
case EM_PPC: |
case EM_PPC: |
435 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
436 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
437 |
n = strtoul(p, NULL, 10); |
n = strtoul(p, NULL, 10); |
438 |
if (n >= MAX_ARGS) |
if (n > MAX_ARGS) |
439 |
error("too many arguments in %s", name); |
error("too many arguments in %s", name); |
440 |
args_present[n - 1] = 1; |
args_present[n - 1] = 1; |
441 |
} |
} |
471 |
if (rel->r_offset >= start_offset && |
if (rel->r_offset >= start_offset && |
472 |
rel->r_offset < start_offset + copy_size) { |
rel->r_offset < start_offset + copy_size) { |
473 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
474 |
if (*sym_name && !strstart(sym_name, "__op_param", &p)) { |
if (*sym_name && |
475 |
|
!strstart(sym_name, "__op_param", NULL) && |
476 |
|
!strstart(sym_name, "__op_jmp", NULL)) { |
477 |
#if defined(HOST_SPARC) |
#if defined(HOST_SPARC) |
478 |
if (sym_name[0] == '.') { |
if (sym_name[0] == '.') { |
479 |
fprintf(outfile, |
fprintf(outfile, |
488 |
} |
} |
489 |
|
|
490 |
fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size); |
fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size); |
491 |
|
|
492 |
|
/* emit code offset information */ |
493 |
|
{ |
494 |
|
ElfW(Sym) *sym; |
495 |
|
const char *sym_name, *p; |
496 |
|
target_ulong val; |
497 |
|
int n; |
498 |
|
|
499 |
|
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
500 |
|
sym_name = strtab + sym->st_name; |
501 |
|
if (strstart(sym_name, "__op_label", &p)) { |
502 |
|
/* test if the variable refers to a label inside |
503 |
|
the code we are generating */ |
504 |
|
if (sym->st_shndx != data_shndx) |
505 |
|
error("__op_labelN symbols must be in .data or .sdata section"); |
506 |
|
val = *(target_ulong *)(data_data + sym->st_value); |
507 |
|
if (val >= start_offset && val < start_offset + copy_size) { |
508 |
|
n = strtol(p, NULL, 10); |
509 |
|
fprintf(outfile, " label_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, val - start_offset); |
510 |
|
} |
511 |
|
} |
512 |
|
} |
513 |
|
} |
514 |
|
|
515 |
|
/* load parameres in variables */ |
516 |
for(i = 0; i < nb_args; i++) { |
for(i = 0; i < nb_args; i++) { |
517 |
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); |
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); |
518 |
} |
} |
558 |
if (rel->r_offset >= start_offset && |
if (rel->r_offset >= start_offset && |
559 |
rel->r_offset < start_offset + copy_size) { |
rel->r_offset < start_offset + copy_size) { |
560 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
561 |
|
if (strstart(sym_name, "__op_jmp", &p)) { |
562 |
|
int n; |
563 |
|
n = strtol(p, NULL, 10); |
564 |
|
/* __op_jmp relocations are done at |
565 |
|
runtime to do translated block |
566 |
|
chaining: the offset of the instruction |
567 |
|
needs to be stored */ |
568 |
|
fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", |
569 |
|
n, rel->r_offset - start_offset); |
570 |
|
continue; |
571 |
|
} |
572 |
|
|
573 |
if (strstart(sym_name, "__op_param", &p)) { |
if (strstart(sym_name, "__op_param", &p)) { |
574 |
snprintf(name, sizeof(name), "param%s", p); |
snprintf(name, sizeof(name), "param%s", p); |
575 |
} else { |
} else { |
875 |
int load_elf(const char *filename, FILE *outfile, int do_print_enum) |
int load_elf(const char *filename, FILE *outfile, int do_print_enum) |
876 |
{ |
{ |
877 |
int fd; |
int fd; |
878 |
struct elfhdr ehdr; |
struct elf_shdr *sec, *symtab_sec, *strtab_sec, *text_sec; |
879 |
struct elf_shdr *sec, *shdr, *symtab_sec, *strtab_sec, *text_sec; |
int i, j; |
880 |
int i, j, nb_syms; |
ElfW(Sym) *sym; |
881 |
ElfW(Sym) *symtab, *sym; |
char *shstr, *data_name; |
|
char *shstr, *strtab; |
|
882 |
uint8_t *text; |
uint8_t *text; |
883 |
void *relocs; |
void *relocs; |
884 |
int nb_relocs, reloc_sh_type; |
int nb_relocs, reloc_sh_type; |
930 |
error("could not find .text section"); |
error("could not find .text section"); |
931 |
text = load_data(fd, text_sec->sh_offset, text_sec->sh_size); |
text = load_data(fd, text_sec->sh_offset, text_sec->sh_size); |
932 |
|
|
933 |
|
#if defined(HOST_PPC) |
934 |
|
data_name = ".sdata"; |
935 |
|
#else |
936 |
|
data_name = ".data"; |
937 |
|
#endif |
938 |
|
sec = find_elf_section(shdr, ehdr.e_shnum, shstr, data_name); |
939 |
|
if (!sec) |
940 |
|
error("could not find %s section", data_name); |
941 |
|
data_shndx = sec - shdr; |
942 |
|
data_data = load_data(fd, sec->sh_offset, sec->sh_size); |
943 |
|
|
944 |
/* find text relocations, if any */ |
/* find text relocations, if any */ |
945 |
nb_relocs = 0; |
nb_relocs = 0; |
946 |
relocs = NULL; |
relocs = NULL; |
997 |
name = strtab + sym->st_name; |
name = strtab + sym->st_name; |
998 |
if (strstart(name, OP_PREFIX, &p)) { |
if (strstart(name, OP_PREFIX, &p)) { |
999 |
gen_code(name, sym->st_value, sym->st_size, outfile, |
gen_code(name, sym->st_value, sym->st_size, outfile, |
1000 |
text, relocs, nb_relocs, reloc_sh_type, symtab, strtab, 2); |
text, relocs, nb_relocs, reloc_sh_type, 2); |
1001 |
} |
} |
1002 |
} |
} |
1003 |
} else { |
} else { |
1024 |
#endif |
#endif |
1025 |
fprintf(outfile, |
fprintf(outfile, |
1026 |
"int dyngen_code(uint8_t *gen_code_buf,\n" |
"int dyngen_code(uint8_t *gen_code_buf,\n" |
1027 |
|
" uint16_t *label_offsets, uint16_t *jmp_offsets,\n" |
1028 |
" const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" |
" const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" |
1029 |
"{\n" |
"{\n" |
1030 |
" uint8_t *gen_code_ptr;\n" |
" uint8_t *gen_code_ptr;\n" |
1063 |
if (sym->st_shndx != (text_sec - shdr)) |
if (sym->st_shndx != (text_sec - shdr)) |
1064 |
error("invalid section for opcode (0x%x)", sym->st_shndx); |
error("invalid section for opcode (0x%x)", sym->st_shndx); |
1065 |
gen_code(name, sym->st_value, sym->st_size, outfile, |
gen_code(name, sym->st_value, sym->st_size, outfile, |
1066 |
text, relocs, nb_relocs, reloc_sh_type, symtab, strtab, 1); |
text, relocs, nb_relocs, reloc_sh_type, 1); |
1067 |
} |
} |
1068 |
} |
} |
1069 |
|
|
1118 |
if (sym->st_shndx != (text_sec - shdr)) |
if (sym->st_shndx != (text_sec - shdr)) |
1119 |
error("invalid section for opcode (0x%x)", sym->st_shndx); |
error("invalid section for opcode (0x%x)", sym->st_shndx); |
1120 |
gen_code(name, sym->st_value, sym->st_size, outfile, |
gen_code(name, sym->st_value, sym->st_size, outfile, |
1121 |
text, relocs, nb_relocs, reloc_sh_type, symtab, strtab, 0); |
text, relocs, nb_relocs, reloc_sh_type, 0); |
1122 |
} |
} |
1123 |
} |
} |
1124 |
} |
} |