DTrace and C++ Objects
If you are interested in accessing the fields of a C++ object, then read on.
This research was performed using OpenSolaris build 104 on an X64 based platform using SunStudio 12.
In order to access the fields of a C++ object through the this pointer, then you need to know the offsets of the data you wish to examine. A C++ object is not a C struct and DTrace does not understand C++.
Attached is an example.
First, you must identify the location of the virtual function table. In a simple object it is the first field. If you have multiple inheritance there may be more than one virtual function table.
Consider:
arwen: make
CC -m64 -g -c CCtest.cc
CC -m64 -g -c TestClass.cc
CC -m64 -g -o CCtest CCtest.o TestClass.o
echo "Done."
Done.
I will use dbx to identify the virtual function table pointer.
arwen: dbx CCtest
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.7' in your .dbxrc
Reading CCtest
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: CCtest
(process id 2803)
stopped in main at line 10 in file "CCtest.cc"
10 int i=0;
(dbx) n
stopped in main at line 13 in file "CCtest.cc"
13 t = new TestClass(i);
(dbx) n
stopped in main at line 14 in file "CCtest.cc"
14 t->a='a';
(dbx) n
stopped in main at line 15 in file "CCtest.cc"
15
(dbx) n
stopped in main at line 16 in file "CCtest.cc"
16 cout << t->ClassName();
(dbx) n
Integer = 0
stopped in main at line 17 in file "CCtest.cc"
17 t->setname((const char *)"Goodbye.");
(dbx) n
stopped in main at line 18 in file "CCtest.cc"
18 cout << t->ClassName() << endl;
(dbx) n
Goodbye.
stopped in main at line 19 in file "CCtest.cc"
19 sleep(5);
(dbx)
(dbx) print t
t = 0x4175b0
(dbx) print &t
&t = 0xfffffd7fffdfeb30
(dbx) print *t
*t = {
a = 'a'
j = 65535
str = 0x41cbe0 "Goodbye."
}
(dbx) examine t/20
0x00000000004175b0: 0x00412870 0x00000000 0x00000061 0x0000ffff
0x00000000004175c0: 0x0041cbe0 0x00000000 0x00000000 0x00000000
0x00000000004175d0: 0x00000020 0x00000000 0x00000000 0x00000000
0x00000000004175e0: 0x00417600 0x00000000 0x00000000 0x00000000
0x00000000004175f0: 0x00000000 0x00000000 0x00000000 0x00000000
=========================================================
The above identifies the first field as the location of the virtual function table.
Now the DTrace.
less str.d
#!/usr/sbin/dtrace -Cs
typedef struct TestClass
{
void *ptr;
char a;
int j;
char *str;
}TestClass_t;
pid$target::__1cJTestClassHsetname6Mpkc_i_:entry
{
this->ptr = arg0; /* this pointer */
printf("\n this ptr = %p\n", this->ptr);
this->sptr=(TestClass_t *)copyin(this->ptr, sizeof(TestClass_t));
printf("\n this my_ptr = %p\n", ((TestClass_t *)this->sptr)->ptr);
printf("\n this my_char = %c\n", ((TestClass_t *)this->sptr)->a);
printf("\n this my_int = %d\n", ((TestClass_t *)this->sptr)->j);
printf("\n this my_str_ptr = %p\n", ((TestClass_t *)this->sptr)->str);
printf("\n this my_str = %s \n", copyinstr((uintptr_t)((TestClass_t
+*)this->sptr)->str));
this->str = copyinstr(arg1);
printf("\nnew string = %s\n", this->str);
}
=========================================================
arwen: str.d -c CCtest
dtrace: script 'str.d' matched 1 probe
Integer = 0Goodbye.
CPU ID FUNCTION:NAME
0 83901 __1cJTestClassHsetname6Mpkc_i_:entry
this ptr = 4175b0
this my_ptr = 412870
this my_char = a
this my_int = 65535
this my_str_ptr = 435d10
this my_str = Integer = 0
new string = Goodbye.
Integer = 1Goodbye.
1 83901 __1cJTestClassHsetname6Mpkc_i_:entry
this ptr = 4175b0
this my_ptr = 412870
this my_char = a
this my_int = 65535
this my_str_ptr = 435d10
this my_str = Integer = 1
new string = Goodbye.
