gdb пропускает инструкции

У меня ограниченный опыт работы с gdb и отладкой общих объектов в целом, поэтому мне интересно, может ли кто-нибудь пролить свет на поведение, которое я вижу.

В основном я пытаюсь понять внутренности плохо документированной библиотеки. С этой целью я написал программу, которая минимально использует библиотеку, и я пытаюсь пройти через нее, чтобы увидеть, что происходит.

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

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

В случае, если это уместно: я отлаживаю трехстрочную программу, которую я написал, которая динамически связывается с интересующей библиотекой. У меня есть исходный код библиотеки, но он сложный, поэтому я надеялся, что gdb прольет свет на некоторые вещи.

Заранее спасибо!


person Joshua Gevirtz    schedule 15.01.2019    source источник
comment
Какие варианты оптимизации вы используете? Чем больше оптимизация, тем сложнее использовать отладчик.   -  person Shawn    schedule 16.01.2019
comment
Вы пытаетесь выполнить оптимизированный код C++ в gdb? Это было бы супер запутанно.   -  person SergeyA    schedule 16.01.2019
comment
@Shawn Глядя на сценарий сборки для рассматриваемой библиотеки, видно, что установка их параметра DEBUG в значение true означает, что используется -O0.   -  person Joshua Gevirtz    schedule 16.01.2019
comment
@Шон Неважно! Я неправильно использовал скрипт сборки. Я только что перестроил и правильно установил параметр отладки, поэтому кажется, что оптимизация сейчас отключена.   -  person Joshua Gevirtz    schedule 16.01.2019
comment
Если кто-то захочет опубликовать ответ об оптимизации, я отмечу его как правильный. Благодаря тонну!   -  person Joshua Gevirtz    schedule 16.01.2019


Ответы (2)


Я думал, что gbd все еще может выполнять инструкции

Можно, но для этого используется команда stepi, а не step, которую вы используете.

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

person Employed Russian    schedule 15.01.2019

Немного об оптимизациях

Например, это код C:

int main(int argc, char** argv) {
  printf("Hello World\n");
  return 0;
}

При сборке с параметром -O0 оптимизация кода почти не выполняется, и код работает очень медленно. Это неоптимизированный код (gcc -m32):

; Variables:
        ;    arg_4: 12
        ;    arg_0: 8
        ;    var_4: -4
        ;    var_8: -8
        ;    var_C: -12
        ;    var_10: -16
        ;    var_18: -24
push       ebp
mov        ebp, esp
sub        esp, 0x18
call       _main+11
pop        eax                            ; CODE XREF=_main+6

-- These lines are gone after optimization --
mov        ecx, dword [ebp+arg_4]
mov        edx, dword [ebp+arg_0]
--                                    --
lea        eax, dword [eax-0x1f5b+0x1fa6] ; "Hello World!\\n"

-- There lines are gone after optimization --
mov        dword [ebp+var_4], 0x0
mov        dword [ebp+var_8], edx
mov        dword [ebp+var_C], ecx

mov        dword [esp+0x18+var_18], eax  ; method imp___symbol_stub__printf
call       imp___symbol_stub__printf
xor        ecx, ecx                           
mov        dword [ebp+var_10], eax
mov        eax, ecx                                    
add        esp, 0x18                           
pop        ebp
ret

Когда вы строите с -03, вы заметите, что строк меньше. Оптимизированный код (gcc -m32 -O3):

push       ebp
mov        ebp, esp
sub        esp, 0x8
call       _main+11
pop        eax                             ; CODE XREF=_main+6
lea        eax, dword [eax-0x1f6b+0x1f9e]  ; "Hello World!"
mov        dword [esp+0x8+var_8], eax      ; "%s" for imp___symbol_stub__puts
call       imp___symbol_stub__puts
xor        eax, eax
add        esp, 0x8
pop        eep
ret

Причина, по которой неоптимизированный код имеет ненужные строки, заключается в том, что main принимает два аргумента и сохраняет их в регистрах независимо от того, используете ли вы оптимизацию или нет, но с оптимизацией компилятор удаляет эти инструкции перемещения, потому что аргументы не используются и не нужны. Точно так же значения регистров также сохраняются в переменных стека, поскольку аргументы копируются в переменные стека.

person Tyson90    schedule 18.01.2019