Monday Oct 05, 2009

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.

The example is available at:

About

user12610965

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today