C++: Learning virutal function at the low level

45 阅读1分钟

Great! Let’s walk through a working C++ virtual function example, and then see how you can inspect the vtable and vptr at the low level using g++, objdump, and gdb.


🧪 Step 1: Write and Compile a Sample C++ Program

main.cpp:

#include <iostream>
using namespace std;

class Base {
public:
    virtual void speak() {
        cout << "Base speaking" << endl;
    }
    virtual ~Base() = default;  // virtual destructor for safety
};

class Derived : public Base {
public:
    void speak() override {
        cout << "Derived speaking" << endl;
    }
};

int main() {
    Base* obj = new Derived();
    obj->speak();  // virtual call
    delete obj;
    return 0;
}

🧱 Compile it with symbols and no optimization:

g++ -g -O0 -o vtable_example main.cpp
  • -g: includes debug symbols for gdb
  • -O0: disables optimizations for clearer disassembly

🔍 Step 2: Disassemble with objdump

objdump -d vtable_example | less

Search for the function call in main. You should see something like this near main:

mov    rax,QWORD PTR [rbp-8]      ; load obj pointer
mov    rdx,QWORD PTR [rax]        ; load vptr from object
call   QWORD PTR [rdx]            ; indirect call (vtable)

This shows the vptr → vtable → function call chain.


🐞 Step 3: Inspect in gdb

Start:

gdb ./vtable_example

Then run and break:

(gdb) break main
(gdb) run

Step through to the call:

(gdb) next    # keep running until after object is created
(gdb) print obj
(gdb) print *(void**)obj          # print vptr
(gdb) x/2a *(void**)obj           # dump two vtable entries (addresses)

You’ll see the vtable addresses, which you can then reverse-lookup:

(gdb) info symbol 0xdeadbeef      # replace with actual address

You’ll see output like:

Derived::speak() in section .text

🎉 That confirms the function pointer from the vtable points to Derived::speak() — even though the pointer is of type Base*.


📌 Optional: Use readelf for vtable symbol info

readelf -s vtable_example | grep vtable

Shows symbol entries like:

VTT for Derived
vtable for Derived

✅ Summary

ToolPurpose
g++ -g -O0Compile with symbols, no optimizations
objdump -dDisassemble and see indirect calls
gdbExamine vptr and follow to vtable
readelfInspect symbols related to vtable layout

Let me know if you want me to create a virtual table diagram, or extend this to multiple inheritance or abstract classes!