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