/* instruments a Binary Operation Expression in a Ist_WrTmp statement */ static void instrument_Triop(IRSB* sb, IRStmt* st, Addr64 cia) { Char thisFct[]="instrument_Triop"; IRDirty* di; IRExpr** argv; IRExpr *op = st->Ist.WrTmp.data; IRExpr* oa_event_expr; IROp irop=op->Iex.Triop.details->op; void* f=callbackFromIROp(irop); if (f == NULL) return; OA_InstrumentContext inscon=contextFor(cia, irop); if (not_worth_watching(inscon)) return; // filter events that can't be attached to source-code location updateStats(inscon->op); oa_event_expr = mkIRExpr_HWord( (HWord)inscon ); IRExpr * args1[2]; packToI32orI64(sb, op->Iex.Triop.details->arg2, args1, irop); IRExpr * args2[2]; packToI32orI64(sb, op->Iex.Triop.details->arg3, args2, irop); argv = mkIRExprVec_3(args1[0], args2[0], oa_event_expr); di = unsafeIRDirty_0_N( 3, thisFct, VG_(fnptr_to_fnentry)( f ), argv); addStmtToIRSB( sb, IRStmt_Dirty(di) ); if (args1[1] != NULL) { // we need a second callback for 64bit types argv = mkIRExprVec_3(args1[1], args2[1], oa_event_expr); di = unsafeIRDirty_0_N( 3, thisFct, VG_(fnptr_to_fnentry)( f ), argv); addStmtToIRSB( sb, IRStmt_Dirty(di) ); } }
/* Converts an IRExpr into 1 or 2 "flat" expressions of type Int */ static void packToI32 ( IRSB* sb, IRExpr* e, IRExpr* res[2]) { //IRType eType = Ity_I32; IRTemp tmp64; res[1]=NULL; switch (typeOfIRExpr(sb->tyenv,e)) { case Ity_I1: res[0]= IRExpr_Unop(Iop_1Uto32,e); break; case Ity_I8: res[0]= IRExpr_Unop(Iop_8Uto32,e); break; case Ity_I16: res[0]= IRExpr_Unop(Iop_16Uto32,e); break; case Ity_I32: res[0]= e; return; case Ity_F32: res[0]= IRExpr_Unop(Iop_ReinterpF32asI32,e); break; case Ity_I64: res[0]= IRExpr_Unop(Iop_64to32, e); res[1]= IRExpr_Unop(Iop_64HIto32, e); break; case Ity_F64: tmp64 = newIRTemp(sb->tyenv, Ity_I64); addStmtToIRSB(sb, IRStmt_WrTmp(tmp64, IRExpr_Unop(Iop_ReinterpF64asI64,e))); res[0]= IRExpr_Unop(Iop_64to32, IRExpr_RdTmp(tmp64) ); res[1]= IRExpr_Unop(Iop_64HIto32, IRExpr_RdTmp(tmp64) ); break; case Ity_V128: /* 128-bit SIMD */ case Ity_I128: /* 128-bit scalar */ case Ity_INVALID: default: VG_(tool_panic)("COJAC cannot packToI32..."); break; } IRTemp myArg = newIRTemp(sb->tyenv, Ity_I32); addStmtToIRSB(sb, IRStmt_WrTmp(myArg, res[0])); res[0]=IRExpr_RdTmp(myArg); // now that's a "flat" expression if (res[1]==NULL) return; IRTemp myArg2 = newIRTemp(sb->tyenv, Ity_I32); addStmtToIRSB(sb, IRStmt_WrTmp(myArg2, res[1])); res[1]=IRExpr_RdTmp(myArg2); // now that's a "flat" expression }
static IRExpr* assignNew_HWord(IRSB* sb_out, IRExpr* expr) { IRTemp tmp = newIRTemp(sb_out->tyenv, Ity_I32); switch (typeOfIRExpr(sb_out->tyenv, expr)) { case Ity_I1: addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_1Uto32, expr))); break; case Ity_I8: addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_8Uto32, expr))); break; case Ity_I16: addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_16Uto32, expr))); break; case Ity_I32: addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, expr)); break; case Ity_I64: addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, IRExpr_Unop(Iop_64to32, expr))); break; default: VG_(tool_panic)("assignNew_HWord"); } return IRExpr_RdTmp(tmp); }
/* Converts an IRExpr into 1 or 2 "flat" expressions of type Long */ static void packToI64 ( IRSB* sb, IRExpr* e, IRExpr* res[2], IROp irop) { res[1]=NULL; // won't be used at all IRTemp tmp64; switch (typeOfIRExpr(sb->tyenv,e)) { case Ity_I1: res[0]= IRExpr_Unop(Iop_1Uto64,e); break; case Ity_I8: res[0]= IRExpr_Unop(Iop_8Uto64,e); break; case Ity_I16: res[0]= IRExpr_Unop(Iop_16Uto64,e); break; case Ity_I32: res[0]= IRExpr_Unop(Iop_32Uto64,e); break; case Ity_F32: e = IRExpr_Unop(Iop_ReinterpF32asI32,e); res[0]= IRExpr_Unop(Iop_32Uto64,e); break; case Ity_I64: res[0]= e; return; case Ity_F64: res[0]= IRExpr_Unop(Iop_ReinterpF64asI64,e); break; case Ity_V128: /* 128-bit SIMD */ //tmp64 = newIRTemp(sb->tyenv, Ity_I64); //addStmtToIRSB(sb, IRStmt_WrTmp(tmp64, IRExpr_Unop(Iop_V128to64,e))); //res[0]= IRExpr_Unop(Iop_64to32, IRExpr_RdTmp(tmp64) ); //res[1]= IRExpr_Unop(Iop_64HIto32, IRExpr_RdTmp(tmp64) ); res[0]= IRExpr_Unop(Iop_V128to64, e ); if (dropV128HiPart(irop)) break; res[1]= IRExpr_Unop(Iop_V128HIto64, e ); break; case Ity_I128: /* 128-bit scalar */ case Ity_INVALID: default: VG_(tool_panic)("COJAC cannot packToI64..."); break; } IRTemp myArg = newIRTemp(sb->tyenv, Ity_I64); addStmtToIRSB(sb, IRStmt_WrTmp(myArg, res[0])); res[0]=IRExpr_RdTmp(myArg); // now that's a "flat" expression if (res[1]==NULL) return; // ... else it was 128-bit SIMD IRTemp myArg2 = newIRTemp(sb->tyenv, Ity_I64); addStmtToIRSB(sb, IRStmt_WrTmp(myArg2, res[1])); res[1]=IRExpr_RdTmp(myArg2); // now that's a "flat" expression }
static void VG_(add_stmt_call_invalidate_if_not_gdbserved) ( IRSB* sb_in, VexGuestLayout* layout, VexGuestExtents* vge, IRTemp jmp, IRSB* irsb) { void* fn; const HChar* nm; IRExpr** args; Int nargs; IRDirty* di; fn = &VG_(helperc_invalidate_if_not_gdbserved); nm = "VG_(helperc_invalidate_if_not_gdbserved)"; args = mkIRExprVec_1(IRExpr_RdTmp (jmp)); nargs = 1; di = unsafeIRDirty_0_N( nargs/*regparms*/, nm, VG_(fnptr_to_fnentry)( fn ), args ); di->nFxState = 0; addStmtToIRSB(irsb, IRStmt_Dirty(di)); }
void instrument_WrTmp_Mux0X(IRStmt* st, IRSB* sb_out) { IRTemp tmp = st->Ist.WrTmp.tmp; IRExpr* data = st->Ist.WrTmp.data; IRExpr* cond = data->Iex.Mux0X.cond; IRExpr* expr0 = data->Iex.Mux0X.expr0; IRExpr* exprX = data->Iex.Mux0X.exprX; Int size = sizeofIRType_bits(typeOfIRExpr(sb_out->tyenv, expr0)); IRDirty* di; tl_assert(cond->tag == Iex_RdTmp); tl_assert(isIRAtom(expr0)); tl_assert(isIRAtom(exprX)); tl_assert(typeOfIRTemp(sb_out->tyenv, tmp) == typeOfIRExpr(sb_out->tyenv, expr0)); tl_assert(typeOfIRTemp(sb_out->tyenv, tmp) == typeOfIRExpr(sb_out->tyenv, exprX)); di = unsafeIRDirty_0_N(0, "helper_instrument_WrTmp_Mux0X", VG_(fnptr_to_fnentry)(helper_instrument_WrTmp_Mux0X), mkIRExprVec_5(mkIRExpr_HWord(tmp), assignNew_HWord(sb_out, cond), mkIRExpr_HWord((expr0->tag == Iex_RdTmp) ? expr0->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord((exprX->tag == Iex_RdTmp) ? exprX->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord(size)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
void AddOpRhsTypeHelper(IRSB* sb, IRExpr* arg, IntTyStateHint hint, Addr addr) { IRDirty * d; HWord tmpname; switch (arg->tag) { case(Iex_RdTmp): tmpname = (HWord)arg->Iex.RdTmp.tmp; d = unsafeIRDirty_0_N(0, "EmitTmpHelper", &EmitTmpHelper, mkIRExprVec_4( mkIRExpr_HWord(tmpname), mkIRExpr_HWord(hint), mkIRExpr_HWord(counter), mkIRExpr_HWord(addr) ) ); setHelperAnns(d); addStmtToIRSB(sb,IRStmt_Dirty(d)); break; default: break; } return; }
void AddStoreHelper(IRSB* sb, IRExpr* addr, IRExpr* data) { IRDirty* d; HWord tmpname; switch (addr->tag) { case (Iex_RdTmp): switch (data->tag) { case (Iex_RdTmp): tmpname = (HWord) data->Iex.RdTmp.tmp; d = unsafeIRDirty_0_N(0, "EmitStoreAddr2TmpHelper", &EmitStoreAddr2TmpHelper, mkIRExprVec_3(addr, mkIRExpr_HWord(tmpname), mkIRExpr_HWord(counter) ) ); setHelperAnns(d); addStmtToIRSB(sb, IRStmt_Dirty(d)); break; case (Iex_Const): /* add code to emit new tyvar for memory address */ d = unsafeIRDirty_0_N(0, "EmitStoreAddr2ConstHelper", &EmitStoreAddr2ConstHelper, mkIRExprVec_1(addr ) ); setHelperAnns(d); addStmtToIRSB(sb,IRStmt_Dirty(d)); break; default: /* Should not reach here. */ ppIRExpr(data); vpanic("Bad store address!\n"); break; } break; default: break; } return; }
/* add stmt to a bb */ static /*inline*/ void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) { if (pce->trace) { VG_(printf)(" %c: ", cat); ppIRStmt(st); VG_(printf)("\n"); } addStmtToIRSB(pce->sb, st); }
/* cc_op add/sub/mul adc/sbb shl/Shl/sar tmp = cond(cc_op(cc_dep1, cc_dep2)) and/or/xor inc/dec rol/ror tmp = cond(cc_op(cc_dep1, 0)) The taintness of tmp depends on taintness of both args. (we can't handle and(cc_dep1, 0) which gives an untainted result) cf. valgrind guest_x86_defs.h */ void instrument_WrTmp_CCall(IRStmt* st, IRSB* sb_out) { IRTemp tmp = st->Ist.WrTmp.tmp; IRExpr* data = st->Ist.WrTmp.data; IRCallee* cee = data->Iex.CCall.cee; IRExpr** args = data->Iex.CCall.args; IRDirty* di; if (VG_(strcmp)(cee->name, "x86g_calculate_condition") == 0) { IRExpr* cond = args[0]; IRExpr* cc_op = args[1]; IRExpr* cc_dep1 = args[2]; IRExpr* cc_dep2 = args[3]; tl_assert(cond->tag == Iex_Const && cond->Iex.Const.con->tag == Ico_U32); tl_assert(isIRAtom(cc_op)); tl_assert(isIRAtom(cc_dep1)); tl_assert(isIRAtom(cc_dep2)); if (cc_op->tag == Iex_Const) tl_assert(cc_op->Iex.Const.con->tag == Ico_U32); if (cc_dep1->tag == Iex_Const) tl_assert(cc_dep1->Iex.Const.con->tag == Ico_U32); if (cc_dep2->tag == Iex_Const) tl_assert(cc_dep2->Iex.Const.con->tag == Ico_U32); // typeOf(x86g_calculate_condition) == typeOf(tmp) == I32 di = unsafeIRDirty_0_N(0, "helper_instrument_WrTmp_CCall_x86g_calculate_condition", VG_(fnptr_to_fnentry)(helper_instrument_WrTmp_CCall_x86g_calculate_condition), mkIRExprVec_7(mkIRExpr_HWord(tmp), mkIRExpr_HWord((cc_dep1->tag == Iex_RdTmp) ? cc_dep1->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord((cc_dep2->tag == Iex_RdTmp) ? cc_dep2->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord(cond->Iex.Const.con->Ico.U32), (cc_op->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, cc_op) : mkIRExpr_HWord(cc_op->Iex.Const.con->Ico.U32), (cc_dep1->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, cc_dep1) : mkIRExpr_HWord(cc_dep1->Iex.Const.con->Ico.U32), (cc_dep2->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, cc_dep2) : mkIRExpr_HWord(cc_dep2->Iex.Const.con->Ico.U32)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); } else { di = unsafeIRDirty_0_N(0, "helper_instrument_WrTmp_CCall_else", VG_(fnptr_to_fnentry)(helper_instrument_WrTmp_CCall_else), mkIRExprVec_0() ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); } }
/* Bind the given expression to a new temporary, and return the temporary. This effectively converts an arbitrary expression into an IRAtom. */ static IRExpr* assignNew(IRSB* sb_out, IRExpr* expr) { IRTemp tmp = newIRTemp(sb_out->tyenv, typeOfIRExpr(sb_out->tyenv, expr)); addStmtToIRSB(sb_out, IRStmt_WrTmp(tmp, expr)); return IRExpr_RdTmp(tmp); }
void instrument_WrTmp_Binop(IRStmt* st, IRSB* sb_out) { IRTemp tmp = st->Ist.WrTmp.tmp; IRExpr* data = st->Ist.WrTmp.data; IROp op = data->Iex.Binop.op; IRExpr* arg1 = data->Iex.Binop.arg1; IRExpr* arg2 = data->Iex.Binop.arg2; UInt arg1_value = 0, arg2_value = 0; IRExpr* expr = IRExpr_Binop(op, arg1, arg2); Int size = sizeofIRType_bits(typeOfIRExpr(sb_out->tyenv, expr)); IRDirty* di; // we don't care about floating point and SIMD operations if (op > Iop_AddF64) return; tl_assert(isIRAtom(arg1)); tl_assert(isIRAtom(arg2)); tl_assert(typeOfIRTemp(sb_out->tyenv, tmp) == typeOfIRExpr(sb_out->tyenv, expr)); if (arg1->tag == Iex_Const) { switch (arg1->Iex.Const.con->tag) { case Ico_U1: arg1_value = arg1->Iex.Const.con->Ico.U1; break; case Ico_U8: arg1_value = arg1->Iex.Const.con->Ico.U8; break; case Ico_U16: arg1_value = arg1->Iex.Const.con->Ico.U16; break; case Ico_U32: arg1_value = arg1->Iex.Const.con->Ico.U32; break; case Ico_U64: arg1_value = arg1->Iex.Const.con->Ico.U64; break; default: VG_(tool_panic)("instrument_WrTmp_Binop"); } } if (arg2->tag == Iex_Const) { switch (arg2->Iex.Const.con->tag) { case Ico_U1: arg2_value = arg2->Iex.Const.con->Ico.U1; break; case Ico_U8: arg2_value = arg2->Iex.Const.con->Ico.U8; break; case Ico_U16: arg2_value = arg2->Iex.Const.con->Ico.U16; break; case Ico_U32: arg2_value = arg2->Iex.Const.con->Ico.U32; break; case Ico_U64: arg2_value = arg2->Iex.Const.con->Ico.U64; break; default: VG_(tool_panic)("instrument_WrTmp_Binop"); } } di = unsafeIRDirty_0_N(0, "helper_instrument_WrTmp_Binop", VG_(fnptr_to_fnentry)(helper_instrument_WrTmp_Binop), mkIRExprVec_7(mkIRExpr_HWord(tmp), mkIRExpr_HWord((arg1->tag == Iex_RdTmp) ? arg1->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord((arg2->tag == Iex_RdTmp) ? arg2->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord(op), mkIRExpr_HWord(size), (arg1->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, arg1) : mkIRExpr_HWord(arg1_value), (arg2->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, arg2) : mkIRExpr_HWord(arg2_value)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
static IRSB * bcg_instrument(VgCallbackClosure* closure, IRSB* bb, VexGuestLayout* layout, VexGuestExtents* vge, IRType gWordTy, IRType hWordTy) { unsigned long rip = 0; int i; if (bb->jumpkind != Ijk_Ret && bb->next->tag != Iex_Const) { IRTemp tmp; for (i = bb->stmts_used - 1; i >= 0; i--) { if (bb->stmts[i]->tag == Ist_IMark) { rip = bb->stmts[i]->Ist.IMark.addr; break; } } tl_assert(i >= 0); if (bb->next->tag == Iex_RdTmp) { tmp = bb->next->Iex.RdTmp.tmp; } else { tmp = newIRTemp(bb->tyenv, Ity_I64); addStmtToIRSB(bb, IRStmt_WrTmp(tmp, bb->next)); bb->next = IRExpr_RdTmp(tmp); } addStmtToIRSB(bb, IRStmt_Dirty( unsafeIRDirty_0_N( 0, "log_call", log_call, mkIRExprVec_3( IRExpr_Const(IRConst_U64(rip)), IRExpr_Const(IRConst_U64(bb->jumpkind == Ijk_Call)), bb->next)))); } return bb; }
void addDynamicDisownNonNull(IRSB* sbOut, IRTemp idx){ IRDirty* disownDirty = unsafeIRDirty_0_N(1, "disownShadowTempNonNullDynamic", VG_(fnptr_to_fnentry)(disownShadowTempNonNullDynamic), mkIRExprVec_1(mkU64(idx))); disownDirty->mFx = Ifx_Modify; disownDirty->mAddr = mkU64((uintptr_t)&(shadowTemps[idx])); disownDirty->mSize = sizeof(ShadowTemp*); addStmtToIRSB(sbOut, IRStmt_Dirty(disownDirty)); }
static void addConstMemStoreStmt( IRSB* bbOut, UWord addr, UInt val, IRType hWordTy) { addStmtToIRSB( bbOut, IRStmt_Store(CLGEndness, IRExpr_Const(hWordTy == Ity_I32 ? IRConst_U32( addr ) : IRConst_U64( addr )), IRExpr_Const(IRConst_U32(val)) )); }
void AddPutHelper(IRSB* sb, Int offset, IRExpr* data) { IRDirty * d; HWord h_offset = (HWord)(offset); HWord lhs_name; switch (data->tag) { case(Iex_Const): d = unsafeIRDirty_0_N(0, "EmitPutConstHelper", &EmitPutConstHelper, mkIRExprVec_2(mkIRExpr_HWord(h_offset), mkIRExpr_HWord(counter) ) ); setHelperAnns(d); addStmtToIRSB(sb, IRStmt_Dirty(d)); break; case(Iex_RdTmp): lhs_name = (HWord)data->Iex.RdTmp.tmp; d = unsafeIRDirty_0_N(0, "EmitPutTmpHelper", &EmitPutTmpHelper, mkIRExprVec_3(mkIRExpr_HWord(h_offset), mkIRExpr_HWord(lhs_name), mkIRExpr_HWord(counter) ) ); setHelperAnns(d); addStmtToIRSB(sb, IRStmt_Dirty(d)); break; default: break; } return; }
void instrument_WrTmp_Const(IRStmt* st, IRSB* sb_out) { IRTemp tmp = st->Ist.WrTmp.tmp; IRDirty* di; di = unsafeIRDirty_0_N(0, "helper_instrument_WrTmp_Const", VG_(fnptr_to_fnentry)(helper_instrument_WrTmp_Const), mkIRExprVec_1(mkIRExpr_HWord(tmp)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
void addSVDisownNonNullG(IRSB* sbOut, IRExpr* guard, IRExpr* sv){ IRExpr* refCountAddr = runArrowAddr(sbOut, sv, ShadowValue, ref_count); IRExpr* prevRefCount = runLoadG64(sbOut, refCountAddr, guard); IRExpr* newRefCount = runBinop(sbOut, Iop_Sub64, prevRefCount, mkU64(1)); addStoreG(sbOut, guard, newRefCount, refCountAddr); IRExpr* lastRef = runBinop(sbOut, Iop_CmpEQ64, prevRefCount, mkU64(1)); IRStmt* freeVal = mkDirtyG_0_1(freeShadowValue, sv, lastRef); addStmtToIRSB(sbOut, freeVal); }
static void instrument_store(IRSB* const bb, IRExpr* const addr_expr, const HWord size) { IRExpr* size_expr; IRExpr** argv; IRDirty* di; switch (size) { case 1: argv = mkIRExprVec_1(addr_expr); di = unsafeIRDirty_0_N(/*regparms*/1, "drd_trace_store_1", VG_(fnptr_to_fnentry)(drd_trace_store_1), argv); break; case 2: argv = mkIRExprVec_1(addr_expr); di = unsafeIRDirty_0_N(/*regparms*/1, "drd_trace_store_2", VG_(fnptr_to_fnentry)(drd_trace_store_2), argv); break; case 4: argv = mkIRExprVec_1(addr_expr); di = unsafeIRDirty_0_N(/*regparms*/1, "drd_trace_store_4", VG_(fnptr_to_fnentry)(drd_trace_store_4), argv); break; case 8: argv = mkIRExprVec_1(addr_expr); di = unsafeIRDirty_0_N(/*regparms*/1, "drd_trace_store_8", VG_(fnptr_to_fnentry)(drd_trace_store_8), argv); break; default: size_expr = mkIRExpr_HWord(size); argv = mkIRExprVec_2(addr_expr, size_expr); di = unsafeIRDirty_0_N(/*regparms*/2, "drd_trace_store", VG_(fnptr_to_fnentry)(drd_trace_store), argv); break; } addStmtToIRSB(bb, IRStmt_Dirty(di)); }
/* A helper that adds the instrumentation for a detail. */ static void instrument_detail(IRSB* sb, Op op, IRType type) { IRDirty* di; IRExpr** argv; const UInt typeIx = type2index(type); tl_assert(op < N_OPS); tl_assert(typeIx < N_TYPES); argv = mkIRExprVec_1( mkIRExpr_HWord( (HWord)&detailCounts[op][typeIx] ) ); di = unsafeIRDirty_0_N( 1, "increment_detail", VG_(fnptr_to_fnentry)( &increment_detail ), argv); addStmtToIRSB( sb, IRStmt_Dirty(di) ); }
static void flushEvents(IRSB* sb) { Int i; Char* helperName; void* helperAddr; IRExpr** argv; IRDirty* di; Event* ev; for (i = 0; i < events_used; i++) { ev = &events[i]; // Decide on helper fn to call and args to pass it. switch (ev->ekind) { case Event_Ir: helperName = "trace_instr"; helperAddr = trace_instr; break; case Event_Dr: helperName = "trace_load"; helperAddr = trace_load; break; case Event_Dw: helperName = "trace_store"; helperAddr = trace_store; break; case Event_Dm: helperName = "trace_modify"; helperAddr = trace_modify; break; default: tl_assert(0); } // Add the helper. argv = mkIRExprVec_2( ev->addr, mkIRExpr_HWord( ev->size ) ); di = unsafeIRDirty_0_N( /*regparms*/2, helperName, VG_(fnptr_to_fnentry)( helperAddr ), argv ); addStmtToIRSB( sb, IRStmt_Dirty(di) ); } events_used = 0; }
static void addEvent_FnEntry ( IRSB* sb, char *fnname) { IRExpr** argv; IRDirty* di; char *buf = (char *)VG_(malloc)("addEvent_FnEntry",100*sizeof(char)); tl_assert(buf!=NULL); VG_(strcpy)(buf,fnname); argv = mkIRExprVec_1( mkIRExpr_HWord( (HWord) buf )); di = unsafeIRDirty_0_N( /*regparms*/1, "trace_fnentry", VG_(fnptr_to_fnentry)( trace_fnentry ), argv ); if(events_used > 0) flushEvents(sb); addStmtToIRSB( sb, IRStmt_Dirty(di) ); }
//----------------------------------------------------------------- static void instrument_Unop(IRSB* sb, IRStmt* st, Addr64 cia) { Char thisFct[]="instrument_Unop"; IRExpr *op = st->Ist.WrTmp.data; IROp irop=op->Iex.Unop.op; void* f=callbackFromIROp(irop); if (f == NULL) return; OA_InstrumentContext inscon=contextFor(cia, irop); if (not_worth_watching(inscon)) return; // filter events that can't be attached to source-code location updateStats(inscon->op); IRExpr* oa_event_expr = mkIRExpr_HWord( (HWord)inscon ); IRExpr * args[2]; packToI32orI64(sb, op->Iex.Unop.arg, args, irop); IRExpr** argv = mkIRExprVec_2(args[0], oa_event_expr); IRDirty* di = unsafeIRDirty_0_N( 2, thisFct, VG_(fnptr_to_fnentry)( f ), argv); addStmtToIRSB( sb, IRStmt_Dirty(di) ); }
static void addEvent_RegW ( IRSB* sb, char *fnname, Int reg_no, IRAtom* tmp_val) { IRExpr** argv; IRDirty* di; tl_assert(clo_trace_mem); tl_assert(isIRAtom(tmp_val)); char *buf = (char *)VG_(malloc)("addEvent_RegW",100*sizeof(char)); tl_assert(buf!=NULL); VG_(strcpy)(buf,fnname); argv = mkIRExprVec_3( mkIRExpr_HWord( (HWord) buf ), mkIRExpr_HWord( reg_no ), tmp_val ); di = unsafeIRDirty_0_N( /*regparms*/3, "trace_regw", VG_(fnptr_to_fnentry)( trace_regw ), argv ); if(events_used > 0) flushEvents(sb); addStmtToIRSB( sb, IRStmt_Dirty(di) ); }
void instrument_WrTmp_RdTmp(IRStmt* st, IRSB* sb_out) { IRTemp tmp_lhs = st->Ist.WrTmp.tmp; IRExpr* data = st->Ist.WrTmp.data; IRTemp tmp_rhs = data->Iex.RdTmp.tmp; Int size = sizeofIRType_bits(typeOfIRTemp(sb_out->tyenv, tmp_rhs)); IRDirty* di; tl_assert(typeOfIRTemp(sb_out->tyenv, tmp_lhs) == typeOfIRTemp(sb_out->tyenv, tmp_rhs)); di = unsafeIRDirty_0_N(0, "helper_instrument_WrTmp_RdTmp", VG_(fnptr_to_fnentry)(helper_instrument_WrTmp_RdTmp), mkIRExprVec_3(mkIRExpr_HWord(tmp_lhs), mkIRExpr_HWord(tmp_rhs), mkIRExpr_HWord(size)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
void instrument_CAS_double_element(IRStmt* st, IRSB* sb_out) { IRCAS* cas = st->Ist.CAS.details; IRTemp oldHi = cas->oldHi, oldLo = cas->oldLo; IREndness end = cas->end; IRExpr* addr = cas->addr; IRExpr *expdHi = cas->expdHi, *expdLo = cas->expdLo; IRExpr *dataHi = cas->dataHi, *dataLo = cas->dataLo; Int size = sizeofIRType_bits(typeOfIRExpr(sb_out->tyenv, dataLo)); IROp op; IRExpr *expr, *expr2; IRDirty* di; tl_assert(isIRAtom(addr)); tl_assert(end == Iend_LE); // we assume endianness is little endian tl_assert(isIRAtom(dataLo)); tl_assert(isIRAtom(dataHi)); if (addr->tag == Iex_Const) tl_assert(addr->Iex.Const.con->tag == Ico_U32); tl_assert(typeOfIRExpr(sb_out->tyenv, addr) == typeOfIRExpr(sb_out->tyenv, dataLo)); switch (size) { case 8: op = Iop_CasCmpEQ8; break; case 16: op = Iop_CasCmpEQ16; break; case 32: op = Iop_CasCmpEQ32; break; default: VG_(tool_panic)("instrument_CAS_double_element"); } expr = assignNew(sb_out, IRExpr_Binop(op, IRExpr_RdTmp(oldLo), expdLo)); // statement has to be flat expr2 = assignNew(sb_out, IRExpr_Binop(op, IRExpr_RdTmp(oldHi), expdHi)); // statement has to be flat di = unsafeIRDirty_0_N(0, "helper_instrument_CAS_double_element", VG_(fnptr_to_fnentry)(helper_instrument_CAS_double_element), mkIRExprVec_6((addr->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, addr) : mkIRExpr_HWord(addr->Iex.Const.con->Ico.U32), mkIRExpr_HWord((dataLo->tag == Iex_RdTmp) ? dataLo->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord((dataHi->tag == Iex_RdTmp) ? dataHi->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord(size), assignNew_HWord(sb_out, expr), assignNew_HWord(sb_out, expr2)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
void instrument_Exit(IRStmt* st, IRSB* sb_out) { IRExpr* guard = st->Ist.Exit.guard; Int offsIP = st->Ist.Exit.offsIP; Int size = sizeofIRType_bits(typeOfIRConst(st->Ist.Exit.dst)); IRDirty* di; tl_assert(guard->tag == Iex_RdTmp); di = unsafeIRDirty_0_N(0, "helper_instrument_Exit", VG_(fnptr_to_fnentry)(helper_instrument_Exit), mkIRExprVec_4(assignNew_HWord(sb_out, guard), mkIRExpr_HWord(offsIP), mkIRExpr_HWord(size), mkIRExpr_HWord(guard->Iex.RdTmp.tmp)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
void AddLoadHelper(IRSB* sb, IRTemp lhs, IRExpr* addr) { IRDirty * d; ULong lhs_int; lhs_int = (HWord)lhs; d = unsafeIRDirty_0_N(0, "EmitLoadTmp2AddrHelper", &EmitRdTmpTmp2TmpHelper, mkIRExprVec_3( mkIRExpr_HWord(lhs_int), addr, mkIRExpr_HWord(counter) ) ); setHelperAnns(d); addStmtToIRSB(sb,IRStmt_Dirty(d)); return; }
void instrument_Put(IRStmt* st, IRSB* sb_out) { Int offset = st->Ist.Put.offset; IRExpr* data = st->Ist.Put.data; Int size = sizeofIRType_bits(typeOfIRExpr(sb_out->tyenv, data)); IRDirty* di; tl_assert(isIRAtom(data)); // the data transfer type is the type of data di = unsafeIRDirty_0_N(0, "helper_instrument_Put", VG_(fnptr_to_fnentry)(helper_instrument_Put), mkIRExprVec_3(mkIRExpr_HWord(offset), mkIRExpr_HWord((data->tag == Iex_RdTmp) ? data->Iex.RdTmp.tmp : IRTemp_INVALID), mkIRExpr_HWord(size)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }
void instrument_LLSC_Load_Linked(IRStmt* st, IRSB* sb_out) { IRTemp result = st->Ist.LLSC.result; IRExpr* addr = st->Ist.LLSC.addr; Int size = sizeofIRType_bits(typeOfIRTemp(sb_out->tyenv, result)); IRDirty* di; tl_assert(isIRAtom(addr)); if (addr->tag == Iex_Const) tl_assert(addr->Iex.Const.con->tag == Ico_U32); // the data transfer type is the type of result di = unsafeIRDirty_0_N(0, "helper_instrument_LLSC_Load_Linked", VG_(fnptr_to_fnentry)(helper_instrument_LLSC_Load_Linked), mkIRExprVec_3(mkIRExpr_HWord(result), (addr->tag == Iex_RdTmp) ? assignNew_HWord(sb_out, addr) : mkIRExpr_HWord(addr->Iex.Const.con->Ico.U32), mkIRExpr_HWord(size)) ); addStmtToIRSB(sb_out, IRStmt_Dirty(di)); }