Использование gdb для преобразования адресов в строки
У меня есть трассировка стека, созданная разделенным приложением, которая выглядит так:
*** Check failure stack trace: ***
@ 0x7f0e442d392d (unknown)
@ 0x7f0e442d7b1f (unknown)
@ 0x7f0e442d7067 (unknown)
@ 0x7f0e442d801d (unknown)
@ 0x7f0e457c55e6 (unknown)
@ 0x7f0e457c5696 (unknown)
@ 0x4e8765 (unknown)
@ 0x4a8b43 (unknown)
@ 0x7f0e43197ced (unknown)
@ 0x4a6889 (unknown)
И у меня есть незанятая версия исполняемого файла и все его библиотеки (скомпилированные с информацией об отладке). Но как я могу перевести адрес в файлы и номера строк?
Вот что я пробовал:
gdb
set solib-absolute-prefix /path/to/non-stripped/edition/of/root/filesystem/sysroot/
file /path/to/non-stripped/edition/of/root/filesystem/sysroot/usr/bin/my-buggy-app
info line *0x7f0e457c5696
Когда я ввожу команду file, она загружает только символы из файла, а не все библиотеки, которые используются. Есть ли способ сделать это?
Команда "info line" говорит:
Нет информации о номере линии для адреса 0x7f0e442d801d
Я предполагаю, что адрес находится в одной из разделяемых библиотек, но как я могу узнать, в каком из них?
Ответы
Ответ 1
Но как я могу перевести адрес в файлы и номера строк?
Для основного исполняемого файла (адреса типа 0x4e8765
) выполните следующее:
addr2line -e /path/to/non-stripped/.../my-buggy-app \
0x4a6889 0x4a8b43 0x4e8765
На самом деле вы можете вычесть 5
(обычную длину команды CALL
) из всех указанных выше адресов.
Для адресов в общих библиотеках вы должны знать адрес загрузки библиотеки.
Если ваше приложение создало файл core
, тогда (gdb) info shared
сообщит вам, где были загружены библиотеки.
Если вы не получили основной файл, и приложение не распечатало требуемое сопоставление, то
- вам следует исправить приложение, чтобы он распечатывал эту информацию (трассировка стека в основном бесполезна без него) и
- Вы все еще можете догадаться: посмотрите на код в исполняемом файле в
0x4e8760
- это должна быть инструкция CALL
для некоторой функции. Теперь узнайте, в какой библиотеке находится эта функция, и найдите ее адрес в библиотеке (через nm
). Если вам повезет, этот адрес близок к 0xNc56NN
. Теперь вы можете угадать адрес загрузки любой библиотеки в 0x7f0e457NNNNNN
. Повторите для 0x7f0e457c55e1
, и вы можете узнать адрес загрузки библиотеки в 0x7f0e442dNNNN
.
Ответ 2
Для OP команда в GDB для поиска исходной строки кода с адреса:
info line *0x10045740
Изменить: заменить "информационный символ 0x10045740", который не будет работать при определенных условиях (спасибо @Thomasa88).