Suppose I have struct foo { int len; char *buf; }; so "struct foo" points to a bunch of bytes, possibly with embedded null bytes (''\0''). Is it possible for me to store these things, and later compare them? For a non-working example: char wad_of_bytes[1234]; /* 1234 is an arbitrary maximum */ fbt::blah:entry { bcopy(args[0]->buf, wad_of_bytes, args[0]->len); } fbt::squonk:entry /bcmp(args[0]->buf, wad_of_bytes, args[0]->len) == 0/ { printf("got it!"); } I know (or I think I know) there is no bcmp(), and I know that bcopy() won''t copy into non-scratch memory. This was just for illustration. Any ideas on how to do this sort of thing? Thanks! - Sam
> Suppose I have > > struct foo { > int len; > char *buf; > }; > > so "struct foo" points to a bunch of bytes, possibly with embedded > null bytes (''\0''). > > Is it possible for me to store these things, and later compare them? > > For a non-working example: > > char wad_of_bytes[1234]; /* 1234 is an arbitrary maximum */ > > fbt::blah:entry > { > bcopy(args[0]->buf, wad_of_bytes, args[0]->len); > } > > fbt::squonk:entry > /bcmp(args[0]->buf, wad_of_bytes, args[0]->len) == 0/ > { > printf("got it!"); > } > > I know (or I think I know) there is no bcmp(), and I know that bcopy() > won''t copy into non-scratch memory. This was just for illustration. > > Any ideas on how to do this sort of thing?The D string type is effectively similar to the C code: struct { char data[N]; } string; So you can declare a variable of type string, and then assign char *''s to it and this will result in a by-value copy as opposed to by-reference, and your string data will be persisted in your string variable''s storage, e.g. fbt:ufs:ufs_lookup:entry { self->s = stringof(args[1]); } fbt:ufs:ufs_lookup:return { trace(self->s); } -Mike -- Mike Shapiro, Solaris Kernel Development. blogs.sun.com/mws/
Mike, In your example:> fbt:ufs:ufs_lookup:entry > { > self->s = stringof(args[1]); > } > > fbt:ufs:ufs_lookup:return > { > trace(self->s); > }Out of curiosity, if args[1] contained null bytes interspersed with valid characters, will the null bytes also be included in self->s? or will stringof see them as a delimiter and stop at the first one it sees? thanks, Noel :-) ************************************************************************ ** "Question all the answers" On Aug 24, 2005, at 10:44 AM, Michael Shapiro wrote:>> Suppose I have >> >> struct foo { >> int len; >> char *buf; >> }; >> >> so "struct foo" points to a bunch of bytes, possibly with embedded >> null bytes (''\0''). >> >> Is it possible for me to store these things, and later compare them? >> >> For a non-working example: >> >> char wad_of_bytes[1234]; /* 1234 is an arbitrary maximum */ >> >> fbt::blah:entry >> { >> bcopy(args[0]->buf, wad_of_bytes, args[0]->len); >> } >> >> fbt::squonk:entry >> /bcmp(args[0]->buf, wad_of_bytes, args[0]->len) == 0/ >> { >> printf("got it!"); >> } >> >> I know (or I think I know) there is no bcmp(), and I know that bcopy() >> won''t copy into non-scratch memory. This was just for illustration. >> >> Any ideas on how to do this sort of thing? > > The D string type is effectively similar to the C code: > > struct { > char data[N]; > } string; > > So you can declare a variable of type string, and then assign char *''s > to it and this will result in a by-value copy as opposed to > by-reference, > and your string data will be persisted in your string variable''s > storage, e.g. > > fbt:ufs:ufs_lookup:entry > { > self->s = stringof(args[1]); > } > > fbt:ufs:ufs_lookup:return > { > trace(self->s); > } > > -Mike > > -- > Mike Shapiro, Solaris Kernel Development. blogs.sun.com/mws/ > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org
On Wed, 24 Aug 2005, Michael Shapiro wrote:> The D string type is effectively similar to the C code: > > struct { > char data[N]; > } string; > > So you can declare a variable of type string, and then assign char *''s > to it and this will result in a by-value copy as opposed to by-reference, > and your string data will be persisted in your string variable''s storage, e.g.Doesn''t the OP''s requirement to allow embedded NULs in their byte array preclude the use of strings? Wouldn''t stringof() stop at the first NUL? I''m relatively new to DTrace, so it is quite possible that I''m complete wrong! -- Rich Teer, SCNA, SCSA, OpenSolaris CAB member President, Rite Online Inc. Voice: +1 (250) 979-1638 URL: http://www.rite-group.com/rich
> Mike, > In your example: > > fbt:ufs:ufs_lookup:entry > > { > > self->s = stringof(args[1]); > > } > > > > fbt:ufs:ufs_lookup:return > > { > > trace(self->s); > > } > > Out of curiosity, if args[1] contained null bytes interspersed with > valid characters, will the null bytes also be included in self->s? or > will stringof see them as a delimiter and stop at the first one it > sees? > > thanks, > Noel :-)Stops at the \0. -Mike -- Mike Shapiro, Solaris Kernel Development. blogs.sun.com/mws/
Michael Shapiro <mws at eng.sun.com> writes:>> Mike, >> In your example: >> > fbt:ufs:ufs_lookup:entry >> > { >> > self->s = stringof(args[1]); >> > } >> > >> > fbt:ufs:ufs_lookup:return >> > { >> > trace(self->s); >> > } >> >> Out of curiosity, if args[1] contained null bytes interspersed with >> valid characters, will the null bytes also be included in self->s? or >> will stringof see them as a delimiter and stop at the first one it >> sees? >> >> thanks, >> Noel :-) > > Stops at the \0.That won''t work for me -- NFS filehandles have embedded \0''s. Okay if I file an RFE? One idea I had was if stringof() could take an optional length. If that length were passed in, the resulting string could include \0 characters. I like this idea because I like the string data type -- I''d rather use "==" than some bcmp()-type thing. Of course, maybe there are reasons why stringof() would be a bad idea; that''d be fine, too. - Sam
On Aug 24, 2005, at 10:09 PM, Sam Falkner wrote:> Michael Shapiro <mws at eng.sun.com> writes: > > >>> Mike, >>> In your example: >>> >>>> fbt:ufs:ufs_lookup:entry >>>> { >>>> self->s = stringof(args[1]); >>>> } >>>> >>>> fbt:ufs:ufs_lookup:return >>>> { >>>> trace(self->s); >>>> } >>>> >>> >>> Out of curiosity, if args[1] contained null bytes interspersed with >>> valid characters, will the null bytes also be included in self- >>> >s? or >>> will stringof see them as a delimiter and stop at the first one it >>> sees? >>> >>> thanks, >>> Noel :-) >>> >> >> Stops at the \0. >> > > That won''t work for me -- NFS filehandles have embedded \0''s. > > Okay if I file an RFE? > > One idea I had was if stringof() could take an optional length. If > that length were passed in, the resulting string could include \0 > characters. I like this idea because I like the string data type -- > I''d rather use "==" than some bcmp()-type thing. > > Of course, maybe there are reasons why stringof() would be a bad idea; > that''d be fine, too. >as an aside.. it''s "almost" like a netbuf struct netbuf { unsigned int maxlen; unsigned int len; char *buf; }; it would seem to me that we would not want to confuse ''string'' with a collection of contiguous bytes. perhaps something like memof(ptr, len) ? -- Robert
On Wed, 24 Aug 2005, Robert Gordon wrote:> > On Aug 24, 2005, at 10:09 PM, Sam Falkner wrote: > > > Michael Shapiro <mws at eng.sun.com> writes: > > > > > >>> Mike, > >>> In your example: > >>> > >>>> fbt:ufs:ufs_lookup:entry > >>>> { > >>>> self->s = stringof(args[1]); > >>>> } > >>>> > >>>> fbt:ufs:ufs_lookup:return > >>>> { > >>>> trace(self->s); > >>>> } > >>>> > >>> > >>> Out of curiosity, if args[1] contained null bytes interspersed with > >>> valid characters, will the null bytes also be included in self- > >>> >s? or > >>> will stringof see them as a delimiter and stop at the first one it > >>> sees? > >>> > >>> thanks, > >>> Noel :-) > >>> > >> > >> Stops at the \0. > >> > > > > That won''t work for me -- NFS filehandles have embedded \0''s. > > > > Okay if I file an RFE? > > > > One idea I had was if stringof() could take an optional length. If > > that length were passed in, the resulting string could include \0 > > characters. I like this idea because I like the string data type -- > > I''d rather use "==" than some bcmp()-type thing. > > > > Of course, maybe there are reasons why stringof() would be a bad idea; > > that''d be fine, too. > > > > as an aside.. it''s "almost" like a netbuf > > struct netbuf { > unsigned int maxlen; > unsigned int len; > char *buf; > };Which is only slightly different that a Bstring: --- from bstrlib.txt --- A bstring is basically a header which wraps a pointer to a char buffer. Lets start with the declaration of a struct tagbstring: struct tagbstring { int mlen; int slen; unsigned char * data; }; --- end of quote ----- Bstrings can contain embedded ''\0'' chars. Before you design/build anything, take a look at: http://bstring.sourceforge.net/> it would seem to me that we would not want to confuse ''string'' with > a collection of contiguous bytes. perhaps something like memof(ptr, > len) ?Regards, Al Hopper Logical Approach Inc, Plano, TX. al at logical-approach.com Voice: 972.379.2133 Fax: 972.379.2134 OpenSolaris Community Advisory Board (CAB) Member - Apr 2005
> > > > Stops at the \0. > > That won''t work for me -- NFS filehandles have embedded \0''s. > > Okay if I file an RFE? > > One idea I had was if stringof() could take an optional length. If > that length were passed in, the resulting string could include \0 > characters. I like this idea because I like the string data type -- > I''d rather use "==" than some bcmp()-type thing. > > Of course, maybe there are reasons why stringof() would be a bad idea; > that''d be fine, too. > > - Sam >Sorry, in your original mail you just had fake functions, so I didn''t realize you were talking about file handles. You can use bcopy() and alloca() to deal with this today, although we definitely can make it friendlier. Here is some example code you can play with since I''m not sure exactly what you''re trying to do ... in my example I copy a filehandle to a clause-local variable, trace the raw filehandle bytes, and also create an associative array of filehandles where the value of each element is its size: struct fh { char data[256]; }; self size_t f[struct fh]; this struct fh *fhp; fbt:nfssrv:nfs4_fhtovp:entry /args[0]->nfs_fh4_len > 256 / { printf("ERROR: len %u exceeds data size\n", args[0]->nfs_fh4_len); } fbt:nfssrv:nfs4_fhtovp:entry /args[0]->nfs_fh4_len <= 256 / { this->fhp = alloca(sizeof (struct fh)); bcopy(args[0]->nfs_fh4_val, this->fhp, args[0]->nfs_fh4_len); self->f[*this->fhp] = args[0]->nfs_fh4_len; tracemem(this->fhp, 256); } $ dtrace -s a.d dtrace: script ''a.d'' matched 2 probes CPU ID FUNCTION:NAME 0 5876 nfs4_fhtovp:entry 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 0: 82 00 78 00 02 00 00 00 0a 00 00 00 02 00 00 00 ..x............. 10: 99 c3 12 37 0a 00 00 00 02 00 00 00 99 c3 12 37 ...7...........7 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ... Hope this helps. If you get something working or get stuck e-mail back what you have so we can think about how to make it easier. -Mike -- Mike Shapiro, Solaris Kernel Development. blogs.sun.com/mws/
>>> >>> Stops at the \0. >> >> That won''t work for me -- NFS filehandles have embedded \0''s. >> >> Okay if I file an RFE? >> >> One idea I had was if stringof() could take an optional length. If >> that length were passed in, the resulting string could include \0 >> characters. I like this idea because I like the string data type -- >> I''d rather use "==" than some bcmp()-type thing. >> >> Of course, maybe there are reasons why stringof() would be a bad idea; >> that''d be fine, too. >> >> - Sam >> > > Sorry, in your original mail you just had fake functions, so I didn''t > realize > you were talking about file handles. You can use bcopy() and alloca() > to > deal with this today, although we definitely can make it friendlier. > Here is > some example code you can play with since I''m not sure exactly what > you''re > trying to do ... in my example I copy a filehandle to a clause-local > variable, > trace the raw filehandle bytes, and also create an associative array of > filehandles where the value of each element is its size: > > struct fh { > char data[256]; > }; > > self size_t f[struct fh]; > this struct fh *fhp; > > fbt:nfssrv:nfs4_fhtovp:entry > /args[0]->nfs_fh4_len > 256 / > { > printf("ERROR: len %u exceeds data size\n", args[0]->nfs_fh4_len); > } > > fbt:nfssrv:nfs4_fhtovp:entry > /args[0]->nfs_fh4_len <= 256 / > { > this->fhp = alloca(sizeof (struct fh)); > bcopy(args[0]->nfs_fh4_val, this->fhp, args[0]->nfs_fh4_len); > self->f[*this->fhp] = args[0]->nfs_fh4_len; > tracemem(this->fhp, 256); > } > > $ dtrace -s a.d > dtrace: script ''a.d'' matched 2 probes > CPU ID FUNCTION:NAME > 0 5876 nfs4_fhtovp:entry > 0 1 2 3 4 5 6 7 8 9 a b c d e f > 0123456789abcdef > 0: 82 00 78 00 02 00 00 00 0a 00 00 00 02 00 00 00 > ..x............. > 10: 99 c3 12 37 0a 00 00 00 02 00 00 00 99 c3 12 37 > ...7...........7 > 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ................ > ... > > Hope this helps. If you get something working or get stuck e-mail back > what you have so we can think about how to make it easier. > > -Mike > > -- > Mike Shapiro, Solaris Kernel Development. blogs.sun.com/mws/I''d like to use the actual contents of the filehandle in a predicate to a probe, much like you can use ''stringof'', as in (assume arg0 is an ASCII string): sdt:::randomprobe /records[stringof(arg0)].x == OP/ The above works if this is a ASCII string, but not if it has embedded NULLs (like a nfs filehandle). So what would be the proper way of doing the above "conversion" with nfs filehandles? So if this is where i set the filehandle contents: #define OP 5 struct fh { char data[40]; }; struct opinfo { int x; }; this struct fh *fhp; struct opinfo records[struct fh]; sdt:::set_value_probe { this->fhp = alloca(sizeof (struct fh)); bcopy(args[0]->nfs_fh4_val, this->fhp, args[0]->nfs_fh4_len); records[*this->fhp].x = OP; } Then in the "done_probe", arg0 is the filehandle, it seems we need something like a ''get_byte_contents()'': sdt:::done_probe /records[get_byte_contents(arg0]).x == OP/ { do_great_stuff } thanks, Noel