Segfault: и разборки различаются между objdump и gdb

[Глубокий вдох.] У нас есть приложение, которое выводит окно с использованием WxMotif 2.6.3 (библиотека GUI не была - и не является - моим выбором). Он отлично работает на 32-разрядных системах ix86. У меня была задача конвертировать его в 64-битное приложение. Это всегда seg-faults. Я нахожусь на RHEL 6, поэтому я скомпилировал gcc 4.4.7. После многого скрежещения зубов проблема кажется очевидной: в wxFrame:: DoCreate, m_mainWidget установлен (правильно); в wxFrame:: GetMainWidget, он возвращается как нулевой указатель. Нулевой указатель приводит к сбою. Используя gdb, команда, которая устанавливает m_mainWidget,

mov    %rax,0x1e0(%rdx) # $rdx = 0x68b2f0

тогда как код, который получает m_mainWidget,

mov    0x1f0(%rax),%rax # $rax = 0x68b2f0

В gdb я могу проверить память и увидеть, что указатель на 0x68b4d0 верен. Почему неправильное смещение?

Чтобы еще больше запутать вещи, когда я использую objdump для дизассемблирования libwx_motifd_core-2.6.so.0.3.1, сборка "получить"

  mov    0x1e0(%rax),%rax

В objdump, как get, так и set используют 0x1e0 в качестве смещения. Что происходит?

Я загрузил некоторую релевантную информацию здесь: GitHub

Я включил небольшую программу, которая реплицирует проблему в моей системе.

Изучая далее, я вижу в разборке wxFrame:: DoCreate, который далее использует m_mainWidget для получения значения с использованием 0x1e0 в качестве смещения (разборка выполняется в компиляции, где я использовал -O0, поэтому код должен вернуться назад в память каждый раз). "Just for Fun", я добавил новую переменную-член в wxFrame-m_myMainWidget и установил ее сразу после установки m_mainWidget. Затем я получил wxFrame:: GetMainWidget(), чтобы вернуть локальное значение (m_myMainWidget). Разве вы не знаете об этом: Сбой все еще происходит, и GetMainWidget содержит то же смещение +16, когда я разбираюсь изнутри gdb. (Смещение не там, где я использую objdump для демонтажа.)

Ответ 1

Основываясь на комментарии @Igor, я просмотрел макеты классов, используя опцию -fdump-class-hierarchy. Оказывается, что действительно существует несоответствие макета vtable из-за этого условного блока в include/wx/app.h:

#ifdef __WXDEBUG__
    virtual void OnAssert(const wxChar *file,
                          int line,
                          const wxChar *cond,
                          const wxChar *msg);
#endif // __WXDEBUG__

Вам нужно убедиться, что вы скомпилируете свой код с тем же значением __WXDEBUG__.