Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
void
watchpoint_indirect_call_event(dcontext_t *drcontext, instrlist_t *ilist, instr_t *instr,
                     instr_t *next_instr, bool mangle_calls, uint flags)
{
    opnd_t instr_opnd;
    reg_id_t base_reg;
    unsigned long used_registers = 0;
    app_pc pc;
    struct memory_operand_modifier ops = {0};

    instr_t *begin_instrumenting = INSTR_CREATE_label(drcontext);
    instr_t *done_instrumenting = INSTR_CREATE_label(drcontext);
    instr_t *nop = INSTR_CREATE_nop(drcontext);
    instr_t *emulated;


    memset(&ops, 0, sizeof(struct memory_operand_modifier));

    if(instr_reads_memory(instr)) {
        instr_opnd = instr_get_src(instr, 0);
        if (opnd_is_rel_addr(instr_opnd) || opnd_is_abs_addr(instr_opnd)) {

        }else if (opnd_is_base_disp(instr_opnd)) {

            for_each_src_operand(instr, &ops, (opnd_callback_t *) memory_src_operand_finder);
           // base_reg = opnd_get_reg(instr_opnd);

            switch(ops.found_operand.value.base_disp.base_reg) {
                case DR_REG_RSP: case DR_REG_ESP: case DR_REG_SP:
                case DR_REG_RBP: case DR_REG_EBP: case DR_REG_BP:
                    return;
                default:
                  break;
            }

            collect_regs(&used_registers, instr, instr_num_srcs, instr_get_src );
            collect_regs(&used_registers, instr, instr_num_dsts, instr_get_dst );

            reg_id_t reg_watched_addr = get_next_free_reg(&used_registers);
            opnd_t opnd_watched_addr = opnd_create_reg(reg_watched_addr);

            reg_id_t reg_unwatched_addr = get_next_free_reg(&used_registers);
            opnd_t opnd_unwatched_addr = opnd_create_reg(reg_unwatched_addr);

            PRE(ilist, instr, begin_instrumenting);
            PRE(ilist, instr, INSTR_CREATE_push(drcontext, opnd_watched_addr));
            PRE(ilist, instr, INSTR_CREATE_push(drcontext, opnd_unwatched_addr));
            PRE(ilist, instr, INSTR_CREATE_pushf(drcontext));
            PRE(ilist, instr, INSTR_CREATE_lea(drcontext, opnd_watched_addr, opnd_create_base_disp(opnd_get_base(ops.found_operand),
                                                        opnd_get_index(ops.found_operand), opnd_get_scale(ops.found_operand),
                                                        opnd_get_disp(ops.found_operand), OPSZ_lea)));

            PRE(ilist, instr, INSTR_CREATE_mov_imm(drcontext, opnd_unwatched_addr,
                                            OPND_CREATE_INT64(WATCHPOINT_INDEX_MASK)));
            PRE(ilist, instr, INSTR_CREATE_or(drcontext, opnd_unwatched_addr, opnd_watched_addr));

            emulated = instr_clone(drcontext, instr);
            emulated->translation = 0;

            ops.replacement_operand = opnd_create_base_disp(
                    reg_unwatched_addr, DR_REG_NULL,1, 0 , ops.found_operand.size);

            for_each_operand(emulated, &ops, (opnd_callback_t *) memory_operand_replacer);

            PRE(ilist, instr, INSTR_CREATE_popf(drcontext));
            PRE(ilist, instr, emulated);
            PRE(ilist, instr, INSTR_CREATE_pop(drcontext, opnd_unwatched_addr));
            PRE(ilist, instr, INSTR_CREATE_pop(drcontext, opnd_watched_addr));

            PRE(ilist, instr, INSTR_CREATE_jmp_short(drcontext,
                    opnd_create_instr(done_instrumenting)));

            pc = instr->translation;
            instr->translation = 0; // hack!
            instr_being_modified(instr, false);
            instr_set_ok_to_mangle(instr, false);

            if(NULL != pc){
                nop->translation = pc + instr->length;
            }
            POST(ilist, instr, nop);
            POST(ilist, instr, done_instrumenting);

        }
    }
}