📄 dyngen.c.svn-base
字号:
#error unsupported CPU#endif /* compute the number of arguments by looking at the relocations */ for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { host_ulong offset = get_rel_offset(rel); if (offset >= start_offset && offset < start_offset + (p_end - p_start)) { sym_name = get_rel_sym_name(rel); if(!sym_name) continue; if (strstart(sym_name, "__op_param", &p) || strstart(sym_name, "__op_gen_label", &p)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } if (gen_switch == 2) { fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size); } else if (gen_switch == 1) { /* output C code */ fprintf(outfile, "case INDEX_%s: {\n", name); if (nb_args > 0) { fprintf(outfile, " long "); for(i = 0; i < nb_args; i++) { if (i != 0) fprintf(outfile, ", "); fprintf(outfile, "param%d", i + 1); } fprintf(outfile, ";\n"); }#if defined(HOST_IA64) fprintf(outfile, " extern char %s;\n", name);#else fprintf(outfile, " extern void %s();\n", name);#endif for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { host_ulong offset = get_rel_offset(rel); if (offset >= start_offset && offset < start_offset + (p_end - p_start)) { sym_name = get_rel_sym_name(rel); if(!sym_name) continue; if (*sym_name && !strstart(sym_name, "__op_param", NULL) && !strstart(sym_name, "__op_jmp", NULL) && !strstart(sym_name, "__op_gen_label", NULL)) {#if defined(HOST_SPARC) if (sym_name[0] == '.') { fprintf(outfile, "extern char __dot_%s __asm__(\"%s\");\n", sym_name+1, sym_name); continue; }#endif#if defined(__APPLE__) /* Set __attribute((unused)) on darwin because we want to avoid warning when we don't use the symbol. */ fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name);#elif defined(HOST_IA64) if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B) /* * PCREL21 br.call targets generally * are out of range and need to go * through an "import stub". */ fprintf(outfile, " extern char %s;\n", sym_name);#else fprintf(outfile, "extern char %s;\n", sym_name);#endif } } } fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, (int)(start_offset - offset), copy_size); /* emit code offset information */ { EXE_SYM *sym; const char *sym_name, *p; host_ulong val; int n; for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { sym_name = get_sym_name(sym); if (strstart(sym_name, "__op_label", &p)) { uint8_t *ptr; unsigned long offset; /* test if the variable refers to a label inside the code we are generating */#ifdef CONFIG_FORMAT_COFF if (sym->st_shndx == text_shndx) { ptr = sdata[coff_text_shndx]; } else if (sym->st_shndx == data_shndx) { ptr = sdata[coff_data_shndx]; } else { ptr = NULL; }#elif defined(CONFIG_FORMAT_MACH) if(!sym->n_sect) continue; ptr = sdata[sym->n_sect-1];#else ptr = sdata[sym->st_shndx];#endif if (!ptr) error("__op_labelN in invalid section"); offset = sym->st_value;#ifdef CONFIG_FORMAT_MACH offset -= section_hdr[sym->n_sect-1].addr;#endif val = *(host_ulong *)(ptr + offset);#ifdef ELF_USES_RELOCA { int reloc_shndx, nb_relocs1, j; /* try to find a matching relocation */ reloc_shndx = find_reloc(sym->st_shndx); if (reloc_shndx) { nb_relocs1 = shdr[reloc_shndx].sh_size / shdr[reloc_shndx].sh_entsize; rel = (ELF_RELOC *)sdata[reloc_shndx]; for(j = 0; j < nb_relocs1; j++) { if (rel->r_offset == offset) { val = rel->r_addend; break; } rel++; } } }#endif if (val >= start_offset && val <= start_offset + copy_size) { n = strtol(p, NULL, 10); fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset)); } } } } /* load parameters in variables */ for(i = 0; i < nb_args; i++) { fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); } /* patch relocations */#if defined(HOST_I386) { char relname[256]; int type; int addend; int reloc_offset; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { sym_name = get_rel_sym_name(rel); if (!sym_name) continue; reloc_offset = rel->r_offset - start_offset; if (strstart(sym_name, "__op_jmp", &p)) { int n; n = strtol(p, NULL, 10); /* __op_jmp relocations are done at runtime to do translated block chaining: the offset of the instruction needs to be stored */ fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, reloc_offset); continue; } get_reloc_expr(relname, sizeof(relname), sym_name); addend = get32((uint32_t *)(text + rel->r_offset));#ifdef CONFIG_FORMAT_ELF type = ELF32_R_TYPE(rel->r_info); switch(type) { case R_386_32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", reloc_offset, relname, addend); break; case R_386_PC32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", reloc_offset, relname, reloc_offset, addend); break; default: error("unsupported i386 relocation (%d)", type); }#elif defined(CONFIG_FORMAT_COFF) { char *temp_name; int j; EXE_SYM *sym; temp_name = get_sym_name(symtab + *(uint32_t *)(rel->r_reloc->r_symndx)); if (!strcmp(temp_name, ".data")) { for (j = 0, sym = symtab; j < nb_syms; j++, sym++) { if (strstart(sym->st_name, sym_name, NULL)) { addend -= sym->st_value; } } } } type = rel->r_type; switch(type) { case DIR32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", reloc_offset, relname, addend); break; case DISP32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n", reloc_offset, relname, reloc_offset, addend); break; default: error("unsupported i386 relocation (%d)", type); }#else#error unsupport object format#endif } } }#elif defined(HOST_X86_64) { char relname[256]; int type; int addend; int reloc_offset; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; get_reloc_expr(relname, sizeof(relname), sym_name); type = ELF32_R_TYPE(rel->r_info); addend = rel->r_addend; reloc_offset = rel->r_offset - start_offset; switch(type) { case R_X86_64_32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n", reloc_offset, relname, addend); break; case R_X86_64_32S: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", reloc_offset, relname, addend); break; case R_X86_64_PC32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", reloc_offset, relname, reloc_offset, addend); break; default: error("unsupported X86_64 relocation (%d)", type); } } } }#elif defined(HOST_PPC) {#ifdef CONFIG_FORMAT_ELF char relname[256]; int type; int addend; int reloc_offset; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; reloc_offset = rel->r_offset - start_offset; if (strstart(sym_name, "__op_jmp", &p)) { int n; n = strtol(p, NULL, 10); /* __op_jmp relocations are done at runtime to do translated block chaining: the offset of the instruction needs to be stored */ fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, reloc_offset); continue; } get_reloc_expr(relname, sizeof(relname), sym_name); type = ELF32_R_TYPE(rel->r_info); addend = rel->r_addend; switch(type) { case R_PPC_ADDR32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", reloc_offset, relname, addend); break; case R_PPC_ADDR16_LO: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", reloc_offset, relname, addend); break; case R_PPC_ADDR16_HI: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", reloc_offset, relname, addend); break; case R_PPC_ADDR16_HA: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", reloc_offset, relname, addend); break; case R_PPC_REL24: /* warning: must be at 32 MB distancy */ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", reloc_offset, reloc_offset, relname, reloc_offset, addend); break; default: error("unsupported powerpc relocation (%d)", type); } } }#elif defined(CONFIG_FORMAT_MACH) struct scattered_relocation_info *scarel; struct relocation_info * rel; char final_sym_name[256]; const char *sym_name; const char *p; int slide, sslide; int i; for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) { unsigned int offset, length, value = 0; unsigned int type, pcrel, isym = 0; unsigned int usesym = 0; if(R_SCATTERED & rel->r_address) { scarel = (struct scattered_relocation_info*)rel; offset = (unsigned int)scarel->r_address; length = scarel->r_length; pcrel = scarel->r_pcrel; type = scarel->r_type; value = scarel->r_value; } else { value = isym = rel->r_symbolnum; usesym = (rel->r_extern); offset = rel->r_address; length = rel->r_length; pcrel = rel->r_pcrel; type = rel->r_type; } slide = offset - start_offset; if (!(offset >= start_offset && offset < start_offset + size)) continue; /* not in our range */ sym_name = get_reloc_name(rel, &sslide); if(usesym && symtab[isym].n_type & N_STAB) continue; /* don't handle STAB (debug sym) */ if (sym_name && strstart(sym_name, "__op_jmp", &p)) { int n; n = strtol(p, NULL, 10); fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n", n, slide); continue; /* Nothing more to do */ } if(!sym_name) { fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n", name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type); continue; /* dunno how to handle without final_sym_name */ } get_reloc_expr(final_sym_name, sizeof(final_sym_name), sym_name); switch(type) { case PPC_RELOC_BR24: if (!strstart(sym_name,"__op_gen_label",&p)) { fprintf(outfile, "{\n"); fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide); 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", slide, slide, name, sslide); fprintf(outfile, "}\n"); } else { fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n", slide, slide, final_sym_name, slide); } break; case PPC_RELOC_HI16: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n", slide, final_sym_name, sslide); break; case PPC_RELOC_LO16: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n", slide, final_sym_name, sslide); break; case PPC_RELOC_HA16: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n", slide, final_sym_name, sslide); break; default: error("unsupported powerpc relocation (%d)", type); } }#else#error unsupport object format#endif }#elif defined(HOST_S390) { char relname[256];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -