Example #1
0
/* inserts "inst" before "where" ("inst" can be a chain of insts) */
void
instrlist_preinsert(instrlist_t *ilist, instr_t *where, instr_t *inst)
{
    instr_t *whereprev;
    instr_t *top = inst;
    instr_t *bot;

    if (where == NULL) {
        /* if where is NULL there is no inst to send for a "before" */
        instrlist_append(ilist, inst);
        return;
    }

    CLIENT_ASSERT(where != NULL, "instrlist_preinsert: where cannot be NULL");
    CLIENT_ASSERT(instr_get_prev(inst) == NULL,
                  "instrlist_preinsert: cannot add middle of list");
    whereprev = instr_get_prev(where);
    check_translation(ilist, inst);
    while (instr_get_next(inst)) {
        inst = instr_get_next(inst);
        check_translation(ilist, inst);
    }
    bot = inst;
    if (whereprev) {
        instr_set_next(whereprev, top);
        instr_set_prev(top, whereprev);
    } else {
        ilist->first = top;
    }
    instr_set_next(bot, where);
    instr_set_prev(where, bot);
}
Example #2
0
/* Check if current instrumentation can be merged into previous aflags
 * (or on ARM, GPR) save/restore inserted by drx_restore_arith_flags.
 * Returns NULL if cannot merge. Otherwise, returns the right insertion point,
 * i.e., DRX_NOTE_AFLAGS_RESTORE_BEGIN label instr.
 *
 * This routine looks for labels inserted by drx_restore_arith_flags,
 * so changes to drx_restore_arith_flags may affect this routine.
 * On ARM the labels are from drx_insert_counter_update.
 */
static instr_t *
merge_prev_drx_spill(instr_t *where, bool aflags)
{
    instr_t *instr;
#ifdef DEBUG
    bool has_sahf = false;
#endif

    if (where == NULL)
        return NULL;
    instr = instr_get_prev(where);
    if (instr == NULL)
        return NULL;
    if (!instr_is_label(instr))
        return NULL;
    /* Check if prev instr is DRX_NOTE_AFLAGS_RESTORE_END.
     * We bail even there is only a label instr in between, which
     * might be a target of internal cti.
     */
    if (instr_get_note(instr) != NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_END))
        return NULL;

    /* find DRX_NOTE_AFLAGS_RESTORE_BEGIN */
    for (instr  = instr_get_prev(instr);
         instr != NULL;
         instr  = instr_get_prev(instr)) {
        if (instr_is_app(instr)) {
            /* we do not expect any app instr */
            ASSERT(false, "drx aflags restore is corrupted");
            return NULL;
        }
        if (instr_is_label(instr)) {
            if (instr_get_note(instr) == NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_BEGIN)) {
                ASSERT(!aflags || has_sahf, "missing sahf");
                return instr;
            }
            /* we do not expect any other label instr */
            ASSERT(false, "drx aflags restore is corrupted");
            return NULL;
#ifdef DEBUG
        } else {
            if (instr_get_note(instr) == NOTE_VAL(DRX_NOTE_AFLAGS_RESTORE_SAHF))
                has_sahf = true;
#endif
        }
    }
    return NULL;
}
Example #3
0
/* removes "inst" from the instrlist_t it currently belongs to */
void
instrlist_remove(instrlist_t *ilist, instr_t *inst)
{
    if (instr_get_prev(inst))
        instr_set_next(instr_get_prev(inst), instr_get_next(inst));
    else
        ilist->first = instr_get_next(inst);

    if (instr_get_next(inst))
        instr_set_prev(instr_get_next(inst), instr_get_prev(inst));
    else
        ilist->last = instr_get_prev(inst);

    instr_set_prev(inst, NULL);
    instr_set_next(inst, NULL);
}
Example #4
0
/* inserts "inst" after "where" ("inst" can be a chain of insts) */
void
instrlist_postinsert(instrlist_t *ilist, instr_t *where, instr_t *inst)
{
    instr_t *wherenext;
    instr_t *top = inst;
    instr_t *bot;

    if (where == NULL) {
        /* if where is NULL there is no inst to send for an "after" */
        instrlist_prepend(ilist, inst);
        return;
    }

    CLIENT_ASSERT(where != NULL, "instrlist_postinsert: where cannot be NULL");
    CLIENT_ASSERT(instr_get_prev(inst) == NULL,
                  "instrlist_postinsert: cannot add middle of list");

    wherenext = instr_get_next(where);
    check_translation(ilist, inst);
    while (instr_get_next(inst)) {
        inst = instr_get_next(inst);
        check_translation(ilist, inst);
    }
    bot = inst;
    instr_set_next(where, top);
    instr_set_prev(top, where);
    if (wherenext) {
        instr_set_next(bot, wherenext);
        instr_set_prev(wherenext, bot);
    } else {
        ilist->last = bot;
    }
}
Example #5
0
/* replace oldinst with newinst, remove oldinst from ilist, and return oldinst
   (newinst can be a chain of insts) */
