GDB에 코어 덤프뿐만 아니라 실행 파일이 필요한 이유는 무엇입니까?


11

코어 덤프를 사용하여 디버깅 중이며 gdb에서는 코어 덤프뿐만 아니라 실행 파일도 제공해야합니다. 왜 이런거야? 코어 덤프에 프로세스가 사용하는 모든 메모리가 포함되어 있으면 실행 파일이 코어 덤프 내에 포함되어 있지 않습니까? 아마도 전체 exe가 메모리에로드된다는 보장이 없거나 (개별 실행 파일이 일반적으로 크지는 않지만) 코어 덤프에 모든 관련 메모리가 포함되어 있지 않을 수도 있습니다. 기호에 대한 것입니까 (아마도 정상적으로 메모리에로드되지 않았습니까)?


1
gdb 문서에 언급 된 것처럼 실행 파일에는 기호 정보가 포함되어 있습니다.
Thomas Dickey

1
놀랍게도, (방금 추가 한 것을 제외하고) 답이 DWARF 형식을 언급하지 않습니다
Basile Starynkevitch

답변:


15

코어 덤프는 프로그램 메모리 풋 프린트의 덤프 일뿐입니다. 모든 것이 어디에 있는지 알고 있다면이를 사용할 수 있습니다.

실행 파일은 메모리에서 논리 파일의 위치 (예 : 코어 파일)를 설명하므로 실행 파일을 사용합니다.

명령을 사용하면 objdump조사중인 실행 가능한 개체에 대한 메타 데이터가 덤프됩니다. a.out이라는 실행 가능 객체를 예로 사용합니다.

objdump -h a.out헤더 정보 만 덤프하면 eg라는 섹션이 표시됩니다. .data 또는 .bss 또는 .text (더 많음) 이들은 커널 로더에게 객체에서 다양한 섹션을 찾을 수있는 위치와 프로세스 주소 공간에서 섹션을로드 할 위치 및로드 할 항목 (예 : .data .text)을 알려줍니다. (.bss 섹션에는 파일에 데이터가 포함되어 있지 않지만 초기화되지 않은 데이터의 프로세스에서 예약 할 메모리 양을 나타내며 0으로 채워집니다).

실행 가능한 객체 파일의 레이아웃은 표준 ELF를 따릅니다.

objdump -x a.out -모든 것을 버린다

실행 개체에 여전히 심볼 테이블이 포함되어 있으면 (제거되지 않았으며 ac 소스 컴파일 을 가정 하여 디버그 생성을 생성하는 man strip데 사용 -ggcc경우) 심볼 이름으로 핵심 내용을 검사 할 수 있습니다 (예 : 변수 / 버퍼가있는 경우) 소스 코드에서 inputLine 이라는 이름을 사용하면 해당 이름을 사용 gdb하여 내용을 볼 수 있습니다 . 즉 gdb, inputLine이 시작 되는 프로그램 초기화 데이터 세그먼트의 시작과 해당 변수의 길이 로부터의 오프셋을 알 수 있습니다 .

추가 기사 1 , 기사 2 및 완벽한 ELF (Executable and Linking Format) 사양에 대해 자세히 읽어보십시오 .


아래 @mirabilos 주석 후에 업데이트하십시오.

그러나 기호 테이블을 다음과 같이 사용하면

$ gdb --batch -s a.out -c core -q -ex "x buf1"

생산

 0x601060 <buf1>:    0x72617453

심볼 테이블을 사용하지 않고 직접 주소를 검사하지 않고

$ gdb --batch -c core -q -ex "x 0x601060"

생산

0x601060:   0x72617453

두 번째 명령에서 기호 테이블을 사용하지 않고 메모리를 직접 검사했습니다.


또한 @ user580082의 답변이 설명에 더 추가되며 투표권이 있습니다.


6
"기본 스택 섹션"에 대해 들어 본 적이 없습니다. .bss 는 (역사적으로) "기호로 시작된 블록"이고 실제로는 "단일화 된 데이터"이며, .data 는 "초기화 된 데이터"이고 텍스트 (.code가 아닌)는 기계 코드를 저장하는 데 사용됩니다. 스택은 런타임에 생성되므로 바이너리에는 스택 섹션이 없습니다.
jlliagre

