Обратный инжиниринг кода виртуальных функций в C ++ - PullRequest
2 голосов
/ 25 июня 2011

Я только что скомпилировал следующее на VS2010 (с отключенной оптимизацией).

class Shape {
  public:
    int x,y;
    Shape() {
      x=10;
      y=20;
    }

    virtual void function1() {
      cout<<"function1";
    }

    virtual void function2() {
      cout<<"function2";
    }
};

int main() {
    Shape *s = new Shape();
    s->function1();
    s->function2();    
    return 0;
}

Разборка не показывает блоки кода, соответствующие виртуальным функциям или любым вызовам к ним, поэтому я предполагаю, что это из-за того, как виртуальные функции ищутся с использованием vftable. Я использую IDA Pro, поэтому он, вероятно, не может решить такие проблемы. Пожалуйста, поправьте меня, если я ошибаюсь.

У меня также есть несколько сомнений в этом отношении.

  1. Можно ли как-то просмотреть виртуальные функции так же, как другие функции во время разборки? Любой сценарий (IDAPython) / метод, который я мог бы использовать?
  2. Можно ли как-нибудь перечислить все виртуальные функции в исполняемом файле?
  3. Рекомендуемое чтение?

Ответы [ 4 ]

10 голосов
/ 25 июня 2011

Виртуальная диспетчеризация происходит только тогда, когда динамический тип объекта отличается от его статического типа (указатель на базу указывает на производный класс).Поскольку у вас даже нет наследования и точного типа на сайте вызовов, почему он должен выполнять поиск в vtable?

4 голосов
/ 25 июня 2011

Поскольку вы определили свои виртуальные функции внутри определения класса, я думаю, что ваши функции могут быть встроены компилятором, так как он знает точный тип на сайте вызова. Попробуйте переместить тела функций из тела класса. Они обязательно должны появиться в разборке. Я подозреваю, что в настоящий момент компоновщик может их заблокировать.

2 голосов
/ 25 июня 2011

Как уже отмечали другие: у вас нет наследования, поэтому компилятор умен, исключая виртуальную диспетчеризацию.

Рекомендуемое чтение: Страуструп «Дизайн и эволюция C ++».Он не будет отвечать на все ваши вопросы, но даст вам основу, чтобы помочь ответить на них или исследовать их ответ более эффективно.

1 голос
/ 25 июня 2011

У меня нет вашего компилятора, и это сильно зависит от компилятора и опций.В g ++ 4.5 с параметрами по умолчанию (и после исправления нескольких проблем в коде) я скомпилировал в ассемблер (g++ -S -o test.asm test.cpp) код, и он показывает функции и вызовы через механизм виртуальной диспетчеризации (в main)после вызова конструктора он извлекает vptr, смещает его и вызывает через значение в регистре).

Определение Shape :: function2 (обратите внимание, что .weak означает inline )

.globl __ZN5Shape9function2Ev
____.weak_definition __ZN5Shape9function2Ev
__ZN5Shape9function2Ev:
[...]

Определение Shape :: function1 (опять же, слабое означает inline )

.globl __ZN5Shape9function1Ev
____.weak_definition __ZN5Shape9function1Ev
__ZN5Shape9function1Ev:
[...]

Определение самого vtable для Shape:

.globl __ZTV5Shape
    .weak_definition __ZTV5Shape
    .section __DATA,__const_coal,coalesced
    .align 5
__ZTV5Shape:
    .quad   0
    .quad   __ZTI5Shape                # Ptr to type_info object
    .quad   __ZN5Shape9function1Ev     # vtable[0] is Shape::function1
    .quad   __ZN5Shape9function2Ev     # vtable[1] is Shape::function2

Определение main:

.globl _main
_main:
[...]
    movq    %rax, %rbx
    movq    %rbx, %rdi
    call    __ZN5ShapeC1Ev         # Call to constructor this will setup the vptr
    movq    %rbx, -24(%rbp)
    movq    -24(%rbp), %rax        # load **vptr into rax i.e. *vptr[0]: Shape::function1
    movq    (%rax), %rax
    movq    (%rax), %rax
    movq    -24(%rbp), %rdi
    call    *%rax                  # call it 

Что говорят другие, что компилятор можетполностью исключить виртуальную диспетчеризацию или встроить функцию, это правда.Эта версия g ++ не делает это для этого конкретного куска кода, но удаляет указатель (используя Shape со статической продолжительностью хранения)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...