Как разобрать одну функцию с помощью objdump?
у меня есть двоичный файл, установленный в моей системе, и я хотел бы посмотреть на разборку данной функции. Предпочтительно использовать objdump
, но другие решения также были бы приемлемыми.
С этот вопрос я узнал, что я мог бы разобрать часть кода, если бы знал только граничные адреса. От ответ я узнал, как превратить мои символы Split debug обратно в один файл.
но даже работая на этот единственный файл и даже разборка всего кода (т. е. без адреса запуска или остановки, но простой до 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,%rsp
A раздел или функции отделяется пустой строкой. Следовательно, изменение FS (разделитель полей) для новой строки и RS (запись Seperator) в два раза newline позволит вам легко найти рекомендуемую функцию, так как это просто найти в поле $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
полные имена символов to данное решение (версия D lang):
- введя
dasm test
и нажмите клавишу TabTab, вы получите список всех функций. - введя
dasm test m
и нажмите клавишу TabTab все функции, начиная с m будет показано, или в случае, если имеется только одна функция, это будут завершаются автоматически.
/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