instr_t *
instrlist_replace(instrlist_t *ilist, instr_t *oldinst, instr_t *newinst)
{
    instr_t *where;

    CLIENT_ASSERT(oldinst != NULL, "instrlist_replace: oldinst cannot be NULL");
    CLIENT_ASSERT(instr_get_prev(newinst) == NULL,
                  "instrlist_replace: cannot add middle of list");
    where = instr_get_prev(oldinst);
    instrlist_remove(ilist, oldinst);
    if (where)
        instrlist_postinsert(ilist, where, newinst);
    else
        instrlist_prepend(ilist, newinst);

    return oldinst;
}
Example #6
0
int
offline_instru_t::instrument_memref(void *drcontext, instrlist_t *ilist, instr_t *where,
                                    reg_id_t reg_ptr, reg_id_t reg_tmp, int adjust,
                                    opnd_t ref, bool write, dr_pred_type_t pred)
{
    // Post-processor distinguishes read, write, prefetch, flush, and finds size.
    instr_t *label = INSTR_CREATE_label(drcontext);
    MINSERT(ilist, where, label);
    insert_save_addr(drcontext, ilist, where, reg_ptr, reg_tmp, adjust, ref);
#ifdef ARM // X86 does not support general predicated execution
    if (pred != DR_PRED_NONE) {
        instr_t *instr;
        for (instr  = instr_get_prev(where);
             instr != label;
             instr  = instr_get_prev(instr)) {
            DR_ASSERT(!instr_is_predicated(instr));
            instr_set_predicate(instr, pred);
        }
    }
#endif
    return (adjust + sizeof(offline_entry_t));
}
Example #7
0
void
cfi_cleanup_after_native_call(void *drcontext, instrlist_t *ilist, instr_t *where)
{
	instr_t *in = (where == NULL) ? instrlist_last(ilist) : instr_get_prev(where);

	CFI_ASSERT(drcontext != NULL, "dr_cleanup_after_call: drcontext cannot be NULL");
/*
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RDI)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RSI)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RBP)));*/
    /* skip xsp by popping into dead rbx */
  /*  PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RBX)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RBX)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RDX)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RCX)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_RAX)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R8)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R9)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R10)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R11)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R12)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R13)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R14)));
    PRE(ilist, where, INSTR_CREATE_pop(drcontext, opnd_create_reg(REG_R15)));

    PRE(ilist, where, INSTR_CREATE_lea
        (drcontext, opnd_create_reg(REG_XSP),
         OPND_CREATE_MEM_lea(REG_XSP, REG_NULL, 0, XMM_SLOTS_SIZE)));

*/
    PRE(ilist, where, INSTR_CREATE_popf(drcontext));

    /* now go through and mark inserted instrs as meta */
    if (in == NULL)
        in = instrlist_first(ilist);
    else
        in = instr_get_next(in);

    while (in != where) {
        instr_set_ok_to_mangle(in, false);
        in = instr_get_next(in);
    }
}
Example #8
0
void
cfi_insert_meta_native_call_vargs(void *dcontext, instrlist_t *bb, instr_t *cursor,
                       bool clean_call, void *callee)
{
    instr_t *in = (cursor == NULL) ? instrlist_last(bb) : instr_get_prev(cursor);

   // PRE(ilist, instr, INSTR_CREATE_mov_ld(dcontext, opnd_create_reg(REG_RDI), opnd_create_reg(REG_RSP)));

    PRE(bb, cursor, INSTR_CREATE_call(dcontext, opnd_create_pc(callee)));

    /* mark it all meta */
    if (in == NULL)
        in = instrlist_first(bb);
    else
        in = instr_get_next(in);
    while (in != cursor) {
        instr_set_ok_to_mangle(in, false);
        in = instr_get_next(in);
    }
}
Example #9
0
/* prepends inst to the list ("inst" can be a chain of insts) */
void
instrlist_prepend(instrlist_t *ilist, instr_t *inst)
{
    instr_t *top = inst;
    instr_t *bot;

    CLIENT_ASSERT(instr_get_prev(inst) == NULL,
                  "instrlist_prepend: cannot add middle of list");
    check_translation(ilist, inst);
    while (instr_get_next(inst)) {
        inst = instr_get_next(inst);
        check_translation(ilist, inst);
    }
    bot = inst;
    if (ilist->first) {
        instr_set_next(bot, ilist->first);
        instr_set_prev(ilist->first, bot);
        ilist->first = top;
    } else {
        ilist->first = top;
        ilist->last = bot;
    }
}
Example #10
0
unsigned int
cfi_prepare_for_native_call(void *drcontext, instrlist_t *ilist, instr_t *where)
{
	unsigned int eflags_offs, dstack_offs = 0;
    instr_t *in = (where == NULL) ? instrlist_last(ilist) : instr_get_prev(where);

    CFI_ASSERT(drcontext != NULL, "cfi_prepare_for_native_call: drcontext cannot be NULL");

    //PRE(ilist, where, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(0)));
    //dstack_offs += XSP_SZ;

    PRE(ilist, where, INSTR_CREATE_pushf(drcontext));
    PRE(ilist, where, INSTR_CREATE_push(drcontext,
                          opnd_create_base_disp(REG_XSP, REG_NULL, 0, 0, OPSZ_STACK)));
    PRE(ilist, where, INSTR_CREATE_and(drcontext,
                         opnd_create_base_disp(REG_XSP, REG_NULL, 0, 0,
                                               OPSZ_STACK),
                         OPND_CREATE_INT32(~(EFLAGS_NON_SYSTEM | EFLAGS_IF))));

    PRE(ilist, where, INSTR_CREATE_popf(drcontext));

  /*  dstack_offs += XSP_SZ;
    eflags_offs = dstack_offs;

    PRE(ilist, where, INSTR_CREATE_lea(drcontext, opnd_create_reg(REG_XSP),
    		OPND_CREATE_MEM_lea(REG_XSP, REG_NULL, 0, - XMM_SLOTS_SIZE)));

    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R15)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R14)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R13)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R12)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R11)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R10)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R9)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_R8)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RAX)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RCX)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RDX)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RBX)));*/
    /* we do NOT match pusha xsp value *//*
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RSP)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RBP)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RSI)));
    PRE(ilist, where, INSTR_CREATE_push(drcontext, opnd_create_reg(REG_RDI)));
    dstack_offs += 16*XSP_SZ + XMM_SLOTS_SIZE;

    PRE(ilist, where, INSTR_CREATE_push(drcontext,
                          opnd_create_base_disp(REG_XSP, REG_NULL, 0,
                          dstack_offs - eflags_offs, OPSZ_STACK)));

    PRE(ilist, where, INSTR_CREATE_and(drcontext,
                         opnd_create_base_disp(REG_XSP, REG_NULL, 0, 0,
                                               OPSZ_STACK),
                         OPND_CREATE_INT32(~(EFLAGS_NON_SYSTEM | EFLAGS_IF))));

    PRE(ilist, where, INSTR_CREATE_popf(drcontext));*/

    /* now go through and mark inserted instrs as meta */
    if (in == NULL)
        in = instrlist_first(ilist);
    else
        in = instr_get_next(in);

    while (in != where) {
        instr_set_ok_to_mangle(in, false);
        in = instr_get_next(in);
    }

    return dstack_offs;
}
Example #11
0
/** Adds instrumentation that records fragment execution. */
struct instr_info_t instrument_frag(void* ctx,
                                    instrlist_t* frag,
                                    frag_id_t id) {
  const size_t offsetof_current = offsetof(struct trace_buffer_t, current);
  ptr_int_t frag_id = id; // sign-extended for OPND_CREATE_INT32
#ifdef TRACE_DEBUG
  app_pc frag_pc;
#endif
  app_pc xl8_pc;
  instr_t* where;
  instr_t* before;
  struct instr_info_t instr_info;
  instr_t* store;
  instr_t* first;

#ifdef TRACE_DEBUG
  dr_fprintf(STDERR, "debug: instrument_frag(0x%" PRIxPTR ")\n", frag_id);
  frag_pc = instr_get_app_pc(instrlist_first(frag));
  instrlist_disassemble(ctx, frag_pc, frag, STDERR);
#endif

  where = configure_instr(&instr_info, frag);
  xl8_pc = instr_get_app_pc(where);
  before = instr_get_prev(where);

#define INSERT(instr) prexl8(frag, where, (instr), xl8_pc)

  // Add instrumentation.
  // save tls_reg
  if(instr_info.restore_tls_reg) {
    dr_save_reg(ctx, frag, where, instr_info.tls_reg, SPILL_SLOT_2);
  }
  // save current_reg
  if(instr_info.restore_current_reg) {
    dr_save_reg(ctx, frag, where, instr_info.current_reg, SPILL_SLOT_3);
  }
  // tls_reg = tb
  dr_insert_read_tls_field(ctx, frag, where, instr_info.tls_reg);
  // current_reg = tb->current
  INSERT(
      INSTR_CREATE_mov_ld(
          ctx,
          opnd_create_reg(instr_info.current_reg),
          OPND_CREATE_MEMPTR(instr_info.tls_reg, offsetof_current)));
  // *current_reg = bb_id
  store = INSERT(
      INSTR_CREATE_mov_st(
          ctx,
          OPND_CREATE_MEMPTR(instr_info.current_reg, 0),
          OPND_CREATE_INT32(frag_id)));
  // current_reg += sizeof(bb_id)
  INSERT(
      INSTR_CREATE_lea(
          ctx,
          opnd_create_reg(instr_info.current_reg),
          OPND_CREATE_MEM_lea(instr_info.current_reg,
                              DR_REG_NULL,
                              0,
                              sizeof(frag_id_t))));
  // tb->current = current_reg
  INSERT(
      INSTR_CREATE_mov_st(
          ctx,
          OPND_CREATE_MEMPTR(instr_info.tls_reg, offsetof_current),
          opnd_create_reg(instr_info.current_reg)));
  // restore current_reg
  if(instr_info.restore_current_reg) {
    dr_restore_reg(ctx, frag, where, instr_info.current_reg, SPILL_SLOT_3);
  }
  // restore tls_reg
  if(instr_info.restore_tls_reg) {
    dr_restore_reg(ctx, frag, where, instr_info.tls_reg, SPILL_SLOT_2);
  }

#undef INSERT

  // Compute instrumentation instructions offsets.
  if(before) {
    first = instr_get_next(before);
  } else {
    first = instrlist_first(frag);
  }
  instr_info.first_offset = get_offset(ctx,
                                       instrlist_first(frag),
                                       first);
  instr_info.store_offset = get_offset(ctx,
                                       instrlist_first(frag),
                                       store);

#ifdef TRACE_DUMP_BB
  instrlist_disassemble(ctx, frag_pc, frag, STDERR);
#endif
#ifdef TRACE_DEBUG
  dr_fprintf(STDERR,
             "debug: instrument_frag() done,"
             " first_offset=0x%" PRIx32
             " store_offset=0x%" PRIx32
             "\n",
             instr_info.first_offset,
             instr_info.store_offset);
#endif

  return instr_info;
}