1

I tried using CXXRecordDecl, to print the virtual functions, but they are in declaration order, which may not be the order actually in the vtable.

sample code

namespace test
{

class Foo {

 public:
    virtual void v_func() {}
    virtual void v_func2() {}
    virtual ~Foo() = default;
};

class Bar : public Foo {
    public:
    virtual void v_func2() {}
    virtual void v_func() {}
    virtual ~Bar() = default;
};

} // namespace test



int main() {
    test::Foo *foo = new test::Bar();
    test::Bar *bar = new test::Bar();
    delete foo;
    delete bar;
    return 0;
}

The virtual function table printed by gdb is as follows:

(gdb) info vtbl foo
vtable for 'test::Foo' @ 0x65a450 (subobject @ 0x101a008):
[0]: 0x404402 <test::Bar::v_func()>
[1]: 0x4043f4 <test::Bar::v_func2(int, test::tmp)>
(gdb) info vtbl bar
vtable for 'test::Bar' @ 0x65a450 (subobject @ 0x101a010):
[0]: 0x404402 <test::Bar::v_func()>
[1]: 0x4043f4 <test::Bar::v_func2(int, test::tmp)>

By traversing the method of CXXRecordDecl, it can only print in the order of function declaration.

// CXXRecordDecl *cxx_record
// Dump out all the virtual methods
for (CXXRecordDecl::method_iterator first = cxx_record->method_begin();
      first != cxx_record->method_end(); ++first) {
  if (!first->isVirtual()) {
    continue;
  }
  llvm::outs() << first->getQualifiedNameAsString() << " " << first->getType().getAsString() << "\n";
}

out:

v_func void (void)
v_func2 void (int, class test::tmp)
~Foo void (void) noexcept
v_func2 void (int, class test::tmp)
v_func void (void)
~Bar void (void) noexcept

I checked the documentation for CXXRecordDecl and found nothing related to vtables

zcfh
  • 101
  • 1
  • 9

1 Answers1

1

When you're looking at the Clang AST, for example in CXXRecordDecl, you are seeing the information available in the compiler "front end", which includes the input syntax, static types, and other things that are specified in the C++ language standard.

However, the C++ standard does not require the existence of virtual function tables ("vtables") per se at all (virtual dispatch could be accomplished with some completely different mechanism, in principle), let alone their order. Instead, vtables are a feature of the Application Binary Interface (ABI), which specifies how various language features are implemented at the machine code data structure level. The ABI depends on the processor architecture.

A commonly used C++ ABI, even on x86_64, is the Itanium C++ ABI. Quoting its section on vtable components:

The order of the virtual function pointers in a virtual table is the order of declaration of the corresponding member functions in the class.

Therefore, if you are interested in the vtable order for a platform that uses that ABI, the order you see in the Clang AST is that order (although you need to read the full document, not just the bit I quoted, to get the full story).

If instead you want to hook into the process clang in particular uses to generate vtables, have a look at its VTableBuilder class. That class is part of the clang "back end", i.e., the part that generates machine code, meaning you'll have to engage the code generator (not just the parser) to use it.

Scott McPeak
  • 8,803
  • 2
  • 40
  • 79