void check_opnd(opnd_t opnd, void *pc, int read, void *drcontext, dr_mcontext_t *mctx, void *prev_pc) { if (opnd_is_memory_reference(opnd) && opnd_is_base_disp(opnd)) add_hit(pc, opnd_size_in_bytes(opnd_get_size(opnd)), opnd_get_disp(opnd) + (void *)reg_get_value(opnd_get_base(opnd), mctx), read, drcontext, prev_pc); else if (opnd_is_memory_reference(opnd) && opnd_get_addr(opnd)) add_hit(pc, opnd_size_in_bytes(opnd_get_size(opnd)), opnd_get_addr(opnd), read, drcontext, prev_pc); // for now no other kind of memory reference was noticed to access heap data else if (opnd_is_memory_reference(opnd)) dr_printf("need to implem other memory ref\n"); }
static void test_instr_opnds(void *dc) { /* Verbose disasm looks like this: * 32-bit: * 0x080f1ae0 ff 25 e7 1a 0f 08 jmp 0x080f1ae7 * 0x080f1ae6 b8 ef be ad de mov $0xdeadbeef -> %eax * 0x080f1ae0 a0 e6 1a 0f 08 mov 0x080f1ae6 -> %al * 0x080f1ae5 b8 ef be ad de mov $0xdeadbeef -> %eax * 64-bit: * 0x00000000006b8de0 ff 25 02 00 00 00 jmp <rel> 0x00000000006b8de8 * 0x00000000006b8de6 48 b8 ef be ad de 00 mov $0x00000000deadbeef -> %rax * 00 00 00 * 0x00000000006b8de0 8a 05 02 00 00 00 mov <rel> 0x00000000006b8de8 -> %al * 0x00000000006b8de6 48 b8 ef be ad de 00 mov $0x00000000deadbeef -> %rax * 00 00 00 */ instrlist_t *ilist; instr_t *tgt, *instr; byte *pc; short disp; ilist = instrlist_create(dc); /* test mem instr as ind jmp target */ tgt = INSTR_CREATE_mov_imm(dc, opnd_create_reg(DR_REG_XAX), opnd_create_immed_int(0xdeadbeef, OPSZ_PTR)); /* skip rex+opcode */ disp = IF_X64_ELSE(2,1); instrlist_append(ilist, INSTR_CREATE_jmp_ind (dc, opnd_create_mem_instr(tgt, disp, OPSZ_PTR))); instrlist_append(ilist, tgt); pc = instrlist_encode(dc, ilist, buf, true/*instr targets*/); ASSERT(pc != NULL); instrlist_clear(dc, ilist); #if VERBOSE pc = disassemble_with_info(dc, buf, STDOUT, true, true); pc = disassemble_with_info(dc, pc, STDOUT, true, true); #endif pc = buf; instr = instr_create(dc); pc = decode(dc, pc, instr); ASSERT(pc != NULL); ASSERT(instr_get_opcode(instr) == OP_jmp_ind); #ifdef X64 ASSERT(opnd_is_rel_addr(instr_get_src(instr, 0))); ASSERT(opnd_get_addr(instr_get_src(instr, 0)) == pc + disp); #else ASSERT(opnd_is_base_disp(instr_get_src(instr, 0))); ASSERT(opnd_get_base(instr_get_src(instr, 0)) == REG_NULL); ASSERT(opnd_get_index(instr_get_src(instr, 0)) == REG_NULL); ASSERT(opnd_get_disp(instr_get_src(instr, 0)) == (ptr_int_t)pc + disp); #endif /* test mem instr as TYPE_O */ tgt = INSTR_CREATE_mov_imm(dc, opnd_create_reg(DR_REG_XAX), opnd_create_immed_int(0xdeadbeef, OPSZ_PTR)); /* skip rex+opcode */ disp = IF_X64_ELSE(2,1); instrlist_append(ilist, INSTR_CREATE_mov_ld (dc, opnd_create_reg(DR_REG_AL), opnd_create_mem_instr(tgt, disp, OPSZ_1))); instrlist_append(ilist, tgt); pc = instrlist_encode(dc, ilist, buf, true/*instr targets*/); ASSERT(pc != NULL); instrlist_clear(dc, ilist); #if VERBOSE pc = disassemble_with_info(dc, buf, STDOUT, true, true); pc = disassemble_with_info(dc, pc, STDOUT, true, true); #endif pc = buf; instr_reset(dc, instr); pc = decode(dc, pc, instr); ASSERT(pc != NULL); ASSERT(instr_get_opcode(instr) == OP_mov_ld); #ifdef X64 ASSERT(opnd_is_rel_addr(instr_get_src(instr, 0))); ASSERT(opnd_get_addr(instr_get_src(instr, 0)) == pc + disp); #else ASSERT(opnd_is_base_disp(instr_get_src(instr, 0))); ASSERT(opnd_get_base(instr_get_src(instr, 0)) == REG_NULL); ASSERT(opnd_get_index(instr_get_src(instr, 0)) == REG_NULL); ASSERT(opnd_get_disp(instr_get_src(instr, 0)) == (ptr_int_t)pc + disp); #endif instr_free(dc, instr); instrlist_destroy(dc, ilist); }
static instr_t * analyze_client_code(void *drcontext, instrlist_t *ilist, instr_t *where, ref_info_t *ref_info) { instr_t *next, *lea, *and, *cmp, *jcc, *sub; opnd_t ref, opnd; ref_cache_t *cache; reg_id_t reg; int pos, i; next = instr_get_next(where); if (next == NULL) return NULL; if (instr_get_opcode(where) != OP_lea) return next; /* lea [ref] => r1 */ ref = instr_get_src(where, 0); if (!opnd_is_base_disp(ref) || opnd_get_index(ref) != DR_REG_NULL) return next; lea = where; and = next; cmp = instr_get_next(and); jcc = instr_get_next(cmp); if (instr_get_app_pc(and) == NULL && instr_get_opcode(and) == OP_and && instr_get_app_pc(cmp) == NULL && instr_get_opcode(cmp) == OP_cmp && instr_get_app_pc(jcc) == NULL && instr_get_opcode(jcc) == OP_jz) { /* find pattern of * lea [ref] => reg * and 0xffffffff00000000 reg * cmp cache->tag reg * jz */ opnd = instr_get_src(cmp, 1); cache = opnd_get_addr(opnd) - offsetof(ref_cache_t, tag); for (i = 0; i < 10; ) { lea = instr_get_next(lea); if (!instr_is_label(lea)) i++; } DR_ASSERT(instr_get_opcode(lea) == OP_lea); } else if (instr_get_app_pc(next) == NULL && instr_get_opcode(next) == OP_sub) { opnd = instr_get_src(next, 0); cache = opnd_get_addr(opnd) - offsetof(ref_cache_t, offset); } else { return next; } reg = opnd_get_base(ref); UMBRA_REG_TO_POS(reg, pos); if (ref_info[pos].cache == NULL) { ref_info[pos].cache = cache; } else { sub = instr_get_next(lea); DR_ASSERT(instr_get_opcode(sub) == OP_sub); while (lea != where) { next = instr_get_next(where); instrlist_remove(ilist, where); instr_destroy(drcontext, where); where = next; } opnd = OPND_CREATE_ABSMEM((void *)(reg_t)ref_info[pos].cache + offsetof(ref_cache_t, offset), OPSZ_PTR); instr_set_src(sub, 0, opnd); if (proc_info.client.app_unit_bits > 0 && proc_info.client.shd_unit_bits != 0) next = instr_get_next(sub); /* reg & mask => reg */ if (proc_info.client.orig_addr) { next = instr_get_next(next); /* mov reg => r2 */ next = instr_get_next(next); /* r2 & bit_mask => r2 */ } } next = instr_get_next(lea); return instr_get_next(next); }