Hi, I am trying to print data returned from a door call. The door_return function has the following prototype int door_return(char *data_ptr, size_t data_size, door_desc_t *desc_ptr, uint_t num_desc); I need some assistance to print data pointed by data_ptr. I tried with tracemem, I consistently get invalid address for all door_calls. Thanks for your help. -- This message posted from opensolaris.org
> I am trying to print data returned from a door call. The door_return function has the following prototype > > int door_return(char *data_ptr, size_t data_size, > door_desc_t *desc_ptr, uint_t num_desc); > > I need some assistance to print data pointed by data_ptr. I tried with tracemem, I consistently get invalid address for all door_calls.Remember that if you''re trying to trace memory from user-land you''ll have to do a copyin(). For example: tracemem(copyin(arg0, 64), 64); Adam -- Adam Leventhal, Fishworks http://blogs.sun.com/ahl
Ouch, copyin bites again. BTW, can you please explain the 8 byte difference in o/p fbt::door_call:entry { printf("entry args are %x and %a \n", arg0, copyin(arg1,4)); door_arg = (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? copyin(arg1, 4) : copyin(arg1, 8)); printf("argument pointer %a \n", door_arg); } 8 bytes difference in o/p entry args are 3 and 0x30226000040 argument pointer 0x30226000048 I was expecting either a 32bit or 64 bit address. I am getting 44 bit address. Thanks Adam -- This message posted from opensolaris.org
On Sun, Mar 14, 2010 at 07:42:08PM -0700, tester wrote:> Ouch, copyin bites again.Remember: copyin() returns the kernel address of the buffer into which it copied the data that you asked for. To get to the data you have to dereference that pointer.> BTW, can you please explain the 8 byte difference in o/p > > fbt::door_call:entry > { > printf("entry args are %x and %a \n", arg0, copyin(arg1,4)); > door_arg = (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ? copyin(arg1, 4) : copyin(arg1, 8)); > printf("argument pointer %a \n", door_arg); > } > > 8 bytes difference in o/p > > entry args are 3 and 0x30226000040 > argument pointer 0x30226000048 > > I was expecting either a 32bit or 64 bit address. I am getting 44 bit address.That''s printing the kernel address returned by copyin(). Try this: fbt::door_call:entry /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ { printf("entry args are %x and %x \n", arg0, *(uint32_t *)copyin(arg1, 4)); } fbt::door_call:entry /curpsinfo->pr_dmodel == PR_MODEL_LP64/ { printf("entry args are %lx and %lx \n", arg0, *(uint64_t *)copyin(arg1, 8)); } Nico --
> That''s printing the kernel address returned by > copyin(). Try this: > > fbt::door_call:entry > /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ > { > printf("entry args are %x and %x \n", arg0, > , *(uint32_t *)copyin(arg1, 4)); > } > > fbt::door_call:entry > /curpsinfo->pr_dmodel == PR_MODEL_LP64/ > { > printf("entry args are %lx and %lx \n", arg0, > , *(uint64_t *)copyin(arg1, 8)); > } > > NicoThanks Nico. Since arg1 is a pointer to a struct in userland, can I use ptr = *(uint32_t *)copyin(arg1, 4); tracemem(ptr,10); to dump the structure. I tried this and getting invalid address (0xfb07bc75) in action #4. Thanks again. -- This message posted from opensolaris.org
On 03/15/10 08:20, tester wrote:>> fbt::door_call:entry >> /curpsinfo->pr_dmodel == PR_MODEL_LP64/ >> { >> printf("entry args are %lx and %lx \n", arg0, >> , *(uint64_t *)copyin(arg1, 8)); >> } >> >> Nico > > Thanks Nico. Since arg1 is a pointer to a struct in userland, can I use > ptr = *(uint32_t *)copyin(arg1, 4); > tracemem(ptr,10); > to dump the structure. I tried this and getting invalid address (0xfb07bc75) in action #4.If arg1 is a userland pointer to a structure, then your copyin just copied in the first four bytes of that structure. And your tracemem is trying to use those first four bytes as though they were a kernel pointer. That''s not going to work. You might want this: this->ptr = copyin(arg1, 10); tracemem(this->ptr, 10); -- James Carlson 42.703N 71.076W <carlsonj at workingcode.com>
I am going to try this self->r = (struct door_arg *)copyin(arg1,sizeof(struct door_arg)); -- This message posted from opensolaris.org
I am getting a 64bit address for char pointer for a 32 bit process. I don''t know if I am getting the casting correct. #!/usr/sbin/dtrace -qs typedef struct door_arg { char *data_ptr; /* Argument/result buf ptr*/ size_t data_size; /* Argument/result buf size */ door_desc_t *desc_ptr; /* Argument/result descriptors */ uint_t desc_num; /* Argument/result num desc */ char *rbuf; /* Result buffer */ size_t rsize; /* Result buffer size */ } door_arg_t; fbt::door_call:entry /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ { self->r = (struct door_arg *)copyin(arg1,sizeof(struct door_arg)); printf("32bit char data pointer is %a and size %x\n",self->r->data_ptr, self->r->data_size); tracemem(self->r,100); } I am getting a 64 bit address here, am I missing some casting here? 32bit char data pointer is 0xff1e0000000000b0 and size 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 0: ff 1e 00 00 00 00 00 b0 00 00 00 00 00 00 00 00 ................ 10: ff 1e 00 00 00 00 40 00 ff 33 37 c0 00 00 00 07 ...... at ..37..... 20: ff 33 37 c8 00 00 00 b0 00 00 40 00 ff 1e 00 90 .37....... at ..... 30: 00 00 00 1c ff ff ff ff 7d 60 00 00 00 00 00 00 ........}`...... 40: 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 ..d............. 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 60: 00 00 00 00 .... Thanks -- This message posted from opensolaris.org
Try door_arg32_t instead of "struct door_arg". tester wrote:> I am getting a 64bit address for char pointer for a 32 bit process. I don''t know if I am getting the casting correct. > > #!/usr/sbin/dtrace -qs > > typedef struct door_arg { > char *data_ptr; /* Argument/result buf ptr*/ > size_t data_size; /* Argument/result buf size */ > door_desc_t *desc_ptr; /* Argument/result descriptors */ > uint_t desc_num; /* Argument/result num desc */ > char *rbuf; /* Result buffer */ > size_t rsize; /* Result buffer size */ > } door_arg_t; > > > > fbt::door_call:entry > /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ > { > self->r = (struct door_arg *)copyin(arg1,sizeof(struct door_arg)); > printf("32bit char data pointer is %a and size %x\n",self->r->data_ptr, self->r->data_size); > tracemem(self->r,100); > } > > I am getting a 64 bit address here, am I missing some casting here? > > 32bit char data pointer is 0xff1e0000000000b0 and size 0 > > 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef > 0: ff 1e 00 00 00 00 00 b0 00 00 00 00 00 00 00 00 ................ > 10: ff 1e 00 00 00 00 40 00 ff 33 37 c0 00 00 00 07 ...... at ..37..... > 20: ff 33 37 c8 00 00 00 b0 00 00 40 00 ff 1e 00 90 .37....... at ..... > 30: 00 00 00 1c ff ff ff ff 7d 60 00 00 00 00 00 00 ........}`...... > 40: 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 ..d............. > 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ > 60: 00 00 00 00 .... > > Thanks
On Mon, Mar 15, 2010 at 12:20:35PM -0700, tester wrote:> #!/usr/sbin/dtrace -qs > > typedef struct door_arg { > char *data_ptr; /* Argument/result buf ptr*/ > size_t data_size; /* Argument/result buf size */ > door_desc_t *desc_ptr; /* Argument/result descriptors */ > uint_t desc_num; /* Argument/result num desc */ > char *rbuf; /* Result buffer */ > size_t rsize; /* Result buffer size */ > } door_arg_t;These declarations will use the sizes of those types as these declarations are to be used in kernel-land. That means that data_ptr is a 64-bit field in kernel-land and in DTrace context. That disagrees with 32-bit user-land. Use door_arg32_t as Michael Bergknoff suggests. You''ll see that door_arg32_t uses caddr32_t instead of "<base type> *": typedef struct door_arg32 { caddr32_t data_ptr; /* Argument/result data */ size32_t data_size; /* Argument/result data size */ caddr32_t desc_ptr; /* Argument/result descriptors */ uint32_t desc_num; /* Argument/result num descriptors */ caddr32_t rbuf; /* Result area */ size32_t rsize; /* Result size */ } door_arg32_t; caddr32_t is (in 64-bit land) an unsigned integer type rather than a pointer type, and its size matches that of 32-bit pointer types. Nico --
Thank you Michael and Nico. I will post my results after the test. Much appreciated. -- This message posted from opensolaris.org
It is somewhat complex for someone like me with limited C programming to unearth the actual data(args and result) from the door call API. I beleive it has custom NSS headers packed along with actual data. Tracemem for most part is not that meaningful. If anyone has already done this, please share it. I am startting to look at other places where I can get this data in a strcutured form. I started looking at pid$target:libc:_nsc_try1door:entry this is where I am now: BEGIN { last = timestamp; } typedef unsigned long long int door_ptr_t; /* Handle 64 bit pointers */ typedef unsigned long long int door_id_t; /* Unique door identifier */ typedef unsigned int door_attr_t; /* Door attributes */ typedef struct door_info { pid_t di_target; /* Server process */ door_ptr_t di_proc; /* Server procedure */ door_ptr_t di_data; /* Data cookie */ door_attr_t di_attributes; /* Attributes associated with door */ door_id_t di_uniquifier; /* Unique number */ int di_resv[4]; /* Future use */ } door_info_t; typedef struct _nsc_door_t { int doorfd; mutex_t door_lock; door_info_t doori; } nsc_door_t; pid$target:libc:_nsc_try1door:entry /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ { /* args nsc_door_t *dp, void **dptr, size_t *ndata, size_t *adata, int *pdesc */ trace(timestamp - last); last = timestamp; self->dp = (struct _nsc_door_t *)copyin(arg0,sizeof(struct _nsc_door_t)); printf("doorfd %d di_proc %x",self->dp->doorfd,self->dp->doori.di_proc); tracemem(self->dp,100); } pid$target:libc:_nsc_try1door:return /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ { trace(timestamp - last); last = timestamp; } I get a invalid alignement. dtrace: error on enabled probe ID 2 (ID 80106: pid13913:libc.so.1:_nsc_try1door:entry): invalid alignment (0x302124160ac) in action #5 at DIF offset 20 I think struct definitions above many not be correct. Now, my basic question is, is there a set of instructions that I can follow to convert structure definitions to 32bit and/or 64 bit. Nico, helped me last time, how can I do this myself? Is it out of my league? (meaning basic/medium C programming experience) Is there anything that I can read up further on userland data tracing 32/64 bit programs/libraries? Thank you for your help. -- This message posted from opensolaris.org
On Tue, Mar 16, 2010 at 08:55:04AM -0700, tester wrote:> It is somewhat complex for someone like me with limited C programming > to unearth the actual data(args and result) from the door call API. I > beleive it has custom NSS headers packed along with actual data. > Tracemem for most part is not that meaningful. If anyone has already > done this, please share it.Ok, so you''re trying to observe name service calls. (There are other doors in use in Solaris besides the one for nscd.) What you need is a way to parse the door call argument data buffer and the door return rbuf too. I don''t see where that''s documented in the source (the protocol itself is private, but it should be documented in source), so I''m cc''ing two people who can help you with that. (The relevant source code is in $SRC/lib/libc/port/gen/nss_common.c.)> I am startting to look at other places where I can get this data in a > strcutured form. I started looking at > > pid$target:libc:_nsc_try1door:entryThat function receives the call data/results already packed. Also, on the client side there are many more processes to trace than on the server side. I recommend tracing the server-side if at all possible. Besides, if you''re tracing the server you don''t need to worry about 32-bit vs. 64-bit -- the server in this is always 32-bit because nscd is only built in 32-bit. Nico --
On Tue, Mar 16, 2010 at 11:11:24AM -0500, Nicolas Williams wrote:> What you need is a way to parse the door call argument data buffer and > the door return rbuf too. I don''t see where that''s documented in the > source (the protocol itself is private, but it should be documented in > source), so I''m cc''ing two people who can help you with that. (The > relevant source code is in $SRC/lib/libc/port/gen/nss_common.c.)Well, I can read the code :) The arg data starts with a nss_pheader_t. In the case of a search (phdr->nsc_callnumber == NSCD_SEARCH) the header will be followed by the db name and key. The header includes offsets to those data, since the header is variable size. For searches take a look at nss_upack_key2arg() in $SRC/lib/libc/port/gen/nss_dbdefs.c. The result is handled similarly, with the data returned in "files" format. Nico --
You may want to use/start with the dtrace script located here: http://hub.opensolaris.org/bin/view/Project+sparks/dtrace It can trace all nscd calls & returns, and provide appropriate information along the way. It was originally written as part of the sparks project. Doug. On 03/16/10 10:55 AM, tester wrote:> It is somewhat complex for someone like me with limited C programming to unearth the actual data(args and result) from the door call API. I beleive it has custom NSS headers packed along with actual data. Tracemem for most part is not that meaningful. If anyone has already done this, please share it. > > I am startting to look at other places where I can get this data in a strcutured form. I started looking at > > pid$target:libc:_nsc_try1door:entry > > this is where I am now: > > > BEGIN { last = timestamp; } > > typedef unsigned long long int door_ptr_t; /* Handle 64 bit pointers */ > typedef unsigned long long int door_id_t; /* Unique door identifier */ > typedef unsigned int door_attr_t; /* Door attributes */ > > typedef struct door_info { > pid_t di_target; /* Server process */ > door_ptr_t di_proc; /* Server procedure */ > door_ptr_t di_data; /* Data cookie */ > door_attr_t di_attributes; /* Attributes associated with door */ > door_id_t di_uniquifier; /* Unique number */ > int di_resv[4]; /* Future use */ > } door_info_t; > > typedef struct _nsc_door_t { > int doorfd; > mutex_t door_lock; > door_info_t doori; > } nsc_door_t; > > > pid$target:libc:_nsc_try1door:entry > /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ > { > /* args nsc_door_t *dp, void **dptr, size_t *ndata, size_t *adata, int *pdesc */ > > trace(timestamp - last); > last = timestamp; > self->dp = (struct _nsc_door_t *)copyin(arg0,sizeof(struct _nsc_door_t)); > > printf("doorfd %d di_proc %x",self->dp->doorfd,self->dp->doori.di_proc); > > tracemem(self->dp,100); > } > > pid$target:libc:_nsc_try1door:return > /curpsinfo->pr_dmodel == PR_MODEL_ILP32/ > { > trace(timestamp - last); > last = timestamp; > } > > I get a invalid alignement. > > dtrace: error on enabled probe ID 2 (ID 80106: pid13913:libc.so.1:_nsc_try1door:entry): invalid alignment (0x302124160ac) in action #5 at DIF offset 20 > > I think struct definitions above many not be correct. Now, my basic question is, is there a set of instructions that I can follow to convert structure definitions to 32bit and/or 64 bit. Nico, helped me last time, how can I do this myself? Is it out of my league? (meaning basic/medium C programming experience) > > Is there anything that I can read up further on userland data tracing 32/64 bit programs/libraries? > > Thank you for your help.
Thanks Doug and Nico. I''ll test and post the results. -- This message posted from opensolaris.org
Unfortunately my tests are on S10 update 6. Can I use nsc_lookup in place of switcher? I realize the args are different. If it''s proprietary I can understand. Thanks -- This message posted from opensolaris.org
tester wrote:> I am going to try this > self->r = (struct door_arg *)copyin(arg1,sizeof(struct door_arg)); >FYI, copyin() essentially calls alloca() for the buffer it returns, and that buffer will evaporate once the probe exits (ie only safe to assign to ''this'') I think you can work around by declaring a ''self struct door_arg foo'' and passing foo''s address to copyinto() as the destination. Regards, Ryan