Something to remember when using DTrace on userland programs

September 5, 2008

As mentioned before, Solaris's DTrace is fundamentally a kernel debugger; in order to extract information from userland programs, you need to copy it to kernel space (generally using DTrace's copyin() function) before you can start printing it or otherwise use it. The most important thing to remember about this is that you wind up dealing with two sorts of pointers: userland pointers, which is what are in all of those data structures you copy in from your program, and kernel pointers, which is what copyin() and friends return. Let's call the former 'locations' and the latter 'pointers'.

Keeping them straight is vital, because you have to do different things in order to use them; you dereference pointers but give locations to copyin(), which returns a pointer that you have to dereference in order to get the actual userland data. Fortunately they have different types; locations are type uintptr_t, while pointers are, well, pointers. Thus the incantation to get an object of primitive type TYPE (like an integer, a long, or a pointer) from a user level pointer LOC is:

uintptr_t LOC;
TYPE var;
var = * ((TYPE *) copyin(LOC, sizeof(TYPE)));

(Unfortunately DTrace doesn't have #define, or you could make this a macro.)

If this seems confusing, well, it is.

The DTrace language is very C-like and it lets you define structures just like C, enough so that you can generally just copy the structure definitions from your C header files into your DTrace program. However, watch out; all of the pointers in your program's structures are userland pointers, ie locations, not kernel pointers (real pointers). You will avoid a lot of confusion if you take all of those structure definitions and change the type of every pointer field to be uintptr_t, so that you will get a compile time error if you ever attempt to directly dereference one (instead of tediously doing it via copyin()).

(The DTrace language helps you out by not having a #include, so you have to copy the structure definitions to start with.)

As a suggestion: if you do this, leave yourself a comment about what type the pointers actually point to, so you can remember what you get when you dereference them via copyin() (and how much data you need to tell copyin() to copy).

Written on 05 September 2008.
« Why SMTP needs a way of communicating partial success for message delivery
Why negative DNS caching is necessary »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Sep 5 01:09:44 2008
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.