2014-03-31 2 views
46

시스템에 바이너리가 설치되어 있으며, 주어진 함수의 디스 어셈블리를보고 싶습니다. 바람직하게는 objdump을 사용하지만, 다른 해결책도 또한 허용 될 수있다.objdump를 사용하여 하나의 함수를 분해하십시오.

this questions 경계 주소 만 알면 코드의 일부를 분해 할 수 있다는 것을 알게되었습니다. this answer에서 분할 디버그 기호를 다시 단일 파일로 변환하는 방법을 배웠습니다.

심지어 단일 파일에서 작동하고 모든 코드를 분해 (즉, 시작 또는 중지 주소가 없지만 -d 매개 변수는 objdump) 매개 변수로 설정하더라도 그 기호는 어디에도 표시되지 않습니다. 문제의 함수가 정적이기 때문에 어떤 의미를 가지므로 내 보낸 것이 아닙니다. 그럼에도 불구하고 valgrind은 함수 이름을보고하므로 어딘가에 저장해야합니다.

디버그 섹션의 세부 정보를 보면 .debug_str 섹션에 언급 된 이름이 있지만 주소 범위로 바꿀 수있는 도구를 알지 못합니다.

+0

사소한 보조 노트 : 함수는'static' 표시되어 있으면 컴파일러에서 호출 사이트로 인라인 될 수 있습니다.이것은 실제로 분해 할 수있는 기능이 없을 수도 있음을 의미합니다. 찾고있는 함수가 아닌 다른 함수의 기호를 찾아 낼 수 있다면 함수가 인라인되었음을 알리는 강력한 힌트입니다. Valgrind는 ELF 파일 디버깅 정보가 지침이 다른 곳으로 옮겨 졌더라도 각 개별 명령의 출처를 저장하기 때문에 원래의 사전 인라인 함수를 계속 참조 할 수 있습니다. – davidg

+0

@ davidg : true이지만, Tom의 답변이이 경우에 효과가있어이 경우가 아닌 것 같습니다. 그럼에도 불구하고 예를 들어 어셈블리 코드에 각 명령어의 출처에 대한 정보를 주석으로 추가 하시겠습니까? – MvG

+1

좋은 소식입니다! 'addr2line'은'stdin'으로부터 PC/IP를 받아들이고 해당 소스 코드 행을 출력합니다. 비슷하게,'objdump -l'은 objdump를 소스 라인과 섞을 것입니다; 무거운 인라인이있는 고도로 최적화 된 코드의 경우, 두 프로그램의 결과가 항상 도움이되는 것은 아닙니다. – davidg

답변

47

가장 간단한 접근 방법으로 gdb를 사용하는 것이 좋습니다. 당신처럼, 한 - 라이너로 할도 수 :

gdb -batch -ex 'file /bin/ls' -ex 'disassemble main' 
+2

문서화되지 않은 기능 +1! '-ex 'command''는 ['man gdb']에 없습니다 (http://linux.die.net/man/1/gdb) !? 그러나 실제로 [gdb docs] (http://sourceware.org/gdb/current/onlinedocs/gdb/gdb-man.html#gdb-man)에 나와 있습니다. 또한 다른 사람들은'/ bin/ls' 같은 것들을 벗겨 낼 수도 있습니다. 그래서 정확한 명령이 아무것도 표시하지 않는다면 다른 객체를 시도하십시오! bareword 인수로 파일/객체를 지정할 수도 있습니다. 예 :'gdb -batch -ex 'main'/ bin/ls'을 역 어셈블하십시오. –

+1

맨 페이지가 정확하지 않습니다. 오랜 시간 동안은 실제로 유지 관리되지 않았지만 이제는 주요 문서에서 생성 된 것 같습니다. 또한 "gdb --help"가 이제 더 완전합니다. –

+2

'gdb/bin/ls -batch -ex '는 main''도 잘 분해합니다. – stefanct

7

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>/' 

-S을 사용하여, 내가 돈 ' 코드 주석에는 가능한 모든 시퀀스가 ​​포함될 수 있으므로 오류가없는 방식으로 생각하면됩니다. 그러나 다음은 거의 항상 작동합니다.

objdump -S a.out | awk '/^[[:xdigit:]]+ <FUNCTION>:$/{flag=1;next}/^[[:xdigit:]]+ <.*>:$/{flag=0}flag' 
는 에서 적응

: How to select lines between two marker patterns which may occur multiple times with awk/sed

메일 링리스트는

가 그것을 말한다 메일 링리스트에 2010 스레드 수없는 응답 : 톰에 의해 제안 된 gdb 해결 게다가 https://sourceware.org/ml/binutils/2010-04/msg00445.html

, 그들은 섹션 당 하나의 함수를 넣은 다음 섹션을 덤프하는 -ffunction-section으로 컴파일하는 또 다른 (더 나쁜) 해결 방법에 대해 의견을 제시합니다.

Nicolas Clifton이 WONTFIX https://sourceware.org/ml/binutils/2015-07/msg00004.html을주었습니다. GDB의 해결 방법이 해당 사례를 다루고 있기 때문일 수 있습니다.

+0

gdb 접근법은 공유 라이브러리와 오브젝트 파일에서 잘 작동합니다. –

+0

@TomTromey 지적 해 주셔서 고맙습니다. –

3

이는 랙이 아니다 것을 제외하고 단지 (제로 향해 오프셋을 이동한다는 점에서) gdb를 솔루션처럼 작동합니다 (GDB 솔루션은 약 150ms의 소요 반면, 내 PC에 대한 5ms의에서 일을 얻는다) :

objdump_func :

#!/bin/sh 
# $1 -- function name; rest -- object files 
fn=$1; shift 1 
exec objdump -d "[email protected]" | 
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 }' 
+0

지금은 테스트 할 수 없지만이 문제가 언제 풀릴 지 기대하고 있습니다. 당신은 "교대가 0으로 오프셋"측면에 대해 좀 더 자세히 설명 할 수 있습니까? 여기서 gdb 해답을 명시 적으로 보지 못했습니다. 실제로 거기에서 진행되는 작업과 그 이유에 대해 좀 더 알고 싶습니다. – MvG

+0

기본적으로 목표로하는 함수 (첫 번째 'awk'이하는 것)가 객체 파일의 유일한 함수 인 것처럼 보이게합니다. 즉 함수가 '0x2d'에서 시작 되더라도 두 번째 awk '0x00' (각 명령의 주소에서'0x2d'를 뺀 것)로 이동합니다. 이는 어셈블리 코드가 종종 함수의 시작을 기준으로 참조를 만들고 함수가 0에서 시작하면 유용하지 않기 때문에 유용합니다 당신의 머리에서 뺄셈을해야합니다. awk 코드는 더 좋을 수도 있지만 최소한 일을하고 상당히 효율적입니다. – PSkocik

1

는 다른 답변에 objdump를의 출력 상대를 구문 분석 AWK의 사용을 단순화하기 위해 :

objdump -d filename | sed '/<functionName>:/,/^$/!d' 
관련 문제