To add Igor Skochinsky's answer:
Given VFT address, you can print the mangled class name:
unsigned int* vmtaddr = *(int*)obj_addr;
DLOG("class name: _Z%s",((char***)vmtaddr)[-1][1]);
The class name may be decoded with c++filt
.
(The _Z
thing is not stored there, but required for c++filt
to work.)
You can also print the inheritance chain (the trick is that typeinfo is also an object, and if it is a __cxxabiv1::__si_class_type_info
, against whose mangled name we strcmp()
, there has been single inheritance and a pointer to the superclass typeinfo follows the pointer to name):
char* classchain = strrealloccat(NULL, "_Z");
char**ptypeinfo = ((char***)vmtaddr[-1]);
for (; ptypeinfo ; ptypeinfo = !strcmp(((char***)ptypeinfo[0])[-1][1], "N10__cxxabiv120__si_class_type_infoE") ? (char**)ptypeinfo[2] : 0) {
//DLOG("tinfo: %p",ptypeinfo);
//DLOG("class: _Z%s meta: _Z%s",ptypeinfo[1], ((char***)ptypeinfo[0])[-1][1]);
//DLOG("meta : _Z%s",((char***)ptypeinfo[0])[-1][1]);
classchain = strrealloccat(strrealloccat(classchain, ptypeinfo[1]), " _Z");
}
DLOG("inheritance chain: %s",classchain);
free(classchain);
where strrealloccat()
is defined as:
char* strrealloccat(char* buffer0, char *addition)
{
char* buffer = realloc(buffer0, (buffer0 ? strlen(buffer0) : 0) + strlen(addition) + sizeof(char));
if (!buffer) {
return buffer;
}
if(!buffer0) {
*buffer = 0;
}
return strcat(buffer, addition);
}
_Z4hopeN4this5helpsE