Suppose one had inherited a complex codebase (in Visual C++, assume 2003 or perhaps later) with a large and complex inheritance graph. Suppose it's deep, and there's lots of virtual functions and possibly even multiple inheritance as well. (Yes, a bit of a maintenance nightmare). Any attempt to refactor this class hierarchy into something saner will need to know which implementation of each virtual function each class uses.
If we take an arbitrary leaf class L1 - which derives from base class B1, which derives from base class B2, etc. - it will clearly have a vtable for the class which will show something like (pseudo-vtable):
L1::F1
B3::F2
B1::F3
L1::F4
etc.
...depending on exactly which virtual functions have been overridden by which class.
How could one see such a vtable in a form much like that? It would be possible to reconstruct it by hand by reading through the code, but that's error-prone and laborious. Presumably also, breaking into an object of the class in the debugger could allow you to inspect the vtable in a Watch window via the vtable pointer for that one class, but that's an awkward solution particularly if you want to also see the vtables for L2, L3, ... LN.
Does DbgHelp.dll provide facilities to inspect the vtables programmatically (allowing output in whatever form is required)? Or is there some other method?
With Visual Studio 2005 there are two undocumented flags that does exactly what you need. They are the reportAllClassLayout and reportSingleClassLayout flags. For example try "/d1 reportAllClassLayout" on the cl.exe commandline. It will show you the full class layout including virtual tables, here's an Example. Also see http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx There isn't too much information on these flags because they are undocumented for now but maybe Microsoft will officially support them in future versions of visual studio.
Another approach, and actually what I prefer, is to use the IDA Pro Interactive disassembler. There is a huge learning curve, but IDA is smart enough to help you build VTables and links them to your classes. It's used to reverse engineer binaries that you don't have symbols for traditionally but it does use visual studio pdb files too. Doing so you will see exactly what all your vtables look like. Which virtual tables are being used for what methods, or what methods are being overridden, all whilst stepping through the code. In other words you actually see your method calls being traced into the vtable during runtime debugging. Typical debuggers like VS debugger don't trace into virtual tables as you've noticed.
I would highly recommend using Doxygen as a tool for any sort of code analysis like this. I don't think it has a quick way to find the final overrider for any function in a type, but it should provide a listing of what is inherited and what is implemented, so that you can quickly scan the tree to identify the overrider for any given function (usually, your hierarchy isn't big enough as to make it a big deal). It can also generate call graphs, relation graphs, and hyperlinked source code, which is a fantastic tool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With