Exemplo n.º 1
0
/* code cache to hold the call to "clean_call" and return to DR code cache */
static void
code_cache_init(void)
{
    void         *drcontext;
    instrlist_t  *ilist;
    instr_t      *where;
    byte         *end;

    drcontext  = dr_get_current_drcontext();
    code_cache = dr_nonheap_alloc(PAGE_SIZE,
                                  DR_MEMPROT_READ  |
                                  DR_MEMPROT_WRITE |
                                  DR_MEMPROT_EXEC);
    ilist = instrlist_create(drcontext);
    /* The lean procecure simply performs a clean call, and then jump back */
    /* jump back to the DR's code cache */
    where = INSTR_CREATE_jmp_ind(drcontext, opnd_create_reg(DR_REG_XCX));
    instrlist_meta_append(ilist, where);
    /* clean call */
    dr_insert_clean_call(drcontext, ilist, where, (void *)clean_call_ins_trace, false, 0);
    /* Encodes the instructions into memory and then cleans up. */
    end = instrlist_encode(drcontext, ilist, code_cache, false);
    DR_ASSERT((end - code_cache) < PAGE_SIZE);
    instrlist_clear_and_destroy(drcontext, ilist);
    /* set the memory as just +rx now */
    dr_memory_protect(code_cache, PAGE_SIZE, DR_MEMPROT_READ | DR_MEMPROT_EXEC);
}
Exemplo n.º 2
0
static void
callee_info_free(dcontext_t *dcontext, callee_info_t *ci)
{
    if (ci->ilist != NULL) {
        ASSERT(ci->opt_inline);
        instrlist_clear_and_destroy(GLOBAL_DCONTEXT, ci->ilist);
    }
    HEAP_TYPE_FREE(GLOBAL_DCONTEXT, ci, callee_info_t, ACCT_CLEANCALL, PROTECTED);
}
Exemplo n.º 3
0
static void
test_instr_as_immed(void)
{
    void *drcontext = dr_get_current_drcontext();
    instrlist_t *ilist = instrlist_create(drcontext);
    byte *pc;
    instr_t *ins0, *ins1, *ins2;
    opnd_t opnd;
    byte *highmem = PREFERRED_ADDR;
    pc = dr_raw_mem_alloc(PAGE_SIZE, DR_MEMPROT_READ|DR_MEMPROT_WRITE|
                               DR_MEMPROT_EXEC, highmem);
    ASSERT(pc == highmem);

    /* Test push_imm of instr */
    ins0 = INSTR_CREATE_nop(drcontext);
    instrlist_append(ilist, ins0);
    instrlist_insert_push_instr_addr(drcontext, ins0, highmem,
                                     ilist, NULL, &ins1, &ins2);
    ASSERT(ins2 != NULL);
    instrlist_append(ilist, INSTR_CREATE_pop
                     (drcontext, opnd_create_reg(DR_REG_RAX)));
    instrlist_append(ilist, INSTR_CREATE_ret(drcontext));
    pc = instrlist_encode(drcontext, ilist, highmem, true);
    instrlist_clear(drcontext, ilist);
    ASSERT(pc < highmem + PAGE_SIZE);
    pc = ((byte* (*)(void))highmem)();
    ASSERT(pc == highmem);

    /* Test mov_imm of instr */
    ins0 = INSTR_CREATE_nop(drcontext);
    instrlist_append(ilist, ins0);
    /* Beyond TOS, but a convenient mem dest */
    opnd = opnd_create_base_disp(DR_REG_RSP, DR_REG_NULL, 0, -8, OPSZ_8);
    instrlist_insert_mov_instr_addr(drcontext, ins0, highmem, opnd,
                                    ilist, NULL, &ins1, &ins2);
    ASSERT(ins2 != NULL);
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_RAX), opnd));
    instrlist_append(ilist, INSTR_CREATE_ret(drcontext));
    pc = instrlist_encode(drcontext, ilist, highmem, true);
    instrlist_clear(drcontext, ilist);
    ASSERT(pc < highmem + PAGE_SIZE);
    pc = ((byte* (*)(void))highmem)();
    ASSERT(pc == highmem);

    instrlist_clear_and_destroy(drcontext, ilist);
    dr_raw_mem_free(highmem, PAGE_SIZE);
}
Exemplo n.º 4
0
DR_EXPORT void
dr_init(client_id_t id)
{
    /* Generate the "slowpath" which just returns to eax. */
    void *dc = dr_get_current_drcontext();
    instrlist_t *ilist = instrlist_create(dc);
    PRE(ilist, NULL, INSTR_CREATE_jmp_ind(dc, opnd_create_reg(DR_REG_XAX)));
    slowpath = dr_nonheap_alloc(SLOWPATH_SIZE, (DR_MEMPROT_READ|
                                                DR_MEMPROT_WRITE|
                                                DR_MEMPROT_EXEC));
    instrlist_encode(dc, ilist, slowpath, false /*no relative jumps*/);
    instrlist_clear_and_destroy(dc, ilist);

    dr_register_bb_event(event_bb);
    dr_register_exit_event(event_exit);
}
Exemplo n.º 5
0
static void
reachability_test(void)
{
    void *drcontext = dr_get_current_drcontext();
    instrlist_t *ilist = instrlist_create(drcontext);
    byte *gencode = (byte *)
        dr_nonheap_alloc(PAGE_SIZE, DR_MEMPROT_READ|DR_MEMPROT_WRITE|DR_MEMPROT_EXEC);
    byte *pc;
    int res;
    byte *highmem = PREFERRED_ADDR;
    pc = dr_raw_mem_alloc(PAGE_SIZE, DR_MEMPROT_READ|DR_MEMPROT_WRITE|
                               DR_MEMPROT_EXEC, highmem);
    ASSERT(pc == highmem);

    dr_fprintf(STDERR, "  reachability test...");

    /* Test auto-magically turning rip-rel that won't reach but targets xax
     * into absmem.
     */
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_EAX),
                      opnd_create_rel_addr(highmem, OPSZ_4)));
    instrlist_append(ilist, INSTR_CREATE_ret(drcontext));
    pc = instrlist_encode(drcontext, ilist, gencode, false);
    instrlist_clear(drcontext, ilist);
    ASSERT(pc < gencode + PAGE_SIZE);
    *(int*)highmem = 0x12345678;
    res = ((int (*)(void))gencode)();
    ASSERT(res == 0x12345678);

    /* Test auto-magically turning a reachable absmem into a rip-rel. */
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_ECX),
                      opnd_create_abs_addr(highmem + 0x800, OPSZ_4)));
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_EAX),
                      opnd_create_reg(DR_REG_ECX)));
    instrlist_append(ilist, INSTR_CREATE_ret(drcontext));
    pc = instrlist_encode(drcontext, ilist, highmem, false);
    instrlist_clear(drcontext, ilist);
    ASSERT(pc < highmem + PAGE_SIZE);
    *(int*)(highmem + 0x800) = 0x12345678;
    res = ((int (*)(void))highmem)();
    ASSERT(res == 0x12345678);

    dr_raw_mem_free(highmem, PAGE_SIZE);

    /* Test targeting upper 2GB of low 4GB */
    highmem = dr_raw_mem_alloc(PAGE_SIZE, DR_MEMPROT_READ|DR_MEMPROT_WRITE|
                               DR_MEMPROT_EXEC, (byte *)0xabcd0000);
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_ECX),
                      opnd_create_abs_addr(highmem, OPSZ_4)));
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_EAX),
                      opnd_create_reg(DR_REG_ECX)));
    instrlist_append(ilist, INSTR_CREATE_ret(drcontext));
    pc = instrlist_encode(drcontext, ilist, gencode, false);
    instrlist_clear(drcontext, ilist);
    ASSERT(pc < gencode + PAGE_SIZE);
    *(int*)highmem = 0x12345678;
    res = ((int (*)(void))gencode)();
    ASSERT(res == 0x12345678);
    dr_raw_mem_free(highmem, PAGE_SIZE);

    /* Test targeting lower 2GB of low 4GB */
    highmem = dr_raw_mem_alloc(PAGE_SIZE, DR_MEMPROT_READ|DR_MEMPROT_WRITE|
                               DR_MEMPROT_EXEC, (byte *)0x143d0000);
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_ECX),
                      opnd_create_abs_addr(highmem, OPSZ_4)));
    instrlist_append(ilist, INSTR_CREATE_mov_ld
                     (drcontext, opnd_create_reg(DR_REG_EAX),
                      opnd_create_reg(DR_REG_ECX)));
    instrlist_append(ilist, INSTR_CREATE_ret(drcontext));
    pc = instrlist_encode(drcontext, ilist, gencode, false);
    instrlist_clear(drcontext, ilist);
    ASSERT(pc < gencode + PAGE_SIZE);
    *(int*)highmem = 0x12345678;
    res = ((int (*)(void))gencode)();
    ASSERT(res == 0x12345678);
    dr_raw_mem_free(highmem, PAGE_SIZE);

    instrlist_clear_and_destroy(drcontext, ilist);
    dr_nonheap_free(gencode, PAGE_SIZE);

    test_instr_as_immed();

    dr_fprintf(STDERR, "success\n");
}
Exemplo n.º 6
0
/* make sure the following are consistent (though they could still all be wrong :))
 * with respect to instr length and opcode:
 * - decode_fast
 * - decode
 * - INSTR_CREATE_
 * - encode
 */
static void
test_all_opcodes(void *dc)
{
    byte *pc, *next_pc;
    byte *end;
    instrlist_t *ilist = instrlist_create(dc);
    instr_t *instr;

    /* we cannot pass on variadic args as separate args to another
     * macro, so we must split ours by # args (xref PR 208603)
     */

#   define MEMARG(sz) (opnd_create_base_disp(REG_XCX, REG_NULL, 0, 0x37, sz))
#   define IMMARG(sz)  opnd_create_immed_int(37, sz)
#   define TGTARG      opnd_create_instr(instrlist_last(ilist))
#   define REGARG(reg) opnd_create_reg(REG_##reg)
#   define X86_ONLY    1
#   define X64_ONLY    2

#   define OPCODE(opc, icnm, ...) \
    int len_##icnm;
#   include "ir_0args.h"
#   include "ir_1args.h"
#   include "ir_2args.h"
#   include "ir_3args.h"
#   include "ir_4args.h"
#   undef OPCODE

    /* we can encode+fast-decode some instrs cross-platform but we
     * leave that testing to the regression run on that platform */ 

#   define OPCODE(opc, icnm, flags) do { \
    if ((flags & IF_X64_ELSE(X86_ONLY, X64_ONLY)) == 0) { \
        instrlist_append(ilist, INSTR_CREATE_##icnm(dc)); \
        len_##icnm = instr_length(dc, instrlist_last(ilist)); \
    } } while (0);
#   include "ir_0args.h"
#   undef OPCODE

#   define OPCODE(opc, icnm, flags, arg1) do { \
    if ((flags & IF_X64_ELSE(X86_ONLY, X64_ONLY)) == 0) { \
        instrlist_append(ilist, INSTR_CREATE_##icnm(dc, arg1)); \
        len_##icnm = instr_length(dc, instrlist_last(ilist)); \
    } } while (0);
#   include "ir_1args.h"
#   undef OPCODE

#   define OPCODE(opc, icnm, flags, arg1, arg2) do { \
    if ((flags & IF_X64_ELSE(X86_ONLY, X64_ONLY)) == 0) { \
        instrlist_append(ilist, INSTR_CREATE_##icnm(dc, arg1, arg2)); \
        len_##icnm = instr_length(dc, instrlist_last(ilist)); \
    } } while (0);
#   include "ir_2args.h"
#   undef OPCODE

#   define OPCODE(opc, icnm, flags, arg1, arg2, arg3) do { \
    if ((flags & IF_X64_ELSE(X86_ONLY, X64_ONLY)) == 0) { \
        instrlist_append(ilist, INSTR_CREATE_##icnm(dc, arg1, arg2, arg3)); \
        len_##icnm = instr_length(dc, instrlist_last(ilist)); \
    } } while (0);
#   include "ir_3args.h"
#   undef OPCODE

#   define OPCODE(opc, icnm, flags, arg1, arg2, arg3, arg4) do { \
    if ((flags & IF_X64_ELSE(X86_ONLY, X64_ONLY)) == 0) { \
        instrlist_append(ilist, INSTR_CREATE_##icnm(dc, arg1, arg2, arg3, arg4)); \
        len_##icnm = instr_length(dc, instrlist_last(ilist)); \
    } } while (0);
#   include "ir_4args.h"
#   undef OPCODE

    end = instrlist_encode(dc, ilist, buf, false);

    instr = instr_create(dc);
    pc = buf;

#   define OPCODE(opc, icnm, flags, ...) do { \
    if ((flags & IF_X64_ELSE(X86_ONLY, X64_ONLY)) == 0 && len_##icnm != 0) { \
        instr_reset(dc, instr); \
        next_pc = decode(dc, pc, instr); \
        ASSERT((next_pc - pc) == decode_sizeof(dc, pc, NULL _IF_X64(NULL))); \
        ASSERT((next_pc - pc) == len_##icnm); \
        ASSERT(instr_get_opcode(instr) == OP_##opc); \
        pc = next_pc; \
    } } while (0);
#   include "ir_0args.h"
#   include "ir_1args.h"
#   include "ir_2args.h"
#   include "ir_3args.h"
#   include "ir_4args.h"
#   undef OPCODE

#if VERBOSE
    for (pc = buf; pc < end; )
        pc = disassemble_with_info(dc, pc, STDOUT, true, true);
#endif

    instr_destroy(dc, instr);
    instrlist_clear_and_destroy(dc, ilist);
}
Exemplo n.º 7
0
void Shade::detour(void *address, void *target, void *&trampoline)
{
    const size_t instr_max = 17;

    auto list = instrlist_create(dr);

    byte instr_data[instr_max];

    byte *current = (byte *)address;
    byte *min_pos = (byte *)address + 5;
    size_t size = 0;

    while(current < min_pos)
    {
        read(current, instr_data, instr_max);

        auto instr = instr_create(dr);

        byte *decoded = decode_from_copy(dr, instr_data, current, instr);

        if(!decoded)
            error("Unknown instruction");

        instrlist_append(list, instr);
        instr_make_persistent(dr, instr);

        current += (size_t)(decoded - instr_data);

        size += instr_length(dr, instr);
    }

    auto instr = INSTR_CREATE_jmp(dr, opnd_create_pc(current));
    size += instr_length(dr, instr);
    instrlist_append(list, instr);

    auto local_trampoline = alloca(size);

    if(!local_trampoline)
        error("Out of memory");

    void *remote = code_section.allocate(size, 4);

    if(!instrlist_encode_to_copy(dr, list, (byte *)local_trampoline, (byte *)remote, 0, true))
        error("Unable to encode instructions");

    instrlist_clear_and_destroy(dr, list);

    write(remote, local_trampoline, size);

    trampoline = remote;

    char code[5];

    DWORD offset = (size_t)target - (size_t)address - 5;

    code[0] = 0xE9;

    *(DWORD *)(code + 1) = offset;

    access(address, 5, [&] {
        write(address, code, 5);
    });
}