Как отладить сбойную программу Linux по ее обратной трассировке glibc/malloc (ядро недоступно)?

У меня есть приложение C++, работающее на удаленном сервере. Недавно я представил много нового кода. Опасаясь сбоев, я установил ulimit -c unlimited и через некоторое время у меня произошел сбой с дампом ядра, который помог мне отладить проблему. По бизнес-причинам работающий двоичный файл не имеет символов отладки, но у меня на компьютере есть двоичный файл with-symbols, поэтому отладка была легкой задачей.

Сегодня обновленный сервис снова дал сбой, к сожалению, на этот раз он не создал дамп ядра (старый файл core все еще был там, нетронутый, я думаю, это может быть какое-то ожидаемое поведение). На этот раз сбой произошел во внутренностях realloc(), поэтому он представил мне эту трассировку стека для stdout:

*** Error in `./MyApp': corrupted double-linked list: 0x0000000003a04940 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f05ed2897e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7e6ed)[0x7f05ed2906ed]
/lib/x86_64-linux-gnu/libc.so.6(+0x81cde)[0x7f05ed293cde]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f05ed296184]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x358)[0x7f05ed296a18]
./MyApp[0x453f58]
./MyApp[0x454a42]
./MyApp[0x457cd6]
./MyApp[0x45eb19]
./MyApp[0x49cfd7]
./MyApp[0x49707b]
./MyApp[0x70734e]
...
a lot more lines
...
./MyApp[0x664c65]
./MyApp[0x73e7b2]
./MyApp[0x70d849]
./MyApp[0x783af4]
./MyApp[0x425da8]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f05ed232830]
./MyApp[0x43a0c9]
======= Memory map: ========
...
< a huge table of memory mappings, ending with: >
Aborted (core dumped)

Как указано выше, основной файл не изменился по сравнению с предыдущим сбоем, поэтому его нельзя использовать.

Мне было интересно, могу ли я использовать эту трассировку стека, чтобы вручную выяснить, какая функция вызвала realloc(), которая все разрушила. Я попробовал addr2line, используя указанные адреса, но чувствую, что это отправляет меня не туда, так как они совершенно неуместны. Вероятно, мне следует каким-то образом использовать карту памяти, которую я не понимаю и не смог выяснить после некоторого поиска в Google. Есть ли руководство по использованию этого типа трассировки стека?


person anrieff    schedule 15.11.2018    source источник
comment
эти адреса выровнены рандомизатором памяти? Вы пробовали искать инструкции по вызову в objdump?   -  person kerrytazi    schedule 15.11.2018
comment
Вау, да, это решило это. Я пропустил двоичный файл with-symbols через objdump, адреса из этой трассировки стека совпадают с адресами из objdump, теперь трассировка стека имеет смысл. Большое спасибо! Не стесняйтесь превратить ваше предложение objdump в ответ :)   -  person anrieff    schedule 15.11.2018


Ответы (1)


objdump — одна классная программа из набора инструментов GNU, которая может показать вам информацию о двоичном файле. связанные библиотеки, выравнивание памяти, таблицы функций и многое другое.

Обычное использование:
objdump -T <file>

Есть еще несколько инструментов, которые могут вам помочь. например nm или readelf (для файлов эльфов).

nm -g -C <file>
readelf -sW <file>

person kerrytazi    schedule 15.11.2018
comment
Как упоминалось в комментариях, objdump декодировал все инструкции в моем двоичном файле with-symbol, и поиск адресов из трассировки стека realloc совпал с точными инструкциями, которые я ожидал; по какой-то причине addr2line давал вводящие в заблуждение результаты, вероятно, потому, что мой двоичный файл скомпилирован с -O2. - person anrieff; 15.11.2018