Как напечатать виртуальную функцию VTable по определенному адресу при отладке с помощью GDB - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь напечатать с помощью 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

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

1 Ответ

0 голосов
/ 07 января 2019

Вам нужно загрузить указатель на функцию из таблицы. Предполагая, что 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()>

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

...