Looking for C++ object in a memory dump
When analyzing the core dump of a C++ based, long-running, server application it may be helpful to know the exact state of some objects created by the process. The question, then is, how to find that object. Core files consist of the recorded state of the working memory. The task may be not trivial if the process uses lots of memory.
I’ll assume that the C++ object has some virtual method. In that case, the object must contain a virtual pointer to the V-table of a class. By using the nm
tool, it is easy to determine the address of a V-table. I can use that address, to determine exact locations in a core dump, of all the objects of that class, as all those objects will contain an address to V-table.
To demonstrate how the procedure works, let’s use the following, code below as “server application”. We are looking for an object t
.
class test {
public:
virtual ~test(){}
};
int main() {
;
test t();
abortreturn 0;
}
As mentioned, the nm
command shows an address of test
class V-table.
$ nm -C myapp | grep "vtable for test"
0000000000400980 V vtable for test
Ok, so the V-table address is 0x400980
. Now I need to find a V-pointer in the compiled binary. The value of a V-pointer is an address to the V-table + 16 (on a 64-bit system). To understand where this +16 comes from, we need to understand how the layout of the V-table looks like.
The graph above shows 5 segments. Typically, on a 64-bit system, each of those segments is 8 bytes long (4 on a 32-bit system). V-table starts with an empty segment, storing value 0x00
. The following segment contains an address to the typeinfo object of the class (used by the typeid
function). The next segment is an address to the first virtual function declared in the class - in our case, it is an address to the destructor of the test
class. The V-pointer stores address to this function, which is a reason why the value of V-pointer is an address of V-table+16 (V-table + 2 segments).
The next step in my investigation is to determine an address of the V-pointer in a program binary. Address of a V-table is 0x400980
, so the address too look for is a value 0x00400980 + 0x10 = 0x00400990
.
> hexdump -C myapp | grep "90 09 40 00"
00001860 48 c7 00 90 09 40 00 5d c3 90 90 90 90 90 90 90 |H....@.]........|
00002860 48 c7 00 90 09 40 00 5d c3 90 90 90 90 90 90 90 |H....@.]........|
0005e410 90 09 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
We have got 3 possible places where an object may be located. I’ll use 3-rd for further description. I know that is the one I’m looking for, but normally at this point, one needs to somehow determine which object is the interesting one by examinating all of them. The address of this object is 0x005e410
.
Now we need to find out what’s the address of this object in a core file. To do it you need to do some calculations, because:
object address in a core file = offset to the V-pointer from program binary + VMA address - VMA offset
VMA address and VMA offset we can get by using objdump
or readelf
commands.
> objdump -h corefile
Sections:
Idx Name Size VMA LMA File off Algn
...
36 load26 00001000 00007f7fbc5c5000 0000000000000000 0003e000 2**12
CONTENTS, ALLOC, LOAD
37 load27 00022000 00007fff4f143000 0000000000000000 0003f000 2**12
CONTENTS, ALLOC, LOAD
38 load28 00001000 00007fff4f1f9000 0000000000000000 00061000 2**12
CONTENTS, ALLOC, LOAD, READONLY, CODE
Section 37, starting with load 27
is the interesting one. That’s because the V-pointer offset value from the program binary is 0x005e410
. This value is between 0x3f000
(“File off” column for section 37) and 0x61000
(“File off” column for section 38). VMA address value for this section is 00007fff4f143000
, VMA offset value is 0003f000
. According to the formula above address of the object will be:
0x5e410 + 0x7fff4f143000 - 0x3f000 = 0x7FFF4F162410
Let’s now check with GDB if the described procedure is correct:
> gdb myapp core
(gdb) p &t
$1 = (test *) 0x7fff4f162410
As we see address of the t
variable is the same as what I have got from the calculation so the procedure is correct.