📄 dyngen.c.svn-base
字号:
exit(1); } memset(plt, 0, sizeof(*plt)); plt->name = strdup(name); plt->addend = addend; /* append to plt-list: */ if (prev) prev->next = plt; else plt_list = plt; return index;}#endif#ifdef HOST_ARMint arm_emit_ldr_info(const char *name, unsigned long start_offset, FILE *outfile, uint8_t *p_start, uint8_t *p_end, ELF_RELOC *relocs, int nb_relocs){ uint8_t *p; uint32_t insn; int offset, min_offset, pc_offset, data_size, spare, max_pool; uint8_t data_allocated[1024]; unsigned int data_index; int type; memset(data_allocated, 0, sizeof(data_allocated)); p = p_start; min_offset = p_end - p_start; spare = 0x7fffffff; while (p < p_start + min_offset) { insn = get32((uint32_t *)p); /* TODO: Armv5e ldrd. */ /* TODO: VFP load. */ if ((insn & 0x0d5f0000) == 0x051f0000) { /* ldr reg, [pc, #im] */ offset = insn & 0xfff; if (!(insn & 0x00800000)) offset = -offset; max_pool = 4096; type = 0; } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) { /* FPA ldf. */ offset = (insn & 0xff) << 2; if (!(insn & 0x00800000)) offset = -offset; max_pool = 1024; type = 1; } else if ((insn & 0x0fff0000) == 0x028f0000) { /* Some gcc load a doubleword immediate with add regN, pc, #imm ldmia regN, {regN, regM} Hope and pray the compiler never generates somethin like add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */ int r; r = (insn & 0xf00) >> 7; offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r)); max_pool = 1024; type = 2; } else { max_pool = 0; type = -1; } if (type >= 0) { /* PC-relative load needs fixing up. */ if (spare > max_pool - offset) spare = max_pool - offset; if ((offset & 3) !=0) error("%s:%04x: pc offset must be 32 bit aligned", name, start_offset + p - p_start); if (offset < 0) error("%s:%04x: Embedded literal value", name, start_offset + p - p_start); pc_offset = p - p_start + offset + 8; if (pc_offset <= (p - p_start) || pc_offset >= (p_end - p_start)) error("%s:%04x: pc offset must point inside the function code", name, start_offset + p - p_start); if (pc_offset < min_offset) min_offset = pc_offset; if (outfile) { /* The intruction position */ fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", p - p_start); /* The position of the constant pool data. */ data_index = ((p_end - p_start) - pc_offset) >> 2; fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n", data_index); fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type); fprintf(outfile, " arm_ldr_ptr++;\n"); } } p += 4; } /* Copy and relocate the constant pool data. */ data_size = (p_end - p_start) - min_offset; if (data_size > 0 && outfile) { spare += min_offset; fprintf(outfile, " arm_data_ptr -= %d;\n", data_size >> 2); fprintf(outfile, " arm_pool_ptr -= %d;\n", data_size); fprintf(outfile, " if (arm_pool_ptr > gen_code_ptr + %d)\n" " arm_pool_ptr = gen_code_ptr + %d;\n", spare, spare); data_index = 0; for (pc_offset = min_offset; pc_offset < p_end - p_start; pc_offset += 4) { ELF_RELOC *rel; int i, addend, type; const char *sym_name; char relname[1024]; /* data value */ addend = get32((uint32_t *)(p_start + pc_offset)); relname[0] = '\0'; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { if (rel->r_offset == (pc_offset + start_offset)) { sym_name = get_rel_sym_name(rel); /* the compiler leave some unnecessary references to the code */ get_reloc_expr(relname, sizeof(relname), sym_name); type = ELF32_R_TYPE(rel->r_info); if (type != R_ARM_ABS32) error("%s: unsupported data relocation", name); break; } } fprintf(outfile, " arm_data_ptr[%d] = 0x%x", data_index, addend); if (relname[0] != '\0') fprintf(outfile, " + %s", relname); fprintf(outfile, ";\n"); data_index++; } } if (p == p_start) goto arm_ret_error; p -= 4; insn = get32((uint32_t *)p); /* The last instruction must be an ldm instruction. There are several forms generated by gcc: ldmib sp, {..., pc} (implies a sp adjustment of +4) ldmia sp, {..., pc} ldmea fp, {..., pc} */ if ((insn & 0xffff8000) == 0xe99d8000) { if (outfile) { fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n", p - p_start); } p += 4; } else if ((insn & 0xffff8000) != 0xe89d8000 && (insn & 0xffff8000) != 0xe91b8000) { arm_ret_error: if (!outfile) printf("%s: invalid epilog\n", name); } return p - p_start;}#endif#define MAX_ARGS 3/* generate op code */void gen_code(const char *name, host_ulong offset, host_ulong size, FILE *outfile, int gen_switch){ int copy_size = 0; uint8_t *p_start, *p_end; host_ulong start_offset; int nb_args, i, n; uint8_t args_present[MAX_ARGS]; const char *sym_name, *p; EXE_RELOC *rel; /* Compute exact size excluding prologue and epilogue instructions. * Increment start_offset to skip epilogue instructions, then compute * copy_size the indicate the size of the remaining instructions (in * bytes). */ p_start = text + offset; p_end = p_start + size; start_offset = offset;#if defined(HOST_I386) || defined(HOST_X86_64)#ifdef CONFIG_FORMAT_COFF { uint8_t *p; p = p_end - 1; if (p == p_start) error("empty code for %s", name); while (*p != 0xc3) { p--; if (p <= p_start) error("ret or jmp expected at the end of %s", name); } copy_size = p - p_start; }#else { int len; len = p_end - p_start; if (len == 0) error("empty code for %s", name); if (p_end[-1] == 0xc3) { len--; } else { error("ret or jmp expected at the end of %s", name); } copy_size = len; }#endif#elif defined(HOST_PPC) { uint8_t *p; p = (void *)(p_end - 4); if (p == p_start) error("empty code for %s", name); if (get32((uint32_t *)p) != 0x4e800020) error("blr expected at the end of %s", name); copy_size = p - p_start; }#elif defined(HOST_S390) { uint8_t *p; p = (void *)(p_end - 2); if (p == p_start) error("empty code for %s", name); if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0) error("br expected at the end of %s", name); copy_size = p - p_start; }#elif defined(HOST_ALPHA) { uint8_t *p; p = p_end - 4;#if 0 /* XXX: check why it occurs */ if (p == p_start) error("empty code for %s", name);#endif if (get32((uint32_t *)p) != 0x6bfa8001) error("ret expected at the end of %s", name); copy_size = p - p_start; }#elif defined(HOST_IA64) { uint8_t *p; p = (void *)(p_end - 4); if (p == p_start) error("empty code for %s", name); /* br.ret.sptk.many b0;; */ /* 08 00 84 00 */ if (get32((uint32_t *)p) != 0x00840008) error("br.ret.sptk.many b0;; expected at the end of %s", name); copy_size = p_end - p_start; }#elif defined(HOST_SPARC) {#define INSN_SAVE 0x9de3a000#define INSN_RET 0x81c7e008#define INSN_RETL 0x81c3e008#define INSN_RESTORE 0x81e80000#define INSN_RETURN 0x81cfe008#define INSN_NOP 0x01000000#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp uint32_t start_insn, end_insn1, end_insn2; uint8_t *p; p = (void *)(p_end - 8); if (p <= p_start) error("empty code for %s", name); start_insn = get32((uint32_t *)(p_start + 0x0)); end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); if (((start_insn & ~0x1fff) == INSN_SAVE) || (start_insn & ~0x1fff) == INSN_ADD_SP) { p_start += 0x4; start_offset += 0x4; if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) /* SPARC v7: ret; restore; */ ; else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) /* SPARC v9: return; nop; */ ; else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) /* SPARC v7: retl; sub %sp, nn, %sp; */ ; else error("ret; restore; not found at end of %s", name); } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { ; } else { error("No save at the beginning of %s", name); }#if 0 /* Skip a preceeding nop, if present. */ if (p > p_start) { skip_insn = get32((uint32_t *)(p - 0x4)); if (skip_insn == INSN_NOP) p -= 4; }#endif copy_size = p - p_start; }#elif defined(HOST_SPARC64) {#define INSN_SAVE 0x9de3a000#define INSN_RET 0x81c7e008#define INSN_RETL 0x81c3e008#define INSN_RESTORE 0x81e80000#define INSN_RETURN 0x81cfe008#define INSN_NOP 0x01000000#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp uint32_t start_insn, end_insn1, end_insn2, skip_insn; uint8_t *p; p = (void *)(p_end - 8);#if 0 /* XXX: check why it occurs */ if (p <= p_start) error("empty code for %s", name);#endif start_insn = get32((uint32_t *)(p_start + 0x0)); end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); if (((start_insn & ~0x1fff) == INSN_SAVE) || (start_insn & ~0x1fff) == INSN_ADD_SP) { p_start += 0x4; start_offset += 0x4; if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) /* SPARC v7: ret; restore; */ ; else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) /* SPARC v9: return; nop; */ ; else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) /* SPARC v7: retl; sub %sp, nn, %sp; */ ; else error("ret; restore; not found at end of %s", name); } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { ; } else { error("No save at the beginning of %s", name); } /* Skip a preceeding nop, if present. */ if (p > p_start) { skip_insn = get32((uint32_t *)(p - 0x4)); if (skip_insn == 0x01000000) p -= 4; } copy_size = p - p_start; }#elif defined(HOST_ARM) { uint32_t insn; if ((p_end - p_start) <= 16) error("%s: function too small", name); if (get32((uint32_t *)p_start) != 0xe1a0c00d || (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 || get32((uint32_t *)(p_start + 8)) != 0xe24cb004) error("%s: invalid prolog", name); p_start += 12; start_offset += 12; insn = get32((uint32_t *)p_start); if ((insn & 0xffffff00) == 0xe24dd000) { /* Stack adjustment. Assume op uses the frame pointer. */ p_start -= 4; start_offset -= 4; } copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, relocs, nb_relocs); }#elif defined(HOST_M68K) { uint8_t *p; p = (void *)(p_end - 2); if (p == p_start) error("empty code for %s", name); // remove NOP's, probably added for alignment while ((get16((uint16_t *)p) == 0x4e71) && (p>p_start)) p -= 2; if (get16((uint16_t *)p) != 0x4e75) error("rts expected at the end of %s", name); copy_size = p - p_start; }#elif defined(HOST_MIPS) || defined(HOST_MIPS64) {#define INSN_RETURN 0x03e00008#define INSN_NOP 0x00000000 uint8_t *p = p_end; if (p < (p_start + 0x8)) { error("empty code for %s", name); } else { uint32_t end_insn1, end_insn2; p -= 0x8; end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP) error("jr ra not found at end of %s", name); } copy_size = p - p_start; }#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -