В моей системе установлен двоичный файл, и я хотел бы посмотреть, как выполняется разборка данной функции. Предпочтительно использовать objdump
, но также будут приемлемы другие решения.
Из этих вопросов я узнал, что мог бы дизассемблировать часть кода, если бы мне были известны только граничные адреса. Из этого ответа я узнал, как превратить мои разделенные символы отладки обратно в один файл.
Но даже работая с этим единственным файлом и даже дизассемблируя весь код (то есть без начального или конечного адреса, но с обычным -d
параметром objdump
), я все равно нигде не вижу этого символа. Это имеет смысл, поскольку рассматриваемая функция статична и не экспортируется. Тем не менее, valgrind
он сообщит имя функции, поэтому его нужно где-то хранить.
Глядя на детали разделов отладки, я обнаружил, что это имя упоминается в .debug_str
разделе, но я не знаю инструмента, который мог бы превратить это в диапазон адресов.
static
, она может быть встроена компилятором в его сайты вызовов. Это может означать, что на самом деле может не быть никакой функции для разборки как таковой . Если вы можете найти символы для других функций, но не для функции, которую ищете, это сильный намек на то, что функция была встроена. Valgrind может по-прежнему ссылаться на исходную предварительно встроенную функцию, потому что отладочная информация файла ELF хранит источник каждой отдельной инструкции, даже если инструкции перемещены в другое место.addr2line
будет принимать ПК / IP-адресаstdin
и распечатывать соответствующие строки исходного кода. Точно так жеobjdump -l
будет смешивать objdump со строками исходного текста; хотя для высокооптимизированного кода с тяжелым встраиванием результаты любой программы не всегда особенно полезны.Ответы:
Я бы посоветовал использовать gdb как самый простой подход. Вы даже можете сделать это однострочно, например:
источник
-ex 'command'
не вman gdb
!? Но на самом деле он указан в документации по gdb . Также для других подобные вещи/bin/ls
могут быть удалены, поэтому, если эта точная команда ничего не отображает, попробуйте другой объект! Также можно указать файл / объект как аргумент без слов; например,gdb -batch -ex 'disassemble main' /bin/ls
gdb /bin/ls -batch -ex 'disassemble main'
тоже работаетcolumn -ts$'\t'
для фильтрации вывода GDB, у вас будут хорошо выровнены необработанные байты и исходные столбцы. Кроме того,-ex 'set disassembly-flavor intel'
перед другими-ex
s приведет к синтаксису сборки Intel.disassemble fn
используя метод, описанный выше. Но кажется, что когда в двоичном файле есть несколько функций с одинаковым именем, дизассемблируется только одна. Можно ли их все разобрать, или я должен разбирать их по необработанному адресу?gdb
disassemble/rs
для отображения исходных и необработанных байтовВ этом формате он действительно приближается к
objdump -S
выводу:main.c
Скомпилировать и разобрать
Разборка:
Проверено на Ubuntu 16.04, GDB 7.11.1.
objdump + awk обходные пути
Распечатайте абзац, как указано здесь: /unix/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the -текст
например:
дает только:
При использовании
-S
я не думаю, что существует отказоустойчивый способ, поскольку комментарии к коду могут содержать любую возможную последовательность ... Но следующее работает почти всегда:адаптировано из: Как выбрать строки между двумя шаблонами маркеров, которые могут встречаться несколько раз с awk / sed
Ответы на рассылку
В списке рассылки 2010 года есть ветка, в которой говорится, что это невозможно: https://sourceware.org/ml/binutils/2010-04/msg00445.html
Помимо
gdb
обходного пути, предложенного Томом, они также комментируют другой (худший) обходной путь компиляции, при-ffunction-section
котором помещается одна функция в раздел, а затем выполняется дамп раздела.Николас Клифтон дал ему WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html , вероятно, потому, что обходной путь GDB охватывает этот вариант использования.
источник
Разберите одну единственную функцию с помощью Objdump
У меня есть два решения:
1. На основе командной строки
Этот метод отлично работает и дополняет простой. Я использую objdump с -d флага и трубами его через AWK . Вывод в разобранном виде выглядит как
Для начала я начну с описания вывода objdump. Раздел или функция отделена пустой строкой. Поэтому изменение FS (разделитель полей) на новую строку и RS (разделитель записей) на двойной перевод строки позволяет вам легко искать рекомендуемую функцию, поскольку ее просто найти в поле $ 1!
Конечно, вы можете заменить main любой другой функцией, которую хотите распечатать.
2. Bash Script
Я написал небольшой сценарий на bash для решения этой проблемы. Вставьте и скопируйте его и сохраните, например, как файл dasm .
Измените x-доступ и вызовите его, например:
Это намного быстрее, чем вызов GDB со скриптом. Кроме того, использование objdump не загружает библиотеки в память и, следовательно, безопаснее!
Виталий Фадеев запрограммировал автозаполнение для этого скрипта, что действительно приятно и ускоряет набор текста.
Скрипт можно найти здесь .
источник
objdump
илиgdb
быстрее. Поскольку огромный двоичный файл (Firefox libxul.so)objdump
занимает вечность, я отменил его через час, а этоgdb
займет меньше минуты.Чтобы упростить использование awk для анализа вывода objdump относительно других ответов:
источник
Это работает так же, как решение gdb (в том, что оно сдвигает смещения в сторону нуля), за исключением того, что оно не тормозит (выполняет работу примерно за 5 мс на моем ПК, тогда как решение gdb занимает около 150 мс):
objdump_func:
источник
awk
делает первая ), была единственной функцией в объектном файле, то есть даже если функция начинается, скажем0x2d
, с второго awk, она сдвинется в сторону0x00
(вычитая0x2d
от адреса каждой инструкции), что полезно, потому что ассемблерный код часто делает ссылки относительно начала функции, и если функция начинается с 0, вам не нужно делать вычитания в уме. Код awk мог бы быть лучше, но, по крайней мере, он выполняет свою работу и достаточно эффективен.-ffunction-sections
- это более простой способ убедиться, что каждая функция начинается с 0.Если у вас установлена последняя версия binutils (2.32+), это очень просто.
При переходе
--disassemble=SYMBOL
к objdump будет дизассемблирована только указанная функция. Не нужно передавать начальный и конечный адреса.LLVM objdump также имеет аналогичную опцию (
--disassemble-symbols
).источник
Завершение Bash для
./dasm
Полные имена символов для этого решения (версия на языке D):
dasm test
а затем нажав TabTab, вы получите список всех функций.dasm test m
и последующем нажатии будут показаны TabTab все функции, начинающиеся с m , или, если существует только одна функция, она будет заполнена автоматически.Файл
/etc/bash_completion.d/dasm
:источник