[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