DRD, --trace-addr: trace stored values too


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12290 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c
index c7bfded..b531ceb 100644
--- a/drd/drd_load_store.c
+++ b/drd/drd_load_store.c
@@ -85,19 +85,26 @@
 }
 
 void DRD_(trace_mem_access)(const Addr addr, const SizeT size,
-                            const BmAccessTypeT access_type)
+                            const BmAccessTypeT access_type,
+                            const HWord stored_value)
 {
    if (DRD_(is_any_traced)(addr, addr + size))
    {
       char* vc;
 
       vc = DRD_(vc_aprint)(DRD_(thread_get_vc)(DRD_(thread_get_running_tid)()));
-      DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
-                           access_type == eLoad ? "load "
-                           : access_type == eStore ? "store"
-                           : access_type == eStart ? "start"
-                           : access_type == eEnd ? "end  " : "????",
-                           addr, size, DRD_(thread_get_running_tid)(), vc);
+      if (access_type == eStore && size <= sizeof(HWord)) {
+         DRD_(trace_msg_w_bt)("store 0x%lx size %ld val 0x%lx (thread %d /"
+                              " vc %s)", addr, size, stored_value,
+                              DRD_(thread_get_running_tid)(), vc);
+      } else {
+         DRD_(trace_msg_w_bt)("%s 0x%lx size %ld (thread %d / vc %s)",
+                              access_type == eLoad ? "load "
+                              : access_type == eStore ? "store"
+                              : access_type == eStart ? "start"
+                              : access_type == eEnd ? "end  " : "????",
+                              addr, size, DRD_(thread_get_running_tid)(), vc);
+      }
       VG_(free)(vc);
       tl_assert(DRD_(DrdThreadIdToVgThreadId)(DRD_(thread_get_running_tid)())
                 == VG_(get_running_tid)());
@@ -106,12 +113,13 @@
 
 static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size)
 {
-   return DRD_(trace_mem_access)(addr, size, eLoad);
+   return DRD_(trace_mem_access)(addr, size, eLoad, 0);
 }
 
-static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size)
+static VG_REGPARM(3) void drd_trace_mem_store(const Addr addr,const SizeT size,
+                                              const HWord stored_value)
 {
-   return DRD_(trace_mem_access)(addr, size, eStore);
+   return DRD_(trace_mem_access)(addr, size, eStore, stored_value);
 }
 
 static void drd_report_race(const Addr addr, const SizeT size,
@@ -363,23 +371,61 @@
    addStmtToIRSB(bb, IRStmt_Dirty(di));
 }
 
-static void instrument_store(IRSB* const bb,
-                             IRExpr* const addr_expr,
-                             const HWord size)
+static const IROp u_widen_irop[5][9] = {
+   [1][2] = Iop_8Uto16,
+   [1][4] = Iop_8Uto32,
+   [1][8] = Iop_8Uto64,
+   [2][4] = Iop_16Uto32,
+   [2][8] = Iop_16Uto64,
+   [4][8] = Iop_32Uto64,
+};
+
+static void instrument_store(IRSB* const bb, IRExpr* const addr_expr,
+                             IRExpr* const data_expr)
 {
    IRExpr* size_expr;
    IRExpr** argv;
    IRDirty* di;
+   HWord size;
+
+   size = sizeofIRType(typeOfIRExpr(bb->tyenv, data_expr));
 
    if (UNLIKELY(DRD_(any_address_is_traced)()))
    {
+      IRExpr *hword_data_expr;
+
+      if (size == sizeof(HWord)) {
+         hword_data_expr = data_expr;
+      } else {
+         IROp widen_op;
+
+         tl_assert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
+         if (size < sizeof(u_widen_irop)/sizeof(u_widen_irop[0])) {
+            widen_op = u_widen_irop[size][sizeof(HWord)];
+            if (!widen_op)
+               widen_op = Iop_INVALID;
+         } else {
+            widen_op = Iop_INVALID;
+         }
+         if (widen_op != Iop_INVALID) {
+            IRTemp tmp;
+
+            tmp = newIRTemp(bb->tyenv, sizeof(HWord) == 4 ? Ity_I32 : Ity_I64);
+            addStmtToIRSB(bb,
+                          IRStmt_WrTmp(tmp, IRExpr_Unop(widen_op, data_expr)));
+            hword_data_expr = IRExpr_RdTmp(tmp);
+         } else {
+            hword_data_expr = mkIRExpr_HWord(0);
+         }
+      }
       addStmtToIRSB(bb,
          IRStmt_Dirty(
-            unsafeIRDirty_0_N(/*regparms*/2,
-			      "drd_trace_mem_store",
-			      VG_(fnptr_to_fnentry)
-			      (drd_trace_mem_store),
-			      mkIRExprVec_2(addr_expr, mkIRExpr_HWord(size)))));
+            unsafeIRDirty_0_N(/*regparms*/3,
+                              "drd_trace_mem_store",
+                              VG_(fnptr_to_fnentry)
+                              (drd_trace_mem_store),
+                              mkIRExprVec_3(addr_expr, mkIRExpr_HWord(size),
+                                            hword_data_expr))));
    }
 
    if (!s_check_stack_accesses && is_stack_access(bb, addr_expr))
@@ -479,12 +525,7 @@
 
       case Ist_Store:
          if (instrument)
-         {
-            instrument_store(bb,
-                             st->Ist.Store.addr,
-                             sizeofIRType(typeOfIRExpr(bb->tyenv,
-                                                       st->Ist.Store.data)));
-         }
+            instrument_store(bb, st->Ist.Store.addr, st->Ist.Store.data);
          addStmtToIRSB(bb, st);
          break;