2017-04-16 12 views
2

gcc -g을 사용하여 C 코드를 컴파일하면 gcc가 원본 소스 코드 (예 : 줄 번호)에 대한 참조를 포함하는 디버깅 정보를 삽입한다는 점을 이해합니다. 그런 다음 gdb 및 objdump와 같은 다른 프로그램은 나중에 이러한 참조를 복구 할 수 있습니다. 예를 들어, objdump -S을 사용하여 해당 소스 코드로 인터리브 된 어셈블리를 인쇄합니다.gcc -g 플래그 : 소스 코드 이동

내 목표는 컴파일 된 바이너리를 다른 컴퓨터에 복사하고이 디버그 정보를 계속 가져올 수있게하는 것입니다. 그러나 현재, 모든 디버깅 정보가 손실됩니다. 나는 원본 파일을 복사하는 데 신경 쓰지 않지만 두 번째 컴퓨터는 다른 OS를 실행하므로 파일 구조가 다르며 objdump를 찾을 수 없도록 정확히 동일한 절대 위치에 소스 파일을 배치 할 수 없습니다. 소스 코드. 나는 바이너리 보았다 이진의 무리와 함께 산재 다음과 같습니다 섹션 보았다 : 나는 소스에 새 경로에 맞게 편집을 시도

/home/path/to/source/code

을하지만 그것은 단지 바이너리 유효했다.

또한 그들 중 하나가 절대 경로 대신 소스 코드에 대한 상대 경로를 지정할 수 있기를 기대하면서 gcc flags을 연구했지만 그와 같은 것을 찾을 수 없었습니다.

참고로, 여기에 내가 objdump - S에서 얻을 수 있었으면 해요 출력의 종류는 다음과 같습니다

0804840b <main>: 
#include <stdio.h> 
int main(){ 
804840b:  8d 4c 24 04    lea 0x4(%esp),%ecx 
804840f:  83 e4 f0    and $0xfffffff0,%esp 
8048412:  ff 71 fc    pushl -0x4(%ecx) 
8048415:  55      push %ebp 
8048416:  89 e5     mov %esp,%ebp 
8048418:  51      push %ecx 
8048419:  83 ec 14    sub $0x14,%esp 
    for(int varName = 0; varName < 100; varName++){ 
804841c:  c7 45 f0 00 00 00 00 movl $0x0,-0x10(%ebp) 
8048423:  eb 32     jmp 8048457 <main+0x4c> 
    for(int innerLoop = 0; innerLoop < 30; innerLoop++){ 
8048425:  c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp) 
804842c:  eb 1f     jmp 804844d <main+0x42> 
     if(innerLoop == varName){ 
804842e:  8b 45 f4    mov -0xc(%ebp),%eax 
8048431:  3b 45 f0    cmp -0x10(%ebp),%eax 
8048434:  75 13     jne 8048449 <main+0x3e> 
     printf("%d\n", innerLoop); 
8048436:  83 ec 08    sub $0x8,%esp 
8048439:  ff 75 f4    pushl -0xc(%ebp) 
804843c:  68 f0 84 04 08   push $0x80484f0 
8048441:  e8 9a fe ff ff   call 80482e0 <[email protected]> 
8048446:  83 c4 10    add $0x10,%esp 
#include <stdio.h> 
int main(){ 
    for(int varName = 0; varName < 100; varName++){ 
    for(int innerLoop = 0; innerLoop < 30; innerLoop++){ 
8048449:  83 45 f4 01    addl $0x1,-0xc(%ebp) 
804844d:  83 7d f4 1d    cmpl $0x1d,-0xc(%ebp) 
8048451:  7e db     jle 804842e <main+0x23> 
#include <stdio.h> 
int main(){ 
    for(int varName = 0; varName < 100; varName++){ 
8048453:  83 45 f0 01    addl $0x1,-0x10(%ebp) 
8048457:  83 7d f0 63    cmpl $0x63,-0x10(%ebp) 
804845b:  7e c8     jle 8048425 <main+0x1a> 
804845d:  b8 00 00 00 00   mov $0x0,%eax 
     if(innerLoop == varName){ 
     printf("%d\n", innerLoop); 
     } 
    } 
    } 
} 

참고 : 나는 소스 파일에 대한 정보를 사용하는 프로그램의 예로서 objdump를 사용하지만, 그것은 내가 관심있는 objdump의 결과가 아닙니다. 나는이 동일한 정보에 대한 액세스가 필요한 다른 프로그램을 실행 중입니다. 문제는 objdump를 사용하는 방법이 아니라 바이너리를 수정하는 방법에 관한 것입니다.

+2

오브젝트 파일을 수정하는 일반적인 방법 인'objcopy'처럼 보이지 않습니다. 현재이 기능을 지원합니다. 그러나 gcc의'-fdebug-prefix-map' 옵션은 컴파일시에 원하는 것을 해줘야합니다. 'cc foo.c -g -fdebug-prefix-map = $ (pwd) =.'출력해야합니다'.'대신 DW_AT_comp_dir 속성에있는 현재 디렉토리의 경로명 (일반적으로 보이는 것)을 사용하십시오. 확인하기 위해'objdump -Wi foo'를 실행하십시오. –

+0

@MarkPlotnick 이것이 작동하는 것 같습니다, 감사합니다! 당신이 대답으로 그것을 넣으면 나는 그것을 받아 들일 것입니다. –

+0

어셈블러 코드를 얻기 위해'gcc -S -fverbose-asm' (아마도'-g' 및/또는'-O')과 함께 사용하는 것이 좋습니다. –

답변

2

gcc 및 clang은 디버그 정보를 생성 할 때 객체 파일의 각 컴파일 단위에 대한 작업 디렉토리에 DWARF 속성 DW_AT_comp_dir을 설정합니다.

cc a.c b.c -g -o foo 
objdump -Wi foo 

Contents of the .debug_info section: 

    Compilation Unit @ offset 0x0: 
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) 
    <11> DW_AT_name  : a.c 
    <15> DW_AT_comp_dir : (indirect string, offset: 0x0): /home/user/src 

    Compilation Unit @ offset 0x4d: 
<0><58>: Abbrev Number: 1 (DW_TAG_compile_unit) 
    <5e> DW_AT_name  : b.c 
    <62> DW_AT_comp_dir : (indirect string, offset: 0x0): /home/user/src 

일반적으로, 현재이 DWARF 속성 변경을 지원하지 않습니다 objcopy, 오브젝트 파일을 변환하는 데 사용되는 프로그램과 같이 표시됩니다.

그러나 gcc와 clang은 컴파일시에 원하는 것을 수행해야하는 -fdebug-prefix-map 옵션을 사용합니다. GCC가의 getcwd을과 libc 우선 (정확성을 확인 후) PWD 환경 변수를 사용 libiberty의 getpwd 기능을 사용하여 현재 디렉토리를 얻을 수 있기 때문에

, 우리는 쉘의 pwd -L 내장을 실행하여 같은 값을 얻을 수 있습니다. DW_AT_comp_dir 속성에 대신 현재 디렉토리의 경로 이름의

cc a.c b.c -g -fdebug-prefix-map=$(pwd -L)=. -o foo 

가 출력 .,.