📄 dyngen.c
字号:
} }#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 parameres 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 name[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(name, sizeof(name), 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, name, addend); break; case R_386_PC32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", reloc_offset, name, 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, name, addend); break; case DISP32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n", reloc_offset, name, reloc_offset, addend); break; default: error("unsupported i386 relocation (%d)", type); }#else#error unsupport object format#endif } } }#elif defined(HOST_X86_64) { char name[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(name, sizeof(name), 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, name, addend); break; case R_X86_64_32S: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", reloc_offset, name, 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, name, reloc_offset, addend); break; default: error("unsupported X86_64 relocation (%d)", type); } } } }#elif defined(HOST_PPC) {#ifdef CONFIG_FORMAT_ELF char name[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(name, sizeof(name), 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, name, addend); break; case R_PPC_ADDR16_LO: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", reloc_offset, name, addend); break; case R_PPC_ADDR16_HI: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", reloc_offset, name, addend); break; case R_PPC_ADDR16_HA: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", reloc_offset, name, 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, name, 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 name[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(name, sizeof(name), sym_name); type = ELF32_R_TYPE(rel->r_info); addend = rel->r_addend; reloc_offset = rel->r_offset - start_offset; switch(type) { case R_390_32: fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", reloc_offset, name, addend); break; case R_390_16: fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", reloc_offset, name, addend); break; case R_390_8: fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", reloc_offset, name, addend); break; default: error("unsupported s390 relocation (%d)", type); } } } }#elif defined(HOST_ALPHA) { for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { int type; long reloc_offset; type = ELF64_R_TYPE(rel->r_info); sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; reloc_offset = rel->r_offset - start_offset; switch (type) { case R_ALPHA_GPDISP: /* The gp is just 32 bit, and never changes, so it's easiest to emit it as an immediate instead of constructing it from the pv or ra. */ fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", reloc_offset); fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", reloc_offset + (int)rel->r_addend); break; case R_ALPHA_LITUSE: /* jsr to literal hint. Could be used to optimize to bsr. Ignore for now, since some called functions (libc) need pv to be set up. */ break; case R_ALPHA_HINT: /* Branch target prediction hint. Ignore for now. Should be already correct for in-function jumps. */ break; case R_ALPHA_LITERAL: /* Load a literal from the GOT relative to the gp. Since there's only a single gp, nothing is to be done. */ break; case R_ALPHA_GPRELHIGH: /* Handle fake relocations against __op_param symbol. Need to emit the high part of the immediate value instead. Other symbols need no special treatment. */ if (strstart(sym_name, "__op_param", &p)) fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", reloc_offset, p); break; case R_ALPHA_GPRELLOW: if (strstart(sym_name, "__op_param", &p)) fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", reloc_offset, p); break; case R_ALPHA_BRSGP: /* PC-relative jump. Tweak offset to skip the two instructions that try to set up the gp from the pv. */ fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld + 4) + 8);\n", reloc_offset, sym_name, reloc_offset); break; default: error("unsupported Alpha relocation (%d)", type); } } } }#elif defined(HOST_IA64) { unsigned long sym_idx; long code_offset; char name[256]; int type; long addend; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { sym_idx = ELF64_R_SYM(rel->r_info); if (rel->r_offset < start_offset || rel->r_offset >= start_offset + copy_size) continue; sym_name = (strtab + symtab[sym_idx].st_name); code_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] =" "%ld + (gen_code_ptr - gen_code_buf);\n", n, code_offset); continue; } get_reloc_expr(name, sizeof(name), sym_name); type = ELF64_R_TYPE(rel->r_info); addend = rel->r_addend; switch(type) { case R_IA64_IMM64: fprintf(outfile, " ia64_imm64(gen_code_ptr + %ld, " "%s + %ld);\n", code_offset, name, addend); break; case R_IA64_LTOFF22X: case R_IA64_LTOFF22: fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld," " %s + %ld, %d);\n", code_offset, name, addend, (type == R_IA64_LTOFF22X)); break; case R_IA64_LDXMOV: fprintf(outfile, " ia64_ldxmov(gen_code_ptr + %ld," " %s + %ld);\n", code_offset, name, addend); break; case R_IA64_PCREL21B: if (strstart(sym_name, "__op_gen_label", NULL)) { fprintf(outfile, " ia64_imm21b(gen_code_ptr + %ld," " (long) (%s + %ld -\n\t\t" "((long) gen_code_ptr + %ld)) >> 4);\n", code_offset, name, addend, code_offset & ~0xfUL); } else { fprintf(outfile, " IA64
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -