내 시스템에 바이너리가 설치되어 있으며 주어진 함수의 분해를보고 싶습니다. 선호하는 사용objdump
것이 좋지만 다른 솔루션도 사용할 수 있습니다.
에서 이 질문에 나는 단지 경계 주소를 알고 있다면 내가 코드의 분해 부분 수있을 것을 배웠다. 이 답변 에서 분할 디버그 기호를 단일 파일로 다시 바꾸는 방법을 배웠습니다.
그러나 해당 단일 파일에서 작동하고 모든 코드를 분해하더라도 (즉, 시작 또는 중지 주소없이 일반 -d
매개 변수를으로 objdump
) 여전히 해당 기호를 볼 수 없습니다. 문제의 함수가 정적이므로 내 보내지 않는 한 의미가 있습니다. 그럼에도 불구하고 valgrind
함수 이름을보고하므로 어딘가에 저장해야합니다.
디버그 섹션의 세부 사항을 살펴보면 섹션에서 언급 한 이름을 찾았 .debug_str
지만이를 주소 범위로 바꿀 수있는 도구를 모릅니다.
답변
가장 간단한 방법으로 gdb를 사용하는 것이 좋습니다. 다음과 같이 한 줄로 할 수도 있습니다.
gdb -batch -ex 'file /bin/ls' -ex 'disassemble main'
답변
disassemble/rs
소스 및 원시 바이트도 표시하는 gdb
이 형식을 사용하면 objdump -S
출력에 매우 가깝습니다 .
gdb -batch -ex "disassemble/rs $FUNCTION" "$EXECUTABLE"
main.c
#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 -O0 -ggdb3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
gdb -batch -ex "disassemble/rs myfunc" main.out
분해 :
Dump of assembler code for function myfunc:
main.c:
3 int myfunc(int i) {
0x0000000000001135 <+0>: 55 push %rbp
0x0000000000001136 <+1>: 48 89 e5 mov %rsp,%rbp
0x0000000000001139 <+4>: 89 7d fc mov %edi,-0x4(%rbp)
4 i = i + 2;
0x000000000000113c <+7>: 83 45 fc 02 addl $0x2,-0x4(%rbp)
5 i = i * 2;
0x0000000000001140 <+11>: d1 65 fc shll -0x4(%rbp)
6 return i;
0x0000000000001143 <+14>: 8b 45 fc mov -0x4(%rbp),%eax
7 }
0x0000000000001146 <+17>: 5d pop %rbp
0x0000000000001147 <+18>: c3 retq
End of assembler dump.
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에 언급 된대로 단락을 인쇄합니다. -본문
objdump -d main.out | awk -v RS= '/^[[:xdigit:]]+ <FUNCTION>/'
예 :
objdump -d main.out | awk -v RS= '/^[[:xdigit:]]+ <myfunc>/'
다음을 제공합니다.
0000000000001135 <myfunc>:
1135: 55 push %rbp
1136: 48 89 e5 mov %rsp,%rbp
1139: 89 7d fc mov %edi,-0x4(%rbp)
113c: 83 45 fc 02 addl $0x2,-0x4(%rbp)
1140: d1 65 fc shll -0x4(%rbp)
1143: 8b 45 fc mov -0x4(%rbp),%eax
1146: 5d pop %rbp
1147: c3 retq
를 사용할 때 -S
코드 주석에 가능한 시퀀스가 포함될 수 있으므로 오류 방지 방법이 없다고 생각합니다.하지만 다음은 거의 항상 작동합니다.
objdump -S main.out | awk '/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag'
적응 : awk / sed로 여러 번 나타날 수있는 두 마커 패턴 사이의 선을 선택하는 방법
메일 링리스트 답장
메일 링리스트에 불가능하다고 말하는 2010 스레드가 있습니다 : https://sourceware.org/ml/binutils/2010-04/msg00445.html
gdb
Tom이 제안한 해결 방법 외에도 -ffunction-section
섹션 당 하나의 함수를 넣은 다음 섹션을 덤프하는 컴파일의 또 다른 (더 나쁜) 해결 방법에 대해서도 설명 합니다.
Nicolas Clifton이 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 $0x20,%rsp
우선 objdump 출력에 대한 설명부터 시작합니다. 부 또는 기능은 빈 라인으로 분리된다. 따라서 FS (Field Separator)를 개행으로 변경하고 RS (Record Separator)를 두 번 개행으로 변경하면 단순히 $ 1 필드 내에서 찾기 만하면 추천 기능을 쉽게 검색 할 수 있습니다!
objdump -d name_of_your_obj_file | awk -F"\n" -v RS="\n\n" '$1 ~ /main/'
물론 메인 을 교체 할 수 있습니다. 을 인쇄하려는 다른 기능으로 있습니다.
2. Bash 스크립트
이 문제에 대한 작은 bash 스크립트를 작성했습니다. 붙여넣고 복사 한 후 예를 들어 dasm 파일 로 저장 합니다.
#!/bin/bash
# Author: abu
# filename: dasm
# Description: puts disassembled objectfile to std-out
if [ $# = 2 ]; then
sstrg="^[[:xdigit:]]{2,}+.*<$2>:$"
objdump -d $1 | awk -F"\n" -v RS="\n\n" '$1 ~ /'"$sstrg"'/'
elif [ $# = 1 ]; then
objdump -d $1 | awk -F"\n" -v RS="\n\n" '{ print $1 }'
else
echo "You have to add argument(s)"
echo "Usage: "$0 " 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 " "$0 " arg1 ... print labels and their rel. addresses"
fi
x-access를 변경하고 다음 과 같이 호출하십시오.
chmod +x dasm
./dasm test main
이것은 스크립트로 gdb를 호출하는 것보다 훨씬 빠릅니다. objdump를 사용하는 방법 외에도 라이브러리를 메모리에로드 하지 않으므로 더 안전합니다!
Vitaly Fadeev 는이 스크립트에 자동 완성 기능을 프로그래밍했습니다. 이것은 정말 멋진 기능이며 타이핑 속도를 높여줍니다.
답변
다른 답변과 관련하여 objdump의 출력을 구문 분석하기 위해 awk 사용을 단순화하려면 다음을 수행하십시오.
objdump -d filename | sed '/<functionName>:/,/^$/!d'
답변
이것은 gdb 솔루션과 똑같이 작동합니다 (오프셋을 0으로 이동한다는 점에서).
objdump_func :
#!/bin/sh
# $1 -- function name; rest -- object files
fn=$1; shift 1
exec objdump -d "$@" |
awk " /^[[:xdigit:]].*<$fn>/,/^\$/ { print \$0 }" |
awk -F: -F' ' 'NR==1 { offset=strtonum("0x"$1); print $0; }
NR!=1 { split($0,a,":"); rhs=a[2]; n=strtonum("0x"$1); $1=sprintf("%x", n-offset); printf "%4s:%s\n", $1,rhs }'
답변
최신 binutils (2.32+)가 있다면 이것은 매우 간단합니다.
--disassemble=SYMBOL
objdump에 전달 하면 지정된 함수 만 디스 어셈블됩니다. 시작 주소와 끝 주소를 전달할 필요가 없습니다.
LLVM objdump에도 유사한 옵션 ( --disassemble-symbols
)이 있습니다.
답변
배시 완성 ./dasm
이 솔루션 에 대한 전체 기호 이름 (D lang 버전) :
- 입력
dasm test
한 다음를 누르면 TabTab모든 기능 목록이 표시됩니다. - 입력
dasm test m
후 m으로TabTab 시작하는 모든 기능 이 표시되거나 기능이 하나만있는 경우 자동 완성됩니다.
파일 /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