[dtrace-discuss] Handling userland char ** pointers
Chip Bennett
cbennett at laurustech.com
Tue Aug 8 14:06:49 PDT 2006
Greetings Jonathan,
I knew that, but I broke up the probe clause so I could see the
intermediate trace data. My initial "one big" probe clause example
didn't work either, but for a different reason: At first, I was using
the (uintptr_t *) cast from the Tips and Tricks example. Some time
after breaking it up, I changed it to (uint32_t *), and didn't realize
that that had fixed my first problem and I had actually traded one
problem for another one.
Thanks!
Chip
Jonathan Adams wrote:
> On Tue, Aug 08, 2006 at 03:06:45PM -0500, Chip Bennett wrote:
>
>> I've been trying to get access to a userland string that's behind a
>> second level pointer using DTrace, but I can't seem to get it to work.
>>
>> I started with the example on the Team DTrace Tips and Tricks slides:
>>
>> trace(copyinstr(*(uintptr_t *)copyin(arg0, curpsinfo->pr_dmodel ==
>> PR_MODEL_ILP32 ? 4 : 8)));
>>
>> And when I couldn't get it to work, I started breaking it down into
>> smaller pieces to see what was going on at each step. Here's the "C"
>> and "D" code:
>>
>> --- pt.c ---
>>
> ...
>
>> --- pt.d ---
>>
>> pid$target::sub1:entry
>> {
>> trace (copyinstr(arg0));
>> }
>> pid$target::sub2:entry
>> {
>> sz = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? 4 : 8;
>> printf ("Userland pointer size = %d\n", sz);
>> }
>> pid$target::sub2:entry
>> {
>> pcp = (uint32_t *) copyin (arg0, sz); /* pcp is ptr to copy of
>> char * */
>> printf ("D pointer pcp = %a\n", pcp);
>> }
>>
> **** after the enabling ends, pcp points to garbage (it's scratch space) ***
>
>> pid$target::sub2:entry
>> {
>> cp = *pcp; /* cp is copy of char * */
>> printf ("%d byte userland pointer = %a\n", sizeof (cp), cp);
>> }
>> pid$target::sub2:entry
>> {
>> str = copyinstr(cp); /* str is the actual string */
>> trace (str);
>> }
>>
>
> The problem is that the storage used by copyin() is released at the end of
> the *enabling* (*NOT* the end of the probe firing). You need to copy the
> values you need out of the copyin()ed result before the '}' for your clause.
>
> By re-writing your example to:
>
> --- cut here ---
> pid$target::sub1:entry
> {
> trace(copyinstr(arg0));
> }
> pid$target::sub2:entry
> {
> sz = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? 4 : 8;
> printf("Userland pointer size = %d\n", sz);
> }
> pid$target::sub2:entry
> {
> cp = *(uint32_t *)copyin(arg0, sz);
> printf("%d byte userland pointer = %a\n", sizeof (cp), cp);
> }
> pid$target::sub2:entry
> {
> str = copyinstr(cp); /* str is the actual string */
> trace(str);
> }
> --- cut here ---
>
> I get:
>
>
> % dtrace -s pt.d -c ./pt
> dtrace: script 'tmpc.d' matched 4 probes
> Size of pointer = 4
> First 32 bit pointer = 20f64
> abcdefghijk
> Second 32 bit pointer = ffbff7b8
> abcdefghijk
> dtrace: pid 186527 has exited
> CPU ID FUNCTION:NAME
> 1 46206 sub1:entry abcdefghijk
> 1 46207 sub2:entry Userland pointer size = 4
>
> 1 46207 sub2:entry 4 byte userland pointer = 0x20f64
>
> 1 46207 sub2:entry abcdefghijk
>
> %
>
> Which looks correct.
>
>
>> One side note: the example on the slide used uintptr_t as the type for
>> the userland pointer. Using that instead of uint32_t and uint64_t,
>> didn't work for me either, but I changed it because, even though my
>> application seems to be 32 bit, sizeof(uintptr_t) kept returning 8 bytes.
>>
>
> Types are always evaluated as kernel types.
>
>
>> Also, I'm using gcc, if that matters.
>>
>
> It shouldn't matter.
>
> Cheers,
> - jonathan
>
>
More information about the dtrace-discuss
mailing list