Beispiel #1
0
/* 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) );
  }

}
Beispiel #2
0
/* 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
}
Beispiel #3
0
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);
}
Beispiel #4
0
/* 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
}
Beispiel #5
0
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));
}
Beispiel #6
0
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));
}
Beispiel #7
0
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; 
}
Beispiel #8
0
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);
}
Beispiel #10
0
/*
    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));
    }
}
Beispiel #11
0
/*
    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);
}
Beispiel #12
0
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));
}
Beispiel #13
0
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;
}
Beispiel #14
0
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));
}
Beispiel #15
0
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)) ));
}   
Beispiel #16
0
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;    
}
Beispiel #17
0
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));
}
Beispiel #18
0
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);
}
Beispiel #19
0
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));
}
Beispiel #20
0
/* 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) );
}
Beispiel #21
0
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;
}
Beispiel #22
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) );
}
Beispiel #23
0
//-----------------------------------------------------------------
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) );
}
Beispiel #24
0
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) );
}
Beispiel #25
0
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));
}
Beispiel #26
0
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));
}
Beispiel #27
0
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));
}
Beispiel #28
0
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;
}
Beispiel #29
0
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));
}
Beispiel #30
0
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));
}