From: David M. <dm...@gm...> - 2008-04-05 18:30:50
|
On Sat, Apr 5, 2008 at 5:37 AM, Ian Lynagh <ig...@ea...> wrote: > > > If so, I should be able to do it by writing a new tool, right? > I had a look at doing so, but got stuck. Does anyone have any pointers > on the best way to approach this please? > I second the suggestion to look at Lackey - it really is a wonderful example tool. That being said, here is one possible design for your tool which may make some sense after you've looked at Lackey. It probably isn't the best way of doing things, so maybe others will have thoughts. 1) Create a helper function void checkValueAndPrintST(HWord value) This function will take as an argument the value stored to or loaded from memory. It checks the value is equal to 1 mod 8, then if so calls VG_(get_and_pp_StackTrace) as Julian said. Our goal will be to add this helper function into an IRBB after each stor statement and after each expression which includes a load expression. We want to pass the helper function an expression which evaluates to the value stored or loaded. For example, if the original IRBB has the statement t5 = LDle:I32(0xDEADBEEF); the new IRBB after the tool is done will add a statement something like this following DIRTY 1:I1 ::: checkValueAndPrintST{0x3800a27c}(t5) 2) In the main IRBB instrumentation callback (this is lk_instrument in lk_main.c), do the following: for each statement s in the IRBB if s is an Ist_Store then insert helper function with argument s->Ist.Store.data endif if s is an Ist_Tmp then if tag of IRExpr in s->Ist.Tmp.Data is Iex_Load insert helper function with argument s->Ist.Tmp.tmp endif end Note this assumes the Ist.Store.data is always a single temporary variable, and that there are no compound expressions involving Iex_Load on the right hand side of an Ist_Tmp. The Ist.Store.data I haven't seen an exception, but there are a few I think for the second. You can look for such behaviour by running your program with --trace-flags=0100000 and --trace-notbelow=0, which shows the IR as it is passed to your tool. Some things to note with this approach: * Issue: The VEX core only handles arguments of type Ity_I32 passed to helper functions. If you try to pass an Ity_I1, Ity_I16, etc. you will hit a sanity check error during the compilation of your instrumented basic block. (At least, as of release 3.2, maybe it is different now). Solution 0: hack the VEX core to properly pass different arguments on your specific architecture(s). I have done this. It has the usual problems of requiring new work for different architectures, plus your tool now will not work with future Valgrind releases. It is quick to implement for Ity_I1, Ity_I16, etc. however. Solution 1: at instrumentation time, use the tyenv array in the basic block to check the type of the temporary variable tX . If tX is not Ity_I32, insert a new IRStmt which allocates a new temporary tZ and inserts a conversion from the type of tX to Ity_I32, then inserts a call to checkValueAndPrintST(tZ). I have not actually done this, but it "should work." * Issue: When adding many statements to a basic block which is already large, it is possible to overrun the VEX translation buffer during the compilation of the instrumented IRBB. (I've seen this with libjpg.) Solution: Increase the size of the VEX translation buffer. You need to modify #define N_TMPBUF 20000 in /coregrind/m_translate.c and also an assertion vg_assert(code_len > 0 && code_len < 20000); in coregrind/m_transtab.c . hope this is useful, good luck with your tool, -David Molnar |