As far as I know, everything you've said is 100% correct. I've experienced the same issues. In fact, I was working on this exact problem in the background when a friend sent me a link to this post.
There are actually three related issues here. First, prior to IDA 7.2, IDA's type system did not have a concept of a virtual function table per se. Meaning, although you can create a structure with a bunch of function pointers in it, IDA did not have a mechanism for changing the type of the VTable pointer in a derived object. "Derivation" meant simply that everything from the base class was included literally at offset 0. Fortunately, IDA 7.2 does understand the concept of VTables in inheritance. There is a bit of documentation on Hex-Rays' website. The end of that page summarizes the rules:
- VFT pointer must have the "__vftable" name
- VFT type must follow the "CLASSNAME_vtbl" pattern
- For multiple inheritance use "CLASSNAME_%04X_vtbl" as the VFT type name where %04X corresponds to the offset of the vft pointer in CLASSNAME in the case if the offset is not zero
The second issue is that the PDB plugin currently does not take advantage of these recent changes to the type system. I.e., it does not generate VTable type/class VTable member names according to the rules above.
The third issue is that the PDB file format is, frankly, a nightmare. You can view the contents of a PDB with the "dia2dump" sample that comes with Visual Studio (in the "DIA SDK" directory), however, be forewarned that the output is often wrong, misleading, or missing important information. The handling of virtual function information is especially terrible. I haven't completed my investigations, but one thing I've learned so far is that only base classes have SymTagVTable
symbols. I.e., for a class B
that derives from another class A
with a VTable, only A
will have a SymTagVTable
symbol, not B
. This is even true if B
defines additional virtual functions that were not defined in A
. And currently, the PDB plugin only creates VTables if the class has a SymTagVTable
symbol, hence the behavior that you are seeing. Instead, you have to iterate through the member functions of B
and check whether they are virtual using the get_virtual
method -- which, by the way, is something that dia2dump does not do. I'm still investigating how all of this works for multiple inheritance.
In short, the solution to your problem -- and my problem -- lies in modifying the IDA 7.2 PDB plugin (which comes with the SDK) to:
- Recover VTable information for derived classes, including the multiple inheritance scenario
- Name the VTable structure types in a suitable way based on the class names (and displacement offset in the case of multiple inheritance)
- Use the new features in
typeinf.hpp
to mark the VTable pointer with attributeTAFLD_VFTABLE
, and the VTable structure itself with attributeTAUDT_VFTABLE
.
Again, this is what I am also currently working on.