|
From: Scott P. <pa...@la...> - 2010-05-13 20:14:33
|
I'm writing my first Valgrind tool, and I'm baffled about how to pass
a GetI.ix to an execution-time function. For example, if at
instrumentation time I encounter a GETI(128:8xI8)[t1,0] expression,
how can I ensure that the function call I insert receives the
*contents* of the t1 temporary when called?
IRSB* myinstrumenter(...)
{
...
IRExpr* myGetIexpr;
...
dcall_argv = mkIRExprVec_1(<WHAT GOES HERE?>)
dcall = unsafeIRDirty_0_N(0, "myfunction",
VG_(fnptr_to_fnentry)(&myfunction),
dcall_argv);
addStmtToIRSB(sbOut, IRStmt_Dirty(dcall));
...
}
void myfunction(<WHAT GOES HERE?> ixValue)
{
...
}
Thanks in advance,
-- Scott
|
|
From: Julian S. <js...@ac...> - 2010-05-13 20:35:36
|
On Thursday 13 May 2010, Scott Pakin wrote:
> I'm writing my first Valgrind tool, and I'm baffled about how to pass
> a GetI.ix to an execution-time function. For example, if at
> instrumentation time I encounter a GETI(128:8xI8)[t1,0] expression,
> how can I ensure that the function call I insert receives the
> *contents* of the t1 temporary when called?
>
> IRSB* myinstrumenter(...)
> {
> ...
> IRExpr* myGetIexpr;
> ...
Let's say that you have (at jit time) some "IRTemp t", which
holds the identity of t1. Then
> dcall_argv = mkIRExprVec_1(<WHAT GOES HERE?>)
mkIRExprVec_1( mkexpr(t) )
> dcall = unsafeIRDirty_0_N(0, "myfunction",
> VG_(fnptr_to_fnentry)(&myfunction),
> dcall_argv);
> addStmtToIRSB(sbOut, IRStmt_Dirty(dcall));
> ...
> }
>
> void myfunction(<WHAT GOES HERE?> ixValue)
Word ixValue
> {
> ...
> }
(Word is a signed machine word)
Passing the identity of bits of the guest state to helper functions
is pretty dangerous; you need to be careful to tell the IR optimiser
that that whole section of the guest state can change in arbitrary ways.
It's safer to pass values (simulated register contents, really)
to helper functions. FWIW, the guest state section denoted by
(128:8xI8) is the tag array for the x87 register stack, which I doubt
contains anything much interesting anyway.
J
|
|
From: Scott P. <pa...@la...> - 2010-05-13 22:06:02
|
Julian,
Thanks for the prompt response!
> Passing the identity of bits of the guest state to helper functions
> is pretty dangerous; you need to be careful to tell the IR optimiser
> that that whole section of the guest state can change in arbitrary ways.
I'm just keeping track of which register bytes have been read when.
I'm not actually modifying any part of guest state.
> It's safer to pass values (simulated register contents, really)
> to helper functions.
I'm not sure I understand this. Maybe I didn't ask my question
correctly so let me try again: If my instrumentation code sees
t3 = 0x1000
t4 = Add32(t3, 0x234)
t5 = GETI(128:8xI8)[t4,-1]
then I want the handler function to get passed 0x1234. Is 0x1234 what
you mean by a value/simulated register contents? If so, then what do
I put in my instrumentation code to ensure that the handler sees that
0x1234?
-- Scott
|
|
From: Julian S. <js...@ac...> - 2010-05-14 08:00:43
|
> I'm not sure I understand this. Maybe I didn't ask my question > correctly so let me try again: If my instrumentation code sees > > t3 = 0x1000 > t4 = Add32(t3, 0x234) > t5 = GETI(128:8xI8)[t4,-1] > > then I want the handler function to get passed 0x1234. Is 0x1234 what > you mean by a value/simulated register contents? Yes. > If so, then what do > I put in my instrumentation code to ensure that the handler sees that > 0x1234? So, my answer from yesterday stands: in this case, if you have an "IRTemp t" where t is "t4" in your code, then you need to pass the arg "mkexpr(t)" as the relevant component of mkIRExprVec_N that you use to prepare the args for the call. That said ... ---------- > I'm just keeping track of which register bytes have been read when. > I'm not actually modifying any part of guest state. You are going to run into problems with the IR optimiser, which runs before the IR gets to your instrumenter. It aggressively does the following things w.r.t. gets and puts (reads/writes of the guest register state): * redundant-Get removal t1 = Get(ty, off); ...; t2 = Get(ty, off) ==> t1 = Get(ty, off); ...; t2 = t1 provided there are no intervening Puts to the same area in the "..." * redundant-Put removal Put(off) = e1; ...; Put(off) = e2 ==> Put(off) = e2 provided, uh, the second Put postdominates the first Put, and there are no Gets of the area in the "..." * Put-Get forwarding Put(off) = e1; ...; t2 = Get(off,ty) ==> ttemp = e1; Put(off) = ttemp; ...; t2 = ttemp; provided there are no Puts of the area in the "..." There is related trickery GetI/PutI, which are Get/Put variants in which the accessed area is not known until run time. This is needed to model rotating register arrays, like the x87 FPU stack. Anyway, the longer the superblock, the more effective the above are. J |
|
From: Scott P. <pa...@la...> - 2010-05-14 16:23:00
|
Julian, > So, my answer from yesterday stands: in this case, if you have an > "IRTemp t" where t is "t4" in your code, then you need to pass > the arg "mkexpr(t)" as the relevant component of mkIRExprVec_N that > you use to prepare the args for the call. Thanks; that seems to work. (I just wanted to make sure I wasn't misinterpreting the data I was getting.) > You are going to run into problems with the IR optimiser, which runs > before the IR gets to your instrumenter. It aggressively does the > following things w.r.t. gets and puts (reads/writes of the guest > register state): Got it. Fortunately, in my tool's case, those IR optimizations shouldn't pose a problem. Thanks for the detailed explanation, -- Scott |