How to print string in C++: e.g. string Fun(string a, int b) Then I''ll try to printf the return value of this Fun(). *****:return { printf("ret = %s", stringof(arg0)); ... } But DTrace told that this use is uncorrect. Then how to get the return string value?? This message posted from opensolaris.org
This method is also failed: printf("ret = %s", stringof(copyinstr(arg0))); This message posted from opensolaris.org
Chip Bennett
2006-Nov-28 19:59 UTC
[dtrace-discuss] Re: DTrace: How to print string in C++
Hi Eric, As you may already know, you got the error on your first attempt because D programs run in the kernel, and the user-land pointer wasn''t in the kernel''s address space. The copyinstr function takes care of that, and it returns a type "string" so you shouldn''t need "stringof", however it shouldn''t hurt anything. What error are you getting with this attempt? Can we see your whole D program? Thanks, Chip eric wang wrote:> This method is also failed: > printf("ret = %s", stringof(copyinstr(arg0))); > > > This message posted from opensolaris.org > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org >
Trond Norbye
2006-Nov-28 20:54 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Hi When you say string in C++ do you mean std::string? The "string" you get in DTrace is more like the char* kinds of strings and not a C++ string object. Please correct me if I''m wrong... Trond This message posted from opensolaris.org
Hi Eric,>How to print string in C++: >e.g. string Fun(string a, int b) > >Then I''ll try to printf the return value of this Fun(). > >*****:return >{ >printf("ret = %s", stringof(arg0)); >... >} >First, note that the return value when using the pid provider is stored in arg1 and not arg0. Second, if you are using C++ string objects then the actual character array is most likely embedded in the object. You''re probably not going to be able to use copyinstr() to access the string itself without knowledge if how the object is laid out. Cheers. Jon.
eric wang
2006-Nov-29 09:45 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Please refer to this: pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return /self->trace/ { self->trace = 0; printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = %d\n\n", copyinstr(&arg0), arg1, arg2, arg3); } There is still this problem! This message posted from opensolaris.org
I used the std::string, and how to get the return value? This message posted from opensolaris.org
eric wang
2006-Nov-29 09:48 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Hi, But I used the std::string. This message posted from opensolaris.org
Jonathan Haslam
2006-Nov-29 15:22 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
>Please refer to this: >pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return >/self->trace/ >{ >self->trace = 0; > >printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = %d\n\n", copyinstr(&arg0), arg1, arg2, arg3); > >} > >There is still this problem! >The problem here is that the std::string object embeds a pointer to the character array. What you actually need to do is to copyin() the pointer and then use that in the copyinstr(). Just to work it through, here''s a simple piece of code using string objects which I think is representative of what you are doing(I''m no C++ man so don''t laugh at the code...): # cat t.cc #include <iostream> #include <string> using namespace std; string Fun(string foo) { return(foo); } int main(int argc, char *argv[]) { string namestr = "Jon"; Fun(namestr); } Let''s compile it and look at the layout of the string object: # CC -g -o t t.cc # dbx ./t For information about new features see `help changes'' To remove this message, put `dbxenv suppress_startup_message 7.4'' in your .dbxrc Reading t Reading ld.so.1 Reading libCstd.so.1 Reading libCrun.so.1 Reading libm.so.2 Reading libc.so.1 (dbx) stop in main (2) stop in main (dbx) run Running: t (process id 101522) stopped in main at line 15 in file "t.cc" 15 string namestr = "Jon"; (dbx) step stopped in main at line 17 in file "t.cc" 17 Fun(namestr); (dbx) print +r namestr namestr = { __data_ = { __data_ = 0x8080864 "Jon" } npos = 0 __nullref = 4 } So, we need to copyin() the __data_ pointer and we can then feed that into a copyinstr(). Here''s the D script to do that: #!/usr/sbin/dtrace -s #pragma D option quiet pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:entry { this->str = *(uintptr_t *)copyin(arg1, sizeof(void *)); printf("string = %s", copyinstr(this->str)); } Executing this we get what we expect: # dtrace -32 -s ./t.d -c ./t string = Jon (Note that use of -32 to select the correct data model here). I know this isn''t that pretty. Having to copyin() the data like that is pretty ugly but that''s the way it is at the minute. Also, the lack of type information in user-land is something that could do with addressing (though that''s not a small piece of work). Hope this helps. Cheers. Jon.
Chip Bennett
2006-Nov-29 18:31 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
The instruction from Jon on accessing a C++ string is good stuff. It got me to thinking that it wouldn''t be a bad idea to add a section to the DTrace FAQ (http://www.genunix.org/wiki/index.php/DTrace_FAQ) that has methods for reading variables and data structures in various languages. C++ strings would be a good first addition. I started to add some new stuff to the FAQ a little while back myself, but lost interest quickly when I realized I didn''t know how to use the WIKI editing tool. (I know: that''s pretty weak.) Maybe some day I''ll have time to figure it out. However, I don''t feel too bad, as it doesn''t look like much has been added since Brendan created it, or am I wrong? Thanks, Chip
Robin Fu
2006-Nov-30 06:37 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Really helpful,thanks,jonathan. Two questions: 1)I noticed you access arg1 instead of arg0 in your dtrace script. And my test proved that arg1 is actually the string parameter. But it is weird,as the first parameter should always passed in by arg0, and in this case string is the only parameter of Fun(). So why you access it by arg1? 2)Eric''s original question is that he would like to get the return value of that question.To finish that,I wrote a simple D-script that is as follows: ... pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:return { printf("arg0=%p, arg1=%p, arg2=%p", arg0,arg1,arg2); this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); printf("string=%s", copyinstr(this->str)); } ... But it showed that the value of arg1 in Fun:return probe is 2 !! Not a valid address. Is there any mistakes here? Thanks, Zhijun Jonathan Haslam wrote:> >> Please refer to this: >> pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return >> >> /self->trace/ >> { >> self->trace = 0; >> >> printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = %d\n\n", >> copyinstr(&arg0), arg1, arg2, arg3); >> >> } >> >> There is still this problem! >> > The problem here is that the std::string object embeds a pointer > to the character array. What you actually need to do is to copyin() > the pointer and then use that in the copyinstr(). > > Just to work it through, here''s a simple piece of code using > string objects which I think is representative of what you are > doing(I''m no C++ man so don''t laugh at the code...): > > # cat t.cc > #include <iostream> > #include <string> > > using namespace std; > > string > Fun(string foo) > { > return(foo); > } > > int > main(int argc, char *argv[]) > { > string namestr = "Jon"; > > Fun(namestr); > } > > > Let''s compile it and look at the layout of the string object: > > # CC -g -o t t.cc # dbx ./t > For information about new features see `help changes'' > To remove this message, put `dbxenv suppress_startup_message 7.4'' in > your .dbxrc > Reading t > Reading ld.so.1 > Reading libCstd.so.1 > Reading libCrun.so.1 > Reading libm.so.2 > Reading libc.so.1 > (dbx) stop in > main (2) stop > in main > (dbx) run Running: t > (process id 101522) > stopped in main at line 15 in file "t.cc" > 15 string namestr = "Jon"; > (dbx) step > stopped in main at line 17 in file "t.cc" > 17 Fun(namestr); > (dbx) print +r namestr > namestr = { > __data_ = { > __data_ = 0x8080864 "Jon" > } > npos = 0 > __nullref = 4 > } > > So, we need to copyin() the __data_ pointer and we can then > feed that into a copyinstr(). Here''s the D script to do that: > > #!/usr/sbin/dtrace -s > > #pragma D option quiet > > pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:entry > > { > this->str = *(uintptr_t *)copyin(arg1, sizeof(void *)); > printf("string = %s", copyinstr(this->str)); > } > > Executing this we get what we expect: > > # dtrace -32 -s ./t.d -c ./t > string = Jon > > (Note that use of -32 to select the correct data model here). > > I know this isn''t that pretty. Having to copyin() the data like > that is pretty ugly but that''s the way it is at the minute. Also, > the lack of type information in user-land is something that could > do with addressing (though that''s not a small piece of work). > > Hope this helps. > > Cheers. > > Jon. > > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org
Jonathan Haslam
2006-Nov-30 11:23 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
> Two questions: > 1)I noticed you access arg1 instead of arg0 in your dtrace script. > And my test proved that arg1 is actually the string parameter. > But it is weird,as the first parameter should always passed in by arg0, > and in this case string is the only parameter of Fun(). > So why you access it by arg1?We are using a *return* probe in this case and they have the following arguments: arg0 - offset in the functon of the return instruction arg1 - The actual return value of the function Check out chapter 30 in the DTrace user guide for more information.> 2)Eric''s original question is that he would like to get the return > value of that question.To finish that,I wrote a simple D-script that > is as follows: > ... > pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:return > > { > printf("arg0=%p, arg1=%p, arg2=%p", arg0,arg1,arg2); > this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); > printf("string=%s", copyinstr(this->str)); > } > ... > But it showed that the value of arg1 in Fun:return probe is 2 !! Not a > valid address. > Is there any mistakes here?I don''t see that when I run the above - arg1 contains a pointer to the string object. Note that arg2 makes no sense when used in a pid provider return probe. Cheers. Jon.> > Thanks, > Zhijun > > Jonathan Haslam wrote: > >> >>> Please refer to this: >>> pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return >>> >>> /self->trace/ >>> { >>> self->trace = 0; >>> >>> printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = %d\n\n", >>> copyinstr(&arg0), arg1, arg2, arg3); >>> >>> } >>> >>> There is still this problem! >>> >> The problem here is that the std::string object embeds a pointer >> to the character array. What you actually need to do is to copyin() >> the pointer and then use that in the copyinstr(). >> >> Just to work it through, here''s a simple piece of code using >> string objects which I think is representative of what you are >> doing(I''m no C++ man so don''t laugh at the code...): >> >> # cat t.cc >> #include <iostream> >> #include <string> >> >> using namespace std; >> >> string >> Fun(string foo) >> { >> return(foo); >> } >> >> int >> main(int argc, char *argv[]) >> { >> string namestr = "Jon"; >> >> Fun(namestr); >> } >> >> >> Let''s compile it and look at the layout of the string object: >> >> # CC -g -o t t.cc # dbx ./t >> For information about new features see `help changes'' >> To remove this message, put `dbxenv suppress_startup_message 7.4'' in >> your .dbxrc >> Reading t >> Reading ld.so.1 >> Reading libCstd.so.1 >> Reading libCrun.so.1 >> Reading libm.so.2 >> Reading libc.so.1 >> (dbx) stop in >> main (2) >> stop in main >> (dbx) run Running: t >> (process id 101522) >> stopped in main at line 15 in file "t.cc" >> 15 string namestr = "Jon"; >> (dbx) step >> stopped in main at line 17 in file "t.cc" >> 17 Fun(namestr); >> (dbx) print +r namestr >> namestr = { >> __data_ = { >> __data_ = 0x8080864 "Jon" >> } >> npos = 0 >> __nullref = 4 >> } >> >> So, we need to copyin() the __data_ pointer and we can then >> feed that into a copyinstr(). Here''s the D script to do that: >> >> #!/usr/sbin/dtrace -s >> >> #pragma D option quiet >> >> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:entry >> >> { >> this->str = *(uintptr_t *)copyin(arg1, sizeof(void *)); >> printf("string = %s", copyinstr(this->str)); >> } >> >> Executing this we get what we expect: >> >> # dtrace -32 -s ./t.d -c ./t >> string = Jon >> >> (Note that use of -32 to select the correct data model here). >> >> I know this isn''t that pretty. Having to copyin() the data like >> that is pretty ugly but that''s the way it is at the minute. Also, >> the lack of type information in user-land is something that could >> do with addressing (though that''s not a small piece of work). >> >> Hope this helps. >> >> Cheers. >> >> Jon. >> >> _______________________________________________ >> dtrace-discuss mailing list >> dtrace-discuss at opensolaris.org > > > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org
Robin Fu
2006-Nov-30 11:33 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Yes, Eric''s intent was to use a return probe. But in your script you used a *entry* probe,and accessed arg1 instead of arg0. That is where I am puzzled. Thanks, Zhijun Jonathan Haslam wrote:> >> Two questions: >> 1)I noticed you access arg1 instead of arg0 in your dtrace script. >> And my test proved that arg1 is actually the string parameter. >> But it is weird,as the first parameter should always passed in by arg0, >> and in this case string is the only parameter of Fun(). >> So why you access it by arg1? > > We are using a *return* probe in this case and they have the > following arguments: > > arg0 - offset in the functon of the return instruction > arg1 - The actual return value of the function > > Check out chapter 30 in the DTrace user guide for more > information. > >> 2)Eric''s original question is that he would like to get the return >> value of that question.To finish that,I wrote a simple D-script that >> is as follows: >> ... >> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:return >> >> { >> printf("arg0=%p, arg1=%p, arg2=%p", arg0,arg1,arg2); >> this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); >> printf("string=%s", copyinstr(this->str)); >> } >> ... >> But it showed that the value of arg1 in Fun:return probe is 2 !! Not >> a valid address. >> Is there any mistakes here? > > I don''t see that when I run the above - arg1 contains a > pointer to the string object. Note that arg2 makes no sense > when used in a pid provider return probe. > > Cheers. > > Jon. > >> >> Thanks, >> Zhijun >> >> Jonathan Haslam wrote: >> >>> >>>> Please refer to this: >>>> pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return >>>> >>>> /self->trace/ >>>> { >>>> self->trace = 0; >>>> >>>> printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = >>>> %d\n\n", copyinstr(&arg0), arg1, arg2, arg3); >>>> >>>> } >>>> >>>> There is still this problem! >>>> >>> The problem here is that the std::string object embeds a pointer >>> to the character array. What you actually need to do is to copyin() >>> the pointer and then use that in the copyinstr(). >>> >>> Just to work it through, here''s a simple piece of code using >>> string objects which I think is representative of what you are >>> doing(I''m no C++ man so don''t laugh at the code...): >>> >>> # cat t.cc >>> #include <iostream> >>> #include <string> >>> >>> using namespace std; >>> >>> string >>> Fun(string foo) >>> { >>> return(foo); >>> } >>> >>> int >>> main(int argc, char *argv[]) >>> { >>> string namestr = "Jon"; >>> >>> Fun(namestr); >>> } >>> >>> >>> Let''s compile it and look at the layout of the string object: >>> >>> # CC -g -o t t.cc # dbx ./t >>> For information about new features see `help changes'' >>> To remove this message, put `dbxenv suppress_startup_message 7.4'' in >>> your .dbxrc >>> Reading t >>> Reading ld.so.1 >>> Reading libCstd.so.1 >>> Reading libCrun.so.1 >>> Reading libm.so.2 >>> Reading libc.so.1 >>> (dbx) stop in >>> main (2) >>> stop in main >>> (dbx) run Running: t >>> (process id 101522) >>> stopped in main at line 15 in file "t.cc" >>> 15 string namestr = "Jon"; >>> (dbx) step >>> stopped in main at line 17 in file "t.cc" >>> 17 Fun(namestr); >>> (dbx) print +r namestr >>> namestr = { >>> __data_ = { >>> __data_ = 0x8080864 "Jon" >>> } >>> npos = 0 >>> __nullref = 4 >>> } >>> >>> So, we need to copyin() the __data_ pointer and we can then >>> feed that into a copyinstr(). Here''s the D script to do that: >>> >>> #!/usr/sbin/dtrace -s >>> >>> #pragma D option quiet >>> >>> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:entry >>> >>> { >>> this->str = *(uintptr_t *)copyin(arg1, sizeof(void *)); >>> printf("string = %s", copyinstr(this->str)); >>> } >>>Here,a *entry* probe but access arg1 instead of arg0. Why?>>> Executing this we get what we expect: >>> >>> # dtrace -32 -s ./t.d -c ./t >>> string = Jon >>> >>> (Note that use of -32 to select the correct data model here). >>> >>> I know this isn''t that pretty. Having to copyin() the data like >>> that is pretty ugly but that''s the way it is at the minute. Also, >>> the lack of type information in user-land is something that could >>> do with addressing (though that''s not a small piece of work). >>> >>> Hope this helps. >>> >>> Cheers. >>> >>> Jon. >>> >>> _______________________________________________ >>> dtrace-discuss mailing list >>> dtrace-discuss at opensolaris.org >> >> >> _______________________________________________ >> dtrace-discuss mailing list >> dtrace-discuss at opensolaris.org >
Jarod Jenson
2006-Nov-30 13:50 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
It''s C++ - arg0 will be "this" that is passed for you. Thanks, Jarod Robin Fu''s email at 11/30/2006 5:33 AM, said:> Yes, Eric''s intent was to use a return probe. > But in your script you used a *entry* probe,and accessed arg1 instead of > arg0. > That is where I am puzzled. > > Thanks, > Zhijun > > Jonathan Haslam wrote: >> >>> Two questions: >>> 1)I noticed you access arg1 instead of arg0 in your dtrace script. >>> And my test proved that arg1 is actually the string parameter. >>> But it is weird,as the first parameter should always passed in by arg0, >>> and in this case string is the only parameter of Fun(). >>> So why you access it by arg1? >> >> We are using a *return* probe in this case and they have the >> following arguments: >> >> arg0 - offset in the functon of the return instruction >> arg1 - The actual return value of the function >> >> Check out chapter 30 in the DTrace user guide for more >> information. >> >>> 2)Eric''s original question is that he would like to get the return >>> value of that question.To finish that,I wrote a simple D-script that >>> is as follows: >>> ... >>> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:return >>> >>> { >>> printf("arg0=%p, arg1=%p, arg2=%p", arg0,arg1,arg2); >>> this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); >>> printf("string=%s", copyinstr(this->str)); >>> } >>> ... >>> But it showed that the value of arg1 in Fun:return probe is 2 !! Not >>> a valid address. >>> Is there any mistakes here? >> >> I don''t see that when I run the above - arg1 contains a >> pointer to the string object. Note that arg2 makes no sense >> when used in a pid provider return probe. >> >> Cheers. >> >> Jon. >> >>> >>> Thanks, >>> Zhijun >>> >>> Jonathan Haslam wrote: >>> >>>> >>>>> Please refer to this: >>>>> pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return >>>>> >>>>> /self->trace/ >>>>> { >>>>> self->trace = 0; >>>>> >>>>> printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = >>>>> %d\n\n", copyinstr(&arg0), arg1, arg2, arg3); >>>>> >>>>> } >>>>> >>>>> There is still this problem! >>>>> >>>> The problem here is that the std::string object embeds a pointer >>>> to the character array. What you actually need to do is to copyin() >>>> the pointer and then use that in the copyinstr(). >>>> >>>> Just to work it through, here''s a simple piece of code using >>>> string objects which I think is representative of what you are >>>> doing(I''m no C++ man so don''t laugh at the code...): >>>> >>>> # cat t.cc >>>> #include <iostream> >>>> #include <string> >>>> >>>> using namespace std; >>>> >>>> string >>>> Fun(string foo) >>>> { >>>> return(foo); >>>> } >>>> >>>> int >>>> main(int argc, char *argv[]) >>>> { >>>> string namestr = "Jon"; >>>> >>>> Fun(namestr); >>>> } >>>> >>>> >>>> Let''s compile it and look at the layout of the string object: >>>> >>>> # CC -g -o t t.cc # dbx ./t >>>> For information about new features see `help changes'' >>>> To remove this message, put `dbxenv suppress_startup_message 7.4'' in >>>> your .dbxrc >>>> Reading t >>>> Reading ld.so.1 >>>> Reading libCstd.so.1 >>>> Reading libCrun.so.1 >>>> Reading libm.so.2 >>>> Reading libc.so.1 >>>> (dbx) stop in >>>> main (2) >>>> stop in main >>>> (dbx) run Running: t >>>> (process id 101522) >>>> stopped in main at line 15 in file "t.cc" >>>> 15 string namestr = "Jon"; >>>> (dbx) step >>>> stopped in main at line 17 in file "t.cc" >>>> 17 Fun(namestr); >>>> (dbx) print +r namestr >>>> namestr = { >>>> __data_ = { >>>> __data_ = 0x8080864 "Jon" >>>> } >>>> npos = 0 >>>> __nullref = 4 >>>> } >>>> >>>> So, we need to copyin() the __data_ pointer and we can then >>>> feed that into a copyinstr(). Here''s the D script to do that: >>>> >>>> #!/usr/sbin/dtrace -s >>>> >>>> #pragma D option quiet >>>> >>>> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:entry >>>> >>>> { >>>> this->str = *(uintptr_t *)copyin(arg1, sizeof(void *)); >>>> printf("string = %s", copyinstr(this->str)); >>>> } >>>> > Here,a *entry* probe but access arg1 instead of arg0. > Why? >>>> Executing this we get what we expect: >>>> >>>> # dtrace -32 -s ./t.d -c ./t >>>> string = Jon >>>> >>>> (Note that use of -32 to select the correct data model here). >>>> >>>> I know this isn''t that pretty. Having to copyin() the data like >>>> that is pretty ugly but that''s the way it is at the minute. Also, >>>> the lack of type information in user-land is something that could >>>> do with addressing (though that''s not a small piece of work). >>>> >>>> Hope this helps. >>>> >>>> Cheers. >>>> >>>> Jon. >>>> >>>> _______________________________________________ >>>> dtrace-discuss mailing list >>>> dtrace-discuss at opensolaris.org >>> >>> >>> _______________________________________________ >>> dtrace-discuss mailing list >>> dtrace-discuss at opensolaris.org >> > > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org > >
Jonathan Haslam
2006-Nov-30 16:10 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
> Yes, Eric''s intent was to use a return probe. > But in your script you used a *entry* probe,and accessed arg1 instead > of arg0. > That is where I am puzzled.And you have good reason to be puzzled. I''ll withdraw my foot from my mouth and (hopefully) correct the stuff that I sent out yesterday. Thanks for pointing out my mistake. First, a short summary for those that don''t wish to read that much: 1) I did indeed use an entry probe instead of a return probe. Changing to use a return probe breaks the example I gave if the code is compiled with Sun Studio. 2) By the look of it, the example now breaks because the Studio compilers aren''t ABI compliant when passing back structures. The Example I gave works with g++ but not with Studio... I''ll log a bug. Now for a bit more detail on what it looks like is going off. Eric asked about looking at the contents of a string object when returned from a C++ function. The answer that I gave was incorrect as it used the entry probe for a function. It appeared to work owing to a couple of factors: 1) The test code was poor as it just returned the same object that it was passed. Therefore when I examined arg1 (see next point) it looked correct. 2) arg1 in C++ will be my first argument as arg0 is the "this" pointer (as Jarod pointed out). So, if I actually alter my code to use a return probe it does indeed fail in the way you describe - i.e. I see an incorrect value in arg1. The reason as to why this happens is this: When an object is returned in C++ we are, essentially, returning a structure (a lump of memory anyway). The ABI specifies that when returning a structure it is up to the calling function (main() in this case) to allocate some space and store the address on the stack which the called function then uses. We therefore have a "hidden" argument which is referenced via the stack so the return object referencing is done via the stack in this case. The ABI does stipulate however that the a function that returns a structure or union also should set %eax to contain (essentially) a pointer to the structure being returned. Our compiler doesn''t do that in this case but g++ does. I won''t go into the details of why it appears not to do that here. I''ll log a bug on this. So, to recap, change my D script to use the return probe and code compiled with g++ should be fine. Unfortunately, it looks like this won''t work with Studio compiler at the minute. Cheers. Jon.> > Thanks, > Zhijun > > Jonathan Haslam wrote: > >> >>> Two questions: >>> 1)I noticed you access arg1 instead of arg0 in your dtrace script. >>> And my test proved that arg1 is actually the string parameter. >>> But it is weird,as the first parameter should always passed in by arg0, >>> and in this case string is the only parameter of Fun(). >>> So why you access it by arg1? >> >> >> We are using a *return* probe in this case and they have the >> following arguments: >> >> arg0 - offset in the functon of the return instruction >> arg1 - The actual return value of the function >> >> Check out chapter 30 in the DTrace user guide for more >> information. >> >>> 2)Eric''s original question is that he would like to get the return >>> value of that question.To finish that,I wrote a simple D-script that >>> is as follows: >>> ... >>> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:return >>> >>> { >>> printf("arg0=%p, arg1=%p, arg2=%p", arg0,arg1,arg2); >>> this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); >>> printf("string=%s", copyinstr(this->str)); >>> } >>> ... >>> But it showed that the value of arg1 in Fun:return probe is 2 !! Not >>> a valid address. >>> Is there any mistakes here? >> >> >> I don''t see that when I run the above - arg1 contains a >> pointer to the string object. Note that arg2 makes no sense >> when used in a pid provider return probe. >> >> Cheers. >> >> Jon. >> >>> >>> Thanks, >>> Zhijun >>> >>> Jonathan Haslam wrote: >>> >>>> >>>>> Please refer to this: >>>>> pid$1:libpolcomp:__1cLtpComponentKgetMMLname6Mib_nDstdMbasic_string4Ccn0BLchar_traits4Cc__n0BJallocator4Cc_____:return >>>>> >>>>> /self->trace/ >>>>> { >>>>> self->trace = 0; >>>>> >>>>> printf("\n\nreturn: arg0 = %s, arg1 = %d, arg2 = %d, arg3 = >>>>> %d\n\n", copyinstr(&arg0), arg1, arg2, arg3); >>>>> >>>>> } >>>>> >>>>> There is still this problem! >>>>> >>>> The problem here is that the std::string object embeds a pointer >>>> to the character array. What you actually need to do is to copyin() >>>> the pointer and then use that in the copyinstr(). >>>> >>>> Just to work it through, here''s a simple piece of code using >>>> string objects which I think is representative of what you are >>>> doing(I''m no C++ man so don''t laugh at the code...): >>>> >>>> # cat t.cc >>>> #include <iostream> >>>> #include <string> >>>> >>>> using namespace std; >>>> >>>> string >>>> Fun(string foo) >>>> { >>>> return(foo); >>>> } >>>> >>>> int >>>> main(int argc, char *argv[]) >>>> { >>>> string namestr = "Jon"; >>>> >>>> Fun(namestr); >>>> } >>>> >>>> >>>> Let''s compile it and look at the layout of the string object: >>>> >>>> # CC -g -o t t.cc # dbx ./t >>>> For information about new features see `help changes'' >>>> To remove this message, put `dbxenv suppress_startup_message 7.4'' >>>> in your .dbxrc >>>> Reading t >>>> Reading ld.so.1 >>>> Reading libCstd.so.1 >>>> Reading libCrun.so.1 >>>> Reading libm.so.2 >>>> Reading libc.so.1 >>>> (dbx) stop in >>>> main (2) >>>> stop in main >>>> (dbx) run Running: t >>>> (process id 101522) >>>> stopped in main at line 15 in file "t.cc" >>>> 15 string namestr = "Jon"; >>>> (dbx) step >>>> stopped in main at line 17 in file "t.cc" >>>> 17 Fun(namestr); >>>> (dbx) print +r namestr >>>> namestr = { >>>> __data_ = { >>>> __data_ = 0x8080864 "Jon" >>>> } >>>> npos = 0 >>>> __nullref = 4 >>>> } >>>> >>>> So, we need to copyin() the __data_ pointer and we can then >>>> feed that into a copyinstr(). Here''s the D script to do that: >>>> >>>> #!/usr/sbin/dtrace -s >>>> >>>> #pragma D option quiet >>>> >>>> pid$target::__1cDFun6FnDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc_____1_:entry >>>> >>>> { >>>> this->str = *(uintptr_t *)copyin(arg1, sizeof(void *)); >>>> printf("string = %s", copyinstr(this->str)); >>>> } >>>> > Here,a *entry* probe but access arg1 instead of arg0. > Why? > >>>> Executing this we get what we expect: >>>> >>>> # dtrace -32 -s ./t.d -c ./t >>>> string = Jon >>>> >>>> (Note that use of -32 to select the correct data model here). >>>> >>>> I know this isn''t that pretty. Having to copyin() the data like >>>> that is pretty ugly but that''s the way it is at the minute. Also, >>>> the lack of type information in user-land is something that could >>>> do with addressing (though that''s not a small piece of work). >>>> >>>> Hope this helps. >>>> >>>> Cheers. >>>> >>>> Jon. >>>> >>>> _______________________________________________ >>>> dtrace-discuss mailing list >>>> dtrace-discuss at opensolaris.org >>> >>> >>> >>> _______________________________________________ >>> dtrace-discuss mailing list >>> dtrace-discuss at opensolaris.org >> >> > > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org
Robin Fu
2006-Dec-01 01:33 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Thanks,Jon,for your kindly explanation. ;-) And still I am a bit puzzled about the arg0 and arg1 parameters, see my comments inline.Please correct me if I make mistakes. Jonathan Haslam wrote:> >> Yes, Eric''s intent was to use a return probe. >> But in your script you used a *entry* probe,and accessed arg1 instead >> of arg0. >> That is where I am puzzled. > > And you have good reason to be puzzled. I''ll withdraw my > foot from my mouth and (hopefully) correct the stuff that > I sent out yesterday. Thanks for pointing out my mistake. > > First, a short summary for those that don''t wish to read that > much: > > 1) I did indeed use an entry probe instead of a return probe. > Changing to use a return probe breaks the example I gave > if the code is compiled with Sun Studio. > 2) By the look of it, the example now breaks because the > Studio compilers aren''t ABI compliant when passing back > structures. The Example I gave works with g++ but not > with Studio... I''ll log a bug. > > Now for a bit more detail on what it looks like is going off. > Eric asked about looking at the contents of a string object > when returned from a C++ function. The answer that I gave > was incorrect as it used the entry probe for a function. > It appeared to work owing to a couple of factors: > > 1) The test code was poor as it just returned the same > object that it was passed. Therefore when I examined > arg1 (see next point) it looked correct. > 2) arg1 in C++ will be my first argument as arg0 is > the "this" pointer (as Jarod pointed out). >Do you mean C++ compiler will add a "this" pointer to each function? Or the changes is just in dtrace script? As far as I know,C++ compiler will do name mangling for all functions, but it will ONLY add "this" pointer to Class member functions;for global functions such as Fun(),no "this" pointer is added. And I also used a script to test: #!/usr/sbin/dtrace -s #pragma D option quiet pid$target::_Z3FunSs:entry { printf("arg0=%p, arg1=%p\n",arg0,arg1); this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); printf("string=%s\n", copyinstr(this->str)); } pid$target::_Z3FunSs:return { printf("arg0=%p, arg1=%p\n",arg0,arg1); this->str=*(uintptr_t*)copyin(arg1,sizeof(void*)); printf("string=%s\n", copyinstr(this->str)); } #root at zhijun-5:tmp] dtrace -s test.d -c ./tt //tt is g++ compiled arg0=8047b94, arg1=8047b84 string=Jon arg0=20, arg1=8047b94 string=Jon From the output,I don''t think arg0 (8047b94) seems to be a "this" pointer. Thanks, Zhijun> So, if I actually alter my code to use a return probe it > does indeed fail in the way you describe - i.e. I see an > incorrect value in arg1. The reason as to why this happens > is this: > > When an object is returned in C++ we are, essentially, > returning a structure (a lump of memory anyway). The > ABI specifies that when returning a structure it is up > to the calling function (main() in this case) to allocate > some space and store the address on the stack which the > called function then uses. We therefore have a "hidden" > argument which is referenced via the stack so the return > object referencing is done via the stack in this case. > > The ABI does stipulate however that the a function that > returns a structure or union also should set %eax to contain > (essentially) a pointer to the structure being returned. Our > compiler doesn''t do that in this case but g++ does. I won''t go > into the details of why it appears not to do that here. I''ll > log a bug on this. > > So, to recap, change my D script to use the return probe > and code compiled with g++ should be fine. Unfortunately, > it looks like this won''t work with Studio compiler at the > minute. > > Cheers. > > Jon. >
Jonathan Haslam
2006-Dec-01 12:15 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
> Do you mean C++ compiler will add a "this" pointer to each function? > Or the changes is just in dtrace script? > As far as I know,C++ compiler will do name mangling for all functions, > but it will ONLY add "this" pointer to Class member functions;for > global functions such as Fun(),no "this" pointer is added.Yes. This was another case of me not thinking clearly before typing! As you say, the "this" pointer will be arg0 in the entry to class member functions only. However, C++ has a tendency to add hidden arguments in other places as well and, unfortunately, you have to be aware of them when using DTrace as we have seen here. See next comment.> #root at zhijun-5:tmp] dtrace -s test.d -c ./tt //tt is g++ > compiled > arg0=8047b94, arg1=8047b84 > string=Jon > arg0=20, arg1=8047b94 > string=Jon > > From the output,I don''t think arg0 (8047b94) seems to be a "this" > pointer.You''re correct - it isn''t. It is a hidden argument which is a pointer to the space allocated by the caller for the return structure to be placed in. This is the value that I referenced in my post yesterday that should be in the %eax register on return (as it is with g++ here). The actual argument to the function appears here in arg1. All this goes to show that you have to be really careful with argument interpretation with C++ as arguments can appear shifted because the compiler adds arguments in. In normal runtime you don''t have to worry about this but DTrace says it as it sees it and you have to understand what is happening under the hood. Thanks for following through on my comments. Let me know if there still appears to be any inconsistencies. Cheers. Jon.> > > Thanks, > Zhijun > >> So, if I actually alter my code to use a return probe it >> does indeed fail in the way you describe - i.e. I see an >> incorrect value in arg1. The reason as to why this happens >> is this: >> >> When an object is returned in C++ we are, essentially, >> returning a structure (a lump of memory anyway). The >> ABI specifies that when returning a structure it is up >> to the calling function (main() in this case) to allocate >> some space and store the address on the stack which the >> called function then uses. We therefore have a "hidden" >> argument which is referenced via the stack so the return >> object referencing is done via the stack in this case. >> >> The ABI does stipulate however that the a function that >> returns a structure or union also should set %eax to contain >> (essentially) a pointer to the structure being returned. Our >> compiler doesn''t do that in this case but g++ does. I won''t go >> into the details of why it appears not to do that here. I''ll >> log a bug on this. >> >> So, to recap, change my D script to use the return probe >> and code compiled with g++ should be fine. Unfortunately, >> it looks like this won''t work with Studio compiler at the >> minute. >> >> Cheers. >> >> Jon. >> >
Jon Haslam
2006-Dec-01 20:06 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
> 2) By the look of it, the example now breaks because the > Studio compilers aren''t ABI compliant when passing back > structures. The Example I gave works with g++ but not > with Studio... I''ll log a bug.In case anyone is interested, the compiler group are, as always, hot on the trail of this one. Two bugs have been created to cover this issue, one for the optimizing code generator and one for the non-optimizing code generator: 6499797 eax (rax for 64-bit) does not contain the address of a returned struct 6499800 eax (rax for 64-bit) does not contain the address of a returned struct Cheers. Jon.
Robin Fu
2006-Dec-03 11:30 UTC
[dtrace-discuss] Re: Re: DTrace: How to print string in C++
Hi,Jon, I totally agree with you,and thanks for your kindly explanations:) I also suppose that "hiden argument" issue exists in C as well as in C++, which I have verified using a similar D script.So I think perhaps we should take special care with functions using struct(or class object) as parameters or return value, in which case compiler may add hiden parameters to our functions. Cheers, Zhijun Jonathan Haslam wrote:> >> Do you mean C++ compiler will add a "this" pointer to each function? >> Or the changes is just in dtrace script? >> As far as I know,C++ compiler will do name mangling for all >> functions, but it will ONLY add "this" pointer to Class member >> functions;for global functions such as Fun(),no "this" pointer is added. > > Yes. This was another case of me not thinking clearly before > typing! As you say, the "this" pointer will be arg0 in the > entry to class member functions only. However, C++ has a tendency > to add hidden arguments in other places as well and, > unfortunately, you have to be aware of them when using DTrace > as we have seen here. See next comment. > >> #root at zhijun-5:tmp] dtrace -s test.d -c ./tt //tt is g++ >> compiled >> arg0=8047b94, arg1=8047b84 >> string=Jon >> arg0=20, arg1=8047b94 >> string=Jon >> >> From the output,I don''t think arg0 (8047b94) seems to be a "this" >> pointer. > > You''re correct - it isn''t. It is a hidden argument which is a > pointer to the space allocated by the caller for the return > structure to be placed in. This is the value that I referenced > in my post yesterday that should be in the %eax register on return > (as it is with g++ here). The actual argument to the function > appears here in arg1. > > All this goes to show that you have to be really careful with > argument interpretation with C++ as arguments can appear shifted > because the compiler adds arguments in. In normal runtime you > don''t have to worry about this but DTrace says it as it sees it > and you have to understand what is happening under the hood. > > Thanks for following through on my comments. Let me know if > there still appears to be any inconsistencies. >