Saturday, 10 July 2010

sizeof(long) in Dtrace

Someone sent me a small dtrace script which I have been poring
over for the last week trying to figure out why it generates
an error (dereferencinging a typedef).



$ cat tests/dt021
/* Basic test for typedefs/structures. */
typedef unsigned long my_dev_t;
typedef struct {
my_dev_t dts_dev; /* device */
int dts_necbs; /* total number of ECBs */
} my_dtrace_state_t;

BEGIN
{
trace(((my_dtrace_state_t *)arg0)->dts_necbs);
}
$ dtrace -S -s tests/dt021
DIFO 0x1caa4c0 returns D type (integer) (size 4)
OFF OPCODE INSTRUCTION
00: 29010601 ldgs DT_VAR(262), %r1 ! DT_VAR(262) = "arg0"
01: 25000002 setx DT_INTEGER[0], %r2 ! 0x0
02: 04010201 sll %r1, %r2, %r1
03: 05010201 srl %r1, %r2, %r1
04: 25000102 setx DT_INTEGER[1], %r2 ! 0x8
05: 07010201 add %r1, %r2, %r1
06: 1e010001 ldsw [%r1], %r1
07: 23000001 ret %r1

NAME ID KND SCP FLAG TYPE
arg0 106 scl glb r D type (integer) (size 8)
dtrace: script 'tests/dt021' matched 1 probe
dtrace: error on enabled probe ID 1 (ID 1: dtrace:::BEGIN): invalid kernel access in action #1 at DIF offset 24



I learnt a lot from such a simple script. What is arg0 in a BEGIN clause ?
Why and how does the kernel handle such things.


arg0 is a pointer to a structure containing useful info for a dtrace
script (a form of introspection). The script above works fine on FreeBSD
and MacOS, which I could repeat. But the bottom line is a bug in the dtrace
port meant that the credentials (uid) of the caller were not being
passed in an ioctl(), meaning that the kernel was refusing
to honor the peek into kernel memory.


Its a shame that dtrace doesnt print a meaningful error message here.
I had to scatter the code with lots of printk()s to follow the cause/effect.


Having solved this, I came across another issue - namely sizeof(long)
is either misdefined in all the dtrace implementations, or the documentation
is wrong:


http://wikis.sun.com/display/DTrace/Types,+Operators+and+Expressions


The docs say that a long is 4 bytes - no matter the platform. But dtrace
codifies sizeof(long) as 8 for a 64-bit platform. Maybe I am misreading
the code (libdtrace/dt_open.c). You can select a model on the command
line.


Another interesting thing is the on MacOSX, /usr/sbin/dtrace is a dual
mode application - containing a 32 bit and 64 bit binary. Not sure I understand
why (presumably so that if Snow Leopard is installed on older 32-bit
only hardware, it will all work). Not clear when I run on a 64-bit
capable cpu which version it is selecting.


Another thing I notice and dislike in dtrace is lack of C++ style
comments. I may just add that; no reason not to, even if the
competition (Apple, FreeBSD, we wont talk about Oracle for now) dont.


Post created by CRiSP v10.0.2a-b5875


No comments:

Post a Comment