Beispiel #1
0
static inline void
instr_set_0dst_2src(dcontext_t *dc, instr_t *instr, int op,
                    opnd_t src0, opnd_t src1)
{
    instr_set_opcode(instr, op);
    instr_set_num_opnds(dc, instr, 0, 2);
    instr_set_src(instr, 0, src0);
    instr_set_src(instr, 1, src1);
}
Beispiel #2
0
static inline void
instr_set_1dst_3src(dcontext_t *dc, instr_t *instr, int op,
                    opnd_t dst0, opnd_t src0, opnd_t src1, opnd_t src2)
{
    instr_set_opcode(instr, op);
    instr_set_num_opnds(dc, instr, 1, 3);
    instr_set_dst(instr, 0, dst0);
    instr_set_src(instr, 0, src0);
    instr_set_src(instr, 1, src1);
    instr_set_src(instr, 2, src2);
}
Beispiel #3
0
instrlist_t*
instrlist_clone(dcontext_t *dcontext, instrlist_t *old)
{
    instr_t *inst, *copy;
    instrlist_t *newlist = instrlist_create(dcontext);

    inst = instrlist_first(old);
    while (inst != NULL) {
        copy = instr_clone(dcontext, inst);
        /* to copy instr targets we temporarily clobber note field */
        instr_set_note(inst, (void *)copy);
        instrlist_append(newlist, copy);
        inst = instr_get_next(inst);
    }

    /* Fix up instr src if it is an instr and restore note field */
    /* Note: we do not allows instruction update code cache,
     * which is very dangerous.
     * So we do not support instr as dst opnd and won't fix up here if any.
     */
    for (inst = instrlist_first(old), copy = instrlist_first(newlist);
            inst != NULL && copy != NULL;
            inst = instr_get_next(inst), copy = instr_get_next(copy)) {
        int i;
        for (i = 0; i < inst->num_srcs; i++) {
            instr_t *tgt;
            opnd_t   op = instr_get_src(copy, i);
            if (!opnd_is_instr(op))
                continue;
            CLIENT_ASSERT(opnd_get_instr(op) != NULL,
                          "instrlist_clone: NULL instr operand");
            tgt = (instr_t *) instr_get_note(opnd_get_instr(op));
            CLIENT_ASSERT(tgt != NULL,
                          "instrlist_clone: operand instr not in instrlist");
            if (opnd_is_far_instr(op)) {
                instr_set_src(copy, i,
                              opnd_create_far_instr
                              (opnd_get_segment_selector(op), tgt));
            } else
                instr_set_src(copy, i,
                              opnd_create_instr(tgt));
        }
    }
    for (inst = instrlist_first(old), copy = instrlist_first(newlist);
            inst != NULL && copy != NULL;
            inst = instr_get_next(inst), copy = instr_get_next(copy)) {
        /* restore note field */
        instr_set_note(inst, instr_get_note(copy));
    }
#ifdef CLIENT_INTERFACE
    newlist->fall_through_bb = old->fall_through_bb;
#endif
    return newlist;
}
Beispiel #4
0
static void
instr_create_ldstex(dcontext_t *dcontext, int len, uint *pc, instr_t *instr,
                    OUT instr_t *instr_ldstex)
{
    int num_dsts = 0;
    int num_srcs = 0;
    int i, d, s, j;

    for (i = 0; i < len; i++) {
        ASSERT(instr[i].length == AARCH64_INSTR_SIZE &&
               instr[i].bytes == instr[0].bytes + AARCH64_INSTR_SIZE * i);
        num_dsts += instr_num_dsts(&instr[i]);
        num_srcs += instr_num_srcs(&instr[i]);
    }
    instr_set_opcode(instr_ldstex, OP_ldstex);
    instr_set_num_opnds(dcontext, instr_ldstex, num_dsts, num_srcs);
    d = 0;
    s = 0;
    for (i = 0; i < len; i++) {
        int dsts = instr_num_dsts(&instr[i]);
        int srcs = instr_num_srcs(&instr[i]);
        for (j = 0; j < dsts; j++)
            instr_set_dst(instr_ldstex, d++, instr_get_dst(&instr[i], j));
        for (j = 0; j < srcs; j++)
            instr_set_src(instr_ldstex, s++, instr_get_src(&instr[i], j));
    }
    ASSERT(d == num_dsts && s == num_srcs);
    /* Set raw bits to original encoding. */
    instr_set_raw_bits(instr_ldstex, instr[0].bytes, len * AARCH64_INSTR_SIZE);
    /* Conservatively assume all flags are read and written. */
    instr_ldstex->eflags = EFLAGS_READ_ALL | EFLAGS_WRITE_ALL;
    instr_set_eflags_valid(instr_ldstex, true);
}
Beispiel #5
0
void
modify_instr_for_relocations(void *drcontext, instr_t *inst,
                             ptr_uint_t *immed, ptr_uint_t *disp)
{
    int i;
    ptr_uint_t limmed = 0, ldisp = 0;
    for (i = instr_num_srcs(inst) - 1; i >= 0; i--) {
        opnd_t opnd = instr_get_src(inst, i);
        if (opnd_is_immed_int(opnd) && opnd_get_immed_int(opnd) > 0x10000) {
            if (limmed != 0) {
                ASSERT(false);
            } else {
                limmed = opnd_get_immed_int(opnd);
            }
            instr_set_src(inst, i, opnd_create_immed_int(0, opnd_get_size(opnd)));
        }
        if (opnd_is_base_disp(opnd) && opnd_get_disp(opnd) > 0x10000) {
            if (ldisp != 0 && ldisp != opnd_get_disp(opnd)) {
                ASSERT(false);
            } else {
                ldisp = opnd_get_disp(opnd);
            }
            instr_set_src(inst, i, opnd_create_base_disp(opnd_get_base(opnd), opnd_get_index(opnd), opnd_get_scale(opnd), 0, opnd_get_size(opnd)));
        }
    }
    for (i = instr_num_dsts(inst) - 1; i >= 0; i--) {
        opnd_t opnd = instr_get_dst(inst, i);
        ASSERT(!opnd_is_immed(opnd));
        if (opnd_is_base_disp(opnd) && opnd_get_disp(opnd) > 0x10000) {
            if (ldisp != 0 && ldisp != opnd_get_disp(opnd)) {
                ASSERT(false);
            } else {
                ldisp = opnd_get_disp(opnd);
            }
            instr_set_dst(inst, i, opnd_create_base_disp(opnd_get_base(opnd), opnd_get_index(opnd), opnd_get_scale(opnd), 0, opnd_get_size(opnd)));
        }
    }
    if (limmed != 0)
        *immed = limmed;
    if (ldisp != 0)
        *disp = ldisp; 
}
Beispiel #6
0
/* First tried something like this, but we hit too many issues in decode and encode */
bool
compare_pages(void *drcontext, byte *start1, byte *start2)
{
    byte *p1 = start1, *p2 = start2;
    int skipped_bytes = 0, identical_skipped_bytes = 0;

    while (p1 < start1 + PAGE_SIZE) {
        int instr_size = decode_sizeof(drcontext, p1, NULL _IF_X64(NULL));
        if (p1 + instr_size > start1 + PAGE_SIZE) {
            /* We're overlapping the end of the page, skip these. */
            int end_skip = start1 + PAGE_SIZE - p1;
            VVERBOSE_PRINT("Passing PAGE_END %d bytes", end_skip);
            skipped_bytes += end_skip;
            if (memcmp(p1, p2, end_skip) == 0)
                identical_skipped_bytes += end_skip;
            break;
        }
        if (decode_sizeof(drcontext, p2, NULL _IF_X64(NULL)) != instr_size) {
            VVERBOSE_PRINT("Instruction alignment mismatch\n");
            return false;
        }
        /* assumption - instructions <= 4 bytes in size won't have relocations */
        if (instr_size < 5) {
            if (memcmp(p1, p2, instr_size) != 0) {
                VVERBOSE_PRINT("Difference found in small instr\n");
                return false;
            }
            p1 += size;
            p2 += size;
        } else {
            /* guess if there could be a relocation */
            instr_t *instr1 = instr_create(drcontext);
            instr_t *instr2 = instr_create(drcontext);
            p1 = decode(drcontext, p1, instr1);
            p2 = decode(drcontext, p2, instr2);
            if (p1 - start1 != p2 - start2) {
                VVERBOSE_PRINT("Instruction alignment mismatch on full decode\n");
                /* Fixme - free instr, don't expect this to happen */
                return false;
            }
            if (instr_get_num_srcs(instr1) != instr_get_num_srcs(instr2) ||
                instr_get_num_dsts(instr1) != instr_get_num_dsts(instr2)) {
                VVERBOSE_PRINT("Full decode operand mismatch");
                return false;
            }
            for (i = instr_get_num_srcs(instr1); i > 0; i--) {
                opnd_t opnd = instr_get_src(instr1, i);
                if (opnd_is_immed_int(opnd) && opnd_get_immed_int(opnd) > 0x10000) {
                    instr_set_src(instr1, i, opnd_create_immed_int(opnd_get_immed_int(opnd), opnd_get_size(opnd)));
                }
            }
        }
    }
}
Beispiel #7
0
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);
}