Как распечатать виртуальную функцию VTable по определенному адресу при отладке с помощью GDB

Я пытаюсь напечатать с помощью GDB Debugger имя виртуальной функции, которая существует в VTable по определенному адресу памяти.

Вот мой простой код:

#include <iostream>
class Parent {
 public:
  virtual void Foo() {}
  virtual void FooNotOverridden() {}
};

class Derived : public Parent {
 public:
  void Foo() override {}
};

int main() {
  Parent p1, p2;
  Derived d1, d2;

  std::cout << "done" << std::endl;
}

Вот следующая информация о gdb

0x8201d18 vtable for Derived:   0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x8201d20 vtable for Derived+8:     0x58    0x1d    0x20    0x08    0x00    0x00    0x00    0x00
0x8201d28 vtable for Derived+16:    0x8e    0x0c    0x00    0x08    0x00    0x00    0x00    0x00
0x8201d30 vtable for Derived+24:    0x82    0x0c    0x00    0x08    0x00    0x00    0x00    0x00
0x8201d38 vtable for Parent:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x8201d40 vtable for Parent+8 : 0x70    0x1d    0x20    0x08    0x00    0x00    0x00    0x00
0x8201d48 vtable for Parent+16 :    0x76    0x0c    0x00    0x08    0x00    0x00    0x00    0x00
0x8201d50 vtable for Parent+24 :    0x82    0x0c    0x00    0x08    0x00    0x00    0x00    0x00

а теперь с помощью следующей команды

info symbol 0x8201d8e

я получил это сообщение

_DYNAMIC + 14 in section .dynamic of .../.../Mypath/MyProject 

Согласно моему небольшому опыту, при смещении +8 это будет указатель на VTABLE, а при смещении +16 это будет указатель на первый метод, который существует внутри VTABLE. Итак, если я получил значение адреса 0x8201d28, которое равно 0x8201d8e, я ожидайте от отладчика вывода, подобного этому

_DYNAMIC + 14 in section .dynamic of .../.../Mypath/MyProject 
 Derived::Foo() in section .text of a.out

и распечатайте имя функции. Но моя проблема в том, что отладчик не печатает имя виртуальной функции. Я так смущен, что оно должно быть там. Что я там не так делаю?


person Mixalis Navridis    schedule 07.01.2019    source источник


Ответы (1)


Вам нужно загрузить указатель на функцию из vtable. Предполагая, что vtable находится по адресу 0x555555755d48

(gdb) info symbol 0x0000555555755d48
vtable for Derived in section .data.rel.ro of /tmp/a.out

Я могу получить имя виртуальной функции следующим образом:

(gdb) print ((void **)0x0000555555755d48)[2]
$3 = (void *) 0x555555554bca <Derived::Foo()>

Очевидно, для этого потребуется отладочная информация. Экспортируемые vtables не включают имена, потому что они идентифицируются только по смещению (даже если у экспортируемых функций есть имена).

person Florian Weimer    schedule 07.01.2019