Подтвердить что ты не робот

Использование 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

Я предполагаю, что адрес находится в одной из разделяемых библиотек, но как я могу узнать, в каком из них?

4b9b3361

Ответ 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).