]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a --trace-mem option to Lackey to print out a memory access trace, if
authorNicholas Nethercote <njn@valgrind.org>
Fri, 30 Dec 2005 22:39:58 +0000 (22:39 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Fri, 30 Dec 2005 22:39:58 +0000 (22:39 +0000)
only so people will stop asking how to do it.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5462

lackey/docs/lk-manual.xml
lackey/lk_main.c

index 6bec5ea6ad6beaa5ea9d3c3befefe97d029476be..e21466ebd10ff5a1c051996f39d5d7ac1be5509e 100644 (file)
@@ -4,7 +4,7 @@
 
 <chapter id="lk-manual" xreflabel="Lackey">
 
-<title>Lackey: a very simple profiler</title>
+<title>Lackey: a simple profiler and memory tracer</title>
 
 <para>To use this tool, you must specify
 <computeroutput>--tool=lackey</computeroutput> on the Valgrind
@@ -71,6 +71,16 @@ tool.</para>
     "F32", "F64", and "V128").</para>
    </listitem>
 
+   <listitem>
+    <para>When command line option
+    <computeroutput>--trace-mem=yes</computeroutput> is
+    specified, it prints out the size and address of almost every load and
+    store made by the program.  See Section 3.3.7 of Nicholas Nethercote's
+    PhD dissertation "Dynamic Binary Analysis and Instrumentation", 2004,
+    for details about the few loads and stores that it misses, and other
+    caveats about the accuracy of the address trace.</para>
+   </listitem>
+
   </orderedlist>
 
  </listitem>
index e19e64a8443a3a0ef208974b67ec29251b3b3589..1aa5e85e913e8cc30d7a12ca40298389ca5f7024 100644 (file)
    The GNU General Public License is contained in the file COPYING.
 */
 
+// This tool shows how to do some basic instrumentation.
+//
+// In particular, if you are interested in tracing every load and store a
+// program does, use the --trace-mem=yes option.  Please note that the
+// address trace is good, but not perfect;  see Section 3.3.7 of Nicholas
+// Nethercote's PhD dissertation "Dynamic Binary Analysis and
+// Instrumentation", 2004, for details about the few loads and stores that
+// it misses, and other caveats about the accuracy of the address trace.
+//
+// If you want to modify how the memory traces are printed/gathered, look at
+// the code that is controlled by the variable 'lk_clo_trace_mem' and the
+// functions 'trace_load()' and 'trace_mem'..  With a bit of effort you
+// should be able to see which other bits of code can be removed, if that's
+// what you want.  If you want to do more complex modifications, please read
+// VEX/pub/libvex_ir.h to understand the intermediate representation.
+//
+// For further inspiration, you should look at cachegrind/cg_main.c which
+// handles memory accesses in a more sophisticated way -- it groups them
+// together for processing into twos and threes so that fewer C calls are
+// made and things run faster.
+
 #include "pub_tool_basics.h"
 #include "pub_tool_tooliface.h"
 #include "pub_tool_libcassert.h"
@@ -47,6 +68,9 @@ static Char* lk_clo_fnname = "_dl_runtime_resolve";
  * with command line option --detailed-counts. */
 static Bool lk_clo_detailed_counts = False;
 
+/* If true, print the trace of loads and stores.  Set with --trace-mem. */
+static Bool lk_clo_trace_mem = False;
+
 /***********************************************************************
  * Implement the needs_command_line_options for Valgrind.
  **********************************************************************/
@@ -55,6 +79,7 @@ static Bool lk_process_cmd_line_option(Char* arg)
 {
    VG_STR_CLO(arg, "--fnname", lk_clo_fnname)
    else VG_BOOL_CLO(arg, "--detailed-counts", lk_clo_detailed_counts)
+   else VG_BOOL_CLO(arg, "--trace-mem",       lk_clo_trace_mem)
    else
       return False;
    
@@ -88,7 +113,6 @@ static ULong n_guest_instrs  = 0;
 static ULong n_Jccs          = 0;
 static ULong n_Jccs_untaken  = 0;
 
-__attribute__((unused))
 static void add_one_func_call(void)
 {
    n_func_calls++;
@@ -104,13 +128,11 @@ static void add_one_BB_completed(void)
    n_BBs_completed++;
 }
 
-__attribute__((unused))
 static void add_one_IRStmt(void)
 {
    n_IRStmts++;
 }
 
-__attribute__((unused))
 static void add_one_guest_instr(void)
 {
    n_guest_instrs++;
@@ -223,6 +245,20 @@ static void print_details ( void )
 }
 
 
+/***********************************************************************
+ * Data and helpers related to --trace-mem.      
+ **********************************************************************/
+
+static VG_REGPARM(2) void trace_load(Addr addr, SizeT size)
+{
+   VG_(printf)("load : %p, %d\n", addr, size);
+}
+
+static VG_REGPARM(2) void trace_store(Addr addr, SizeT size)
+{
+   VG_(printf)("store: %p, %d\n", addr, size);
+}
+
 /***********************************************************************
  * Implement the basic_tool_funcs for Valgrind.
  **********************************************************************/
@@ -246,6 +282,9 @@ IRBB* lk_instrument( IRBB* bb_in, VexGuestLayout* layout,
    IRBB*    bb;
    Char     fnname[100];
    IRType   type;
+   IRExpr** argv;
+   IRExpr*  addr_expr;
+   IRExpr*  size_expr;
 
    if (gWordTy != hWordTy) {
       /* We don't currently support this case. */
@@ -345,6 +384,19 @@ IRBB* lk_instrument( IRBB* bb_in, VexGuestLayout* layout,
           * constrains them to being flat SSA-style.
           */
          case Ist_Store:
+            // Add a call to trace_store() if --trace-mem=yes.
+            if (lk_clo_trace_mem) {
+               addr_expr = st->Ist.Store.addr;
+               size_expr = mkIRExpr_HWord( 
+                             sizeofIRType(
+                               typeOfIRExpr(bb->tyenv, st->Ist.Store.data)));
+               argv = mkIRExprVec_2( addr_expr, size_expr );
+               di = unsafeIRDirty_0_N( /*regparms*/2, 
+                                       "trace_store",
+                                       VG_(fnptr_to_fnentry)( trace_store ), 
+                                       argv );
+               addStmtToIRBB( bb, IRStmt_Dirty(di) );
+            }
             if (lk_clo_detailed_counts) {
                type = typeOfIRExpr(bb->tyenv, st->Ist.Store.data);
                tl_assert(type != Ity_INVALID);
@@ -354,6 +406,20 @@ IRBB* lk_instrument( IRBB* bb_in, VexGuestLayout* layout,
             break;
 
          case Ist_Tmp:
+            // Add a call to trace_load() if --trace-mem=yes.
+            if (lk_clo_trace_mem) {
+               IRExpr* data = st->Ist.Tmp.data;
+               if (data->tag == Iex_Load) {
+                  addr_expr = data->Iex.Load.addr;
+                  size_expr = mkIRExpr_HWord( sizeofIRType(data->Iex.Load.ty) );
+                  argv = mkIRExprVec_2( addr_expr, size_expr );
+                  di = unsafeIRDirty_0_N( /*regparms*/2, 
+                                          "trace_load",
+                                          VG_(fnptr_to_fnentry)( trace_load ), 
+                                          argv );
+                  addStmtToIRBB( bb, IRStmt_Dirty(di) );
+               }
+            }
             if (lk_clo_detailed_counts) {
                IRExpr* expr = st->Ist.Tmp.data;
                type = typeOfIRExpr(bb->tyenv, expr);