Trying to trace 32 bit executable under SPARC here is the script typedef struct spwd{ char *sp_namp; /* login name */ char *sp_pwdp; /* encrypted passwd */ int sp_lstchg; /* date of last change */ int sp_min; /* min days to passwd change */ int sp_max; /* max days to passwd change*/ int sp_warn; /* warning period */ int sp_inact; /* max days inactive */ int sp_expire; /* account expiry date */ unsigned int sp_flag; /* not used */ } spwd_t; pid$target::getspnam:return { self->spwd = (spwd_t *)(uint32_t *)copyin(arg1, sizeof(spwd_t)); printf("name: %s", copyinstr(*(uint32_t *)self->spwd->sp_namp)); } getting an invalid address dtrace: error on enabled probe ID 1 (ID 76178: pid14270:libc.so.1:getspnam:return): invalid address (0x6e32333300000000) in action #6 at DIF offset 8 Any ideas? Thanks -- This message posted from opensolaris.org
max at bruningsystems.com
2009-Apr-09 21:59 UTC
[dtrace-discuss] userlan tracing woes - need help
Hi, tester wrote:> Trying to trace 32 bit executable under SPARC > > here is the script > typedef struct spwd{ > char *sp_namp; /* login name */ > char *sp_pwdp; /* encrypted passwd */ > int sp_lstchg; /* date of last change */ > int sp_min; /* min days to passwd change */ > int sp_max; /* max days to passwd change*/ > int sp_warn; /* warning period */ > int sp_inact; /* max days inactive */ > int sp_expire; /* account expiry date */ > unsigned int sp_flag; /* not used */ > } spwd_t; > > > pid$target::getspnam:return { > self->spwd = (spwd_t *)(uint32_t *)copyin(arg1, sizeof(spwd_t)); > printf("name: %s", copyinstr(*(uint32_t *)self->spwd->sp_namp)); > } > > getting an invalid address > > dtrace: error on enabled probe ID 1 (ID 76178: pid14270:libc.so.1:getspnam:return): invalid address (0x6e32333300000000) in action #6 at DIF offset 8 >0x6e32333300 is ascii string "332n" (not an address). max
since sp_namp is userland pointer to char shouldn''t the printf/copyinstr work? printf("name: %s", copyinstr((uint32_t *)self->spwd->sp_namp)); Thanks -- This message posted from opensolaris.org
s = (string)self->spwd; trace(s); seems to give the correct results. does that mean copyin derefrences char * present in structures during copyin so the scratch area contains the actual data? The above seem to work regardless of self->spwd = (struct spwd *)(uint32_t *) copyin((uintptr_t)(struct spwd *)arg1, sizeof(struct spwd)); or this self->spwd = (struct spwd *)(uint32_t *) copyin((uintptr_t)(struct spwd *)arg1, 4); Thanks -- This message posted from opensolaris.org
The automagic here is performed by trace() and DTrace''s string type. trace() operates the same way on D strings as it does with C char *''s. Try trace(*s) and note the difference. Dereferencing within trace() returns only the character at the given address. When you say trace(s) gives the correct results, do you mean that you are getting the value you expected from self->spwd->spname? You casted to string at self->spwd, but it and self-spwd->spname share an address. The intention isn''t clear from the code, but it works out to what you wanted. -- This message posted from opensolaris.org
I realize I am not getting it right. trace((string)self->spwd->sp_namp) is not the same as trace((string)self->spwd) You are correct trace((string)self->spwd) gives the user name from the structure, but trace((string)self->spwd->sp_namp) gives the hex values. Would appreciate some guidance on tracing userland strcutures containing char* . Thanks -- This message posted from opensolaris.org
Uh huh, and what about trace(copyinstr(self->spwd->sp_namp)) ? -- This message posted from opensolaris.org
I tried that initially, here is the result dtrace: error on enabled probe ID 1 (ID 215: pid17771:libc.so.1:getspanam:return): invalid address (0x6e32333300000000) in action #2 as max pointed out early the hex value is the user name and not an address. Thanks -- This message posted from opensolaris.org
At this point, I''m guessing I recreated all your experiments with all the same results. I vaguely knew I was going down a wrong path, but any amount of RTFM (more like GTFI) wasn''t helping. It finally dawned on me that DTrace doesn''t actually know what''s in a userland struct. I came across a blog Ben Rockwood that hints at using translators: http://www.cuddletech.com/blog/pivot/entry.php?id=923 I understood a translator as a means to separate the implementation details of a private data structure from a more stable or general way to address them in DTrace script. The hint seems to be that this could be applied to an arbitrary library or other defined structure. The documentation on the DTrace Wiki is the same as in the Solaris Dynamic Tracing Guide. There''s a separate example on the solarisinternals.org as well. I''ll post a working example, should I actually create one. It does make me wonder though how you got a value in string form at all. Might that be a bug? -- This message posted from opensolaris.org
It''s getting more confused as I dig more deeper into this I getting the same data from two different addresses as I did the below self->spwd = (uintptr_t *) copyin((uintptr_t)arg1, 4); self->a = (char *) copyin((uintptr_t)arg1, 4); printf("\nchar at address %a is %c\n",self->a,*self->a); printf("\nchar at address%a is %c\n",self->a+1,*(self->a+1)); printf("\nchar at address%a is %c\n",self->a+2,*(self->a+2)); printf("\nchar at address%a is %c\n",self->a+3,*(self->a+3)); printf("\nchar at address%a is %c\n",self->a+4,*(self->a+4)); printf("\nchar at address%a is %c\n",self->a+5,*(self->a+5)); printf("\nchar at address%a is %c\n",self->a+6,*(self->a+6)); printf("\nchar at address%a is %c\n",self->a+7,*(self->a+7)); printf("\nchar at address%a is %c\n",self->a+8,*(self->a+8)); printf("\nchar at address%a is %c\n",self->spwd,*((char *) self->spwd)); printf("\nchar at address%a is %c\n",self->spwd+1,*((char *) self->spwd+1)); char at address 0x300dc9249b8 is p char at address0x300dc9249b9 is q char at address0x300dc9249ba is r char at address0x300dc9249bb is s char at address0x300dc9249bc is char at address0x300dc9249bd is char at address0x300dc9249be is char at address0x300dc9249bf is char at address0x300dc9249c0 is char at address0x300dc9249b0 is p char at address0x300dc9249b8 is q 0x300dc9249b8 and 0x300dc9249b0 contain char p? I''ll take a look at the link you suggested and read the DTrace UG again. Thanks -- This message posted from opensolaris.org
On Thu, Apr 09, 2009 at 12:45:09PM -0700, tester wrote:> Trying to trace 32 bit executable under SPARC > > here is the script > typedef struct spwd{ > char *sp_namp; /* login name */ > char *sp_pwdp; /* encrypted passwd */ > int sp_lstchg; /* date of last change */ > int sp_min; /* min days to passwd change */ > int sp_max; /* max days to passwd change*/ > int sp_warn; /* warning period */ > int sp_inact; /* max days inactive */ > int sp_expire; /* account expiry date */ > unsigned int sp_flag; /* not used */ > } spwd_t; > > > pid$target::getspnam:return { > self->spwd = (spwd_t *)(uint32_t *)copyin(arg1, sizeof(spwd_t)); > printf("name: %s", copyinstr(*(uint32_t *)self->spwd->sp_namp));^^^^^^^^^^^^^ this seems wrong.> } > > getting an invalid address > > dtrace: error on enabled probe ID 1 (ID 76178: pid14270:libc.so.1:getspnam:return): invalid address (0x6e32333300000000) in action #6 at DIF offset 8 > > Any ideas?Please give your full dtrace(1M) invocation; are you using -32? If I change your enabling to: pid$target::getspnam:return /arg1 != NULL/ { self->spwd = (spwd_t *)copyin(arg1, sizeof(spwd_t)); printf("name: %s", copyinstr((uintptr_t)(uint32_t)self->spwd->sp_namp)); } and invoke it like: % dtrace -32 -s ./foo.d -c ''./callgetspnam'' dtrace: script ''/home/jwadams/foo.d'' matched 1 probe dtrace: pid 18766 has exited CPU ID FUNCTION:NAME 1 80527 getspnam:return name: jwadams % Everything works.. Cheers, - jonathan
Thanks Jonathan. # /usr/sbin/dtrace -32 -s d3_2.d -c /var/tmp/getspnam.o dtrace: script ''d3_2.d'' matched 1 probe dtrace: pid 12352 has exited dtrace: error on enabled probe ID 1 (ID 77377: pid12352:libc.so.1:getspnam:return): invalid address (0x6e322000) in action #2 at DIF offset 20 here is the complete script typedef struct spwd { char *sp_namp; /* user name */ char *sp_pwdp; /* user password */ int sp_lstchg; /* password lastchanged date */ int sp_min; /* minimum number of days between password changes */ int sp_max; /* number of days password is valid */ int sp_warn; /* number of days to warn user to change passwd */ int sp_inact; /* number of days the login may be inactive */ int sp_expire; /* date when the login is no longer valid */ unsigned int sp_flag; /* currently not being used */ } spwd_t; pid$target::getspnam:return /arg1 != NULL/ { self->spwd = (spwd_t *)copyin(arg1, sizeof(spwd_t)); printf("name: %s", copyinstr((uintptr_t)(uint32_t)self->spwd->sp_namp)); } -- This message posted from opensolaris.org