|
From: Dave A. <ai...@gm...> - 2006-03-08 01:26:43
|
I want to trace all writes to an mmaped piece of RAM (a GPU) using valgrind=
,
I wrote a trivial store interceptor copying from lackey, and I've set
it up to intercept mmap (changed new_mem_mmap to see the offset) and
if I like the offset I want to dump info in that area.
This is fine and I can tell when the app writes to the address, and
what address it is and how much, however I'm not really sure how I can
actually extract the data the app is writing.
Do I need to do something along the lines of memcheck with all the
shadowing stuff in order to get what data is being written into the
area in my handler function?
Some of my code is below (unworking.. can't push non-32 or 64-bit words)
Dave.
static struct mmt_memmap {
Addr addr;
SizeT len;
} mmt_gpu_reg;
static VG_REGPARM(3) void trace_store(Addr addr, SizeT size)
{
if ((addr > mmt_gpu_reg.addr) && (addr < mmt_gpu_reg.addr+mmt_gpu_reg.len=
))
VG_(printf)("store: %p, %d\n", addr-mmt_gpu_reg.addr, size);
}
static void mmt_post_clo_init(void)
{
}
static
IRBB* mmt_instrument ( VgCallbackClosure* closure,
IRBB* bb_in,
VexGuestLayout* layout,
VexGuestExtents* vge,
IRType gWordTy, IRType hWordTy )
{
IRBB* bb;
IRStmt* st;
IRDirty* di;
int i;
IRExpr** argv;
IRExpr* addr_expr;
IRExpr* size_expr;
IRExpr* data_expr;
IRType arg_ty;
if (gWordTy !=3D hWordTy) {
/* We don't currently support this case. */
VG_(tool_panic)("host/guest word size mismatch");
}
/* Set up BB */
bb =3D emptyIRBB();
bb->tyenv =3D dopyIRTypeEnv(bb_in->tyenv);
bb->next =3D dopyIRExpr(bb_in->next);
bb->jumpkind =3D bb_in->jumpkind;
// Copy verbatim any IR preamble preceding the first IMark
for (i =3D 0; i < bb_in->stmts_used; i++) {
st =3D bb_in->stmts[i];
tl_assert(st);
switch(st->tag) {
case Ist_Store:
arg_ty =3D typeOfIRExpr(bb->tyenv, st->Ist.Store.data);
addr_expr =3D st->Ist.Store.addr;
size_expr =3D mkIRExpr_HWord(sizeofIRType(arg_ty));
data_expr =3D st->Ist.Store.data;
switch(arg_ty)
{
}
switch(data_expr->tag) {
case Iex_Tmp:
case Iex_Const:
=09argv =3D mkIRExprVec_3( addr_expr, size_expr, data_expr );
=09di =3D unsafeIRDirty_0_N( /*regparms*/2,
=09=09=09=09"trace_store",
=09=09=09=09VG_(fnptr_to_fnentry)( trace_store ),
=09=09=09=09argv );
=09addStmtToIRBB( bb, IRStmt_Dirty(di) );
=09break;
default:
=09break;
}
default:
break;
}
addStmtToIRBB( bb, st );
}
return bb;
|
|
From: Nicholas N. <nj...@cs...> - 2006-03-08 01:36:47
|
On Wed, 8 Mar 2006, Dave Airlie wrote:
> I wrote a trivial store interceptor copying from lackey, and I've set
> it up to intercept mmap (changed new_mem_mmap to see the offset) and
> if I like the offset I want to dump info in that area.
>
> This is fine and I can tell when the app writes to the address, and
> what address it is and how much, however I'm not really sure how I can
> actually extract the data the app is writing.
>
> Do I need to do something along the lines of memcheck with all the
> shadowing stuff in order to get what data is being written into the
> area in my handler function?
Nope. You have the address -- just dereference it!
> static VG_REGPARM(3) void trace_store(Addr addr, SizeT size)
> {
> if ((addr > mmt_gpu_reg.addr) && (addr < mmt_gpu_reg.addr+mmt_gpu_reg.len))
> VG_(printf)("store: %p, %d\n", addr-mmt_gpu_reg.addr, size);
> }
Here you need something like this (warning, untested code):
ULong data;
switch (size) {
case 1: data = *(UChar*)addr;
case 2: data = *(UShort*)addr;
case 4: data = *(UInt*)addr;
case 8: data = *(ULong*)addr;
default: /*barf*/
}
I think that'll work.
Nick
|
|
From: Olly B. <ol...@su...> - 2006-03-08 01:40:01
|
On 2006-03-08, Nicholas Nethercote <nj...@cs...> wrote:
> ULong data;
> switch (size) {
> case 1: data = *(UChar*)addr;
> case 2: data = *(UShort*)addr;
> case 4: data = *(UInt*)addr;
> case 8: data = *(ULong*)addr;
> default: /*barf*/
> }
>
> I think that'll work.
Not without the addition of "break;" after each case!
Cheers,
Olly
|
|
From: Dave A. <ai...@gm...> - 2006-03-08 01:42:22
|
> > Nope. You have the address -- just dereference it! > I knew I was missing something simple, forgot that data was already written to the address at that time.. I'd really like to know though what the system was going to write before it wrote it as well, as some graphics chips may have write-only registers, where readback gives a totally different answer... in that case do I need to do that hard work? Dave. |
|
From: Nicholas N. <nj...@cs...> - 2006-03-08 03:52:04
|
On Wed, 8 Mar 2006, Dave Airlie wrote: > I'd really like to know though what the system was going to write > before it wrote it as well, as some graphics chips may have write-only > registers, where readback gives a totally different answer... in that > case do I need to do that hard work? In that case you need to pass in the to-be-stored value to trace_store(). Imagine a store, something like: STORE (t1), t2 which stores the value in register t2 in the address pointed to by t1. Currently you're passing in t1 to trace_store(). You want to also pass in t2. You are already almost doing it -- you have three args in the instrumentation code, but trace_store() only takes two. I don't think data_expr is what you want, but you're close. Memcheck and/or Cachegrind must do similar things in places. Nick |
|
From: Ashley P. <as...@qu...> - 2006-03-08 10:33:15
|
On Wed, 2006-03-08 at 12:42 +1100, Dave Airlie wrote: > > > > Nope. You have the address -- just dereference it! > > > > I knew I was missing something simple, forgot that data was already > written to the address at that time.. > > I'd really like to know though what the system was going to write > before it wrote it as well, as some graphics chips may have write-only > registers, where readback gives a totally different answer... in that > case do I need to do that hard work? This tool is exactly the same as one I was discussing on Monday, we to do something very similar (with a network card rather than a GPU) and have the problem you describe here that the mmaped memory is write-only, it gives back garbage when read. I'd be very interested in seeing your tool when it's up and running. Ashley, |