“모든 것이 어디에 있는지 알고 있다면 그냥 사용할 수 있습니다”라고 프로그램의 모든 것이 반드시 설치 공간에 포함되어 있지 않기 때문에 사실이 아닙니다.
mirabilos

1
@ jlliagre 당신이 맞습니다. 실수로 .text .code이라고 불렀습니다 (답을 작성하는 동안 설명을 생각했기 때문에)-업데이트되었습니다. 나는 실수로 이름으로 bss를 잘못 생각하고 내 대답을 업데이트했지만 * 방정식에 실제로 추가한다고 생각하지 않기 때문에 Symbol에 의해 시작됨을 피하고 초기화되지 않은 데이터로 사용한다고 설명했습니다. 일반적인 이해. 감사합니다.이 게시물을 수정 한 의견에 감사드립니다.
X Tian

4

코어 파일은 프로세스 종료시 스택 이미지, 메모리 매핑 및 레지스터의 스냅 샷입니다. 내용은 핵심 매뉴얼 페이지에 주어진대로 조작 할 수 있습니다 . 기본적으로 개인 매핑, 공유 매핑 및 ELF 헤더 정보는 코어 파일로 덤프됩니다.

귀하의 질문에 따르면, gdb가 실행 파일을 필요로하는 이유는 실행을 시뮬레이션하지 않기 때문입니다 .valgrind와 같은 이진 명령을 읽고 해석하여 실행 중에 프로세스의 동작을 제어하기 위해 프로세스의 부모가됩니다. 시각. 코어 파일을 사용하여 충돌 중 메모리 맵핑 및 프로세스의 프로세서 상태를 판별합니다.

리눅스에서 부모 프로세스는 자식에 대한 추가 정보, 특히 ptrace 기능을 통해 디버거가 메모리 읽기 / 쓰기, 레지스터, 신호 매핑 변경, 실행 중지 등과 같은 프로세스의 하위 수준 정보에 액세스 할 수 있습니다.

디버거의 작동 방식을 읽으면 코어 파일이 더 많음에도 불구하고 실행 파일의 요구 사항을 이해할 수 있습니다.


1

(다른 좋은 답변 외에)

현대 리눅스 (및 많은 유닉스 계열) 시스템에서 디버깅 정보 (기호 유형, 소스 코드 위치, 변수 유형 등에 대한 메타 데이터 포함)는 DWARF 형식이며 ELF 실행 파일 ( 또는 ELF 공유 라이브러리)) -g옵션으로 컴파일 된 경우 나는 프로그램으로 디버깅 할 컴파일 추천 -g3 -O0아마도 -fno-inline최근 사용하는 경우 GCC를 ; 그러나 GCC를 사용하면 최적화 및 디버깅 정보, 예를 들어 디버그 정보로 컴파일 할 수 -O2 -g1있습니다.이 경우 디버그 정보가 약간 "퍼지"일 수 있습니다 (이것은 약간의 나쁜 Heisenbugs 잡는 데 도움이 될 수 있습니다 ).

동일한 실행 파일에 대해 여러 가지 다른 코어 파일 (많은 사용자가 버그 보고서를 작성하고 대부분은 덤프를 사용하여 버그 보고서를 작성하는 데 널리 사용되는 소프트웨어를 상상할 수 있음)을 가질 수 있기 때문에 해당 정보를 코어 파일에 저장 하지 않는 것이 합리적 입니다 core. 또한 core (5) 파일은 커널에 의해 덤프되며, elf (5) 실행 파일 에 DWARF 섹션의 존재를 신경 쓰지 않아야합니다 (이 섹션은 일부 신호에서 코어를 덤프 한 결함 프로세스가상 주소 공간 에 맵핑되지 않기 때문에 7) ). 디버그 정보를 별도의 파일 에 넣을 수도 있습니다 (실행 파일 외부).

BTW, GDB는 할 수 고통스럽게 모든 디버그 정보없이 실행에 대한 디버그 코어 덤프하는 데 사용됩니다. 그러나 실제로 프로그래밍 언어와 컴파일러에서 제공하는 기호 수준이 아닌 머신 코드 수준에서 실제로 디버깅합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.