Как разобрать одну единственную функцию с помощью objdump?
у меня есть двоичный файл, установленный в моей системе, и я хотел бы посмотреть на разборку данной функции. Предпочтительно с помощью objdump, но и другие решения были бы приемлемы.
из этих вопросов я узнал, что я мог бы разобрать часть кода, если бы знал только граничные адреса. Из этого ответа я узнал, как превратить мои разделенные символы отладки обратно в один файл.
но даже работая на одном файле, и даже разборка всего кода (т. е. без стартового или стоп-адреса, но простой до objdump), Я до сих пор не вижу этот символ нигде. Что имеет смысл, поскольку рассматриваемая функция статична, поэтому она не экспортируется. Тем не менее, valgrind сообщит имя функции, поэтому она должна быть сохранена где-то.
глядя на детали разделов отладки, я нахожу, что имя упоминается в , но я не знаю инструмент, который может превратить это в адрес диапазон.
6 ответов:
Я бы предложил использовать gdb как самый простой подход. Вы даже можете сделать это как один лайнер, например:
gdb -batch -ex 'file /bin/ls' -ex 'disassemble main'
gdb
disassemble/rsчтобы показать исходные и необработанные байты, а такжеС этим форматом, он становится очень близко к
objdump -Sвыход:gdb -batch -ex "file $EXECUTABLE" -ex "disassemble/rs $FUNCTION"а.с:
#include <assert.h> int myfunc(int i) { i = i + 2; i = i * 2; return i; } int main(void) { assert(myfunc(1) == 6); assert(myfunc(2) == 8); return 0; }компилировать и разбирать
gcc -std=c99 -O0 -g a.c gdb -batch -ex 'file a.out' -ex "disassemble/rs myfunc"разборки:
Dump of assembler code for function main: a.c: 1 int main(void) { 0x00000000004004d6 <+0>: 55 push %rbp 0x00000000004004d7 <+1>: 48 89 e5 mov %rsp,%rbp 2 int i; 3 i = 0; 0x00000000004004da <+4>: c7 45 fc 00 00 00 00 movl x0,-0x4(%rbp) 4 i = i + 2; 0x00000000004004e1 <+11>: 83 45 fc 02 addl x2,-0x4(%rbp) 5 i = i * 2; 0x00000000004004e5 <+15>: d1 65 fc shll -0x4(%rbp) 6 return 0; 0x00000000004004e8 <+18>: b8 00 00 00 00 mov x0,%eax 7 } 0x00000000004004ed <+23>: 5d pop %rbp 0x00000000004004ee <+24>: c3 retq End of assembler dump.протестировано на Ubuntu 16.04, GDB 7.11.1.
objdump + awk обходные пути
Распечатать абзац, как указано на: https://unix.stackexchange.com/questions/82944/how-to-grep-for-text-in-a-file-and-display-the-paragraph-that-has-the-text
objdump -d a.out | awk -v RS= '/^[[:xdigit:]]+ <FUNCTION>/'например:
objdump -d a.out | awk -v RS= '/^[[:xdigit:]]+ <myfunc>/'дает просто:
000000000000064a <myfunc>: 64a: 55 push %rbp 64b: 48 89 e5 mov %rsp,%rbp 64e: 89 7d fc mov %edi,-0x4(%rbp) 651: 83 45 fc 02 addl x2,-0x4(%rbp) 655: d1 65 fc shll -0x4(%rbp) 658: 8b 45 fc mov -0x4(%rbp),%eax 65b: 5d pop %rbp 65c: c3 retqпри использовании
-S, Я не думаю, что есть отказоустойчивый способ, так как комментарии кода могут содержать любую возможную последовательность... Но почти все время работает следующее:objdump -S a.out | awk '/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag'адаптировано из: Как выбрать линии между двумя шаблоны маркеров, которые могут возникать несколько раз с 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. Разобранный вывод выглядит как
000000000000068a <main>: 68a: 55 push %rbp 68b: 48 89 e5 mov %rsp,%rbp 68e: 48 83 ec 20 sub x20,%rspA раздел или функции отделяется пустой строкой. Следовательно, изменение FS (разделитель полей) на новую строку и RS (запись Seperator) в два раза новая строка позволит вам легко найти рекомендуемую функцию, так как это просто найти в поле $1!
objdump -d name_of_your_obj_file | awk -F"\n" -v RS="\n\n" ' ~ /main/'конечно, вы можете заменить main для любой функции, которую вы хотите вывести.
2. Bash Script
Я написал небольшой скрипт bash для этой проблемы. Просто скопируйте его и сохраните его как dasm файл.
#!/bin/bash # Author: abu # Description: puts disassembled objectfile to std-out if [ $# = 2 ]; then sstrg="^[[:xdigit:]]{2,}+.*<>:$" objdump -d | awk -F"\n" -v RS="\n\n" ' ~ /'"$sstrg"'/' elif [ $# = 1 ]; then objdump -d | awk -F"\n" -v RS="\n\n" '{ print }' else echo "You have to add argument(s)" echo "Usage: " " arg1 arg2" echo "Description: print disassembled label to std-out" echo " arg1: name of object file" echo " arg2: name of function to be disassembled" echo " " " arg1 ... print labels and their rel. addresses" fiизменить x-access и вызвать его, например:
chmod +x dasm ./dasm test mainэто много быстрее, чем вызов gdb со скриптом. Кроме того, используя objdump будет не загрузка библиотеки в память и поэтому безопаснее!
Виталий Фадеев запрограммировал автозаполнение для этого скрипта, что действительно хорошая функция и ускоряет ввод текста.
сценарий может быть нашел здесь.
это работает так же, как решение gdb (в том, что он сдвигает смещения к нулю), за исключением того, что он не отстает (получает работу примерно за 5 мс на моем ПК, тогда как решение gdb занимает около 150 мс):
objdump_func:
#!/bin/sh # -- function name; rest -- object files fn=; shift 1 exec objdump -d "$@" | awk " /^[[:xdigit:]].*<$fn>/,/^$/ { print $0 }" | awk -F: -F' ' 'NR==1 { offset=strtonum("0x"); print ; } NR!=1 { split(,a,":"); rhs=a[2]; n=strtonum("0x"); =sprintf("%x", n-offset); printf "%4s:%s\n", ,rhs }'
чтобы упростить использование awk для разбора вывода objdump относительно других ответов:
objdump -d filename | sed '/<functionName>:/,/^$/!d'
завершение Bash для
./dasmполные имена символов до данное решение (версия D lang):
- введя
dasm testи нажмите клавишу TabTab, вы получите список всех функций.- введя
dasm test mи нажмите клавишу TabTab все функции, начиная с m будет показано, или в случае, если имеется только одна функция, это будет автоматически завершена.File
/etc/bash_completion.d/dasm:# bash completion for dasm _dasm() { local cur=${COMP_WORDS[COMP_CWORD]} if [[ $COMP_CWORD -eq 1 ]] ; then # files COMPREPLY=( $( command ls *.o -F 2>/dev/null | grep "^$cur" ) ) elif [[ $COMP_CWORD -eq 2 ]] ; then # functions OBJFILE=${COMP_WORDS[COMP_CWORD-1]} COMPREPLY=( $( command nm --demangle=dlang $OBJFILE | grep " W " | cut -d " " -f 3 | tr "()" " " | grep "$cur" ) ) else COMPREPLY=($(compgen -W "" -- "$cur")); fi } complete -F _dasm dasm
Comments