gdb를 사용할 때 Linux 가상 메모리에 일부 라이브러리 및 기타 부분이 중복되는 이유는 무엇입니까?

gdb를 사용할 때 Linux 가상 메모리에 일부 라이브러리 및 기타 부분이 중복되는 이유는 무엇입니까?

여기에 이미지 설명을 입력하세요.

이것은 gdb에서 프로세스 가상 메모리를 살펴본 결과입니다. 이에 대해 몇 가지 질문이 있습니다.

  1. 가상 메모리의 일부가 중복되는 이유는 무엇입니까? 예를 들어, 우리 프로그램(stack6)과 libc 라이브러리가 서로 다른 부분으로 분할되어 있다면 왜 그럴까요? 모두 함께 모아 보는 것은 어떨까요?

  2. 최상위 경로(/opt/pro...)는 가상 메모리의 명령 부분(텍스트 부분)이며 명령만 포함합니까?

  3. 4개의 libc 크기가 왜 다른가요? 오프셋의 용도는 무엇입니까? 크기와 시작 주소가 이미 있는 경우 오프셋의 용도는 무엇입니까?

  4. 데이터, bss, 커널 및 힙 부분은 어디에 있습니까? 위 이미지의 일부 부분에 대한 정보가 없는 이유는 무엇입니까? 실제로 모든 섹션을 표시하는 더 나은 옵션이 gdb에 있습니까?

  5. 프로세스의 가상 메모리 부분을 더 잘 표시할 수 있는 gdb보다 더 나은 프로그램이 있습니까? 저는 실제 가상 메모리와 어떤 디버거가 최상의 결과를 제공하는지 명확하게 확인하고 싶습니다.

제가 언급한 부분:

여기에 이미지 설명을 입력하세요.

답변1

출력에서 gdb페이지 권한이라는 중요한 정보가 누락되었습니다. (그들은 보여줍니다솔라리스와 FreeBSD에서, 그러나 Linux에서는 그렇지 않습니다. ) ;을 보면 이러한 내용을 볼 수 있습니다 /proc/<pid>/maps. Protostar 예시의 지도 표시

$ cat /proc/.../maps
08048000-08049000 r-xp 00000000 00:0f 2925       /opt/protostar/bin/stack6
08049000-0804a000 rwxp 00000000 00:0f 2925       /opt/protostar/bin/stack6
b7e96000-b7e97000 rwxp 00000000 00:00 0
b7e97000-b7fd5000 r-xp 00000000 00:0f 759        /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:0f 759        /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r-xp 0013e000 00:0f 759        /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rwxp 00140000 00:0f 759        /lib/libc-2.11.2.so
b7fd9000-b7fdc000 rwxp 00000000 00:00 0
b7fe0000-b7fe2000 rwxp 00000000 00:00 0
b7fe2000-b7fe3000 r-xp 00000000 00:00 0          [vdso]
b7fe3000-b7ffe000 r-xp 00000000 00:0f 741        /lib/ld-2.11.2.so
b7ffe000-b7fff000 r-xp 0001a000 00:0f 741        /lib/ld-2.11.2.so
b7fff000-b8000000 rwxp 0001b000 00:0f 741        /lib/ld-2.11.2.so
bffeb000-c0000000 rwxp 00000000 00:0f 0          [stack]

(Protostar 예제는 쉽게 해킹할 수 있는 VM에서 실행되며, 아마도 연습을 쉽게 하기 위해 NX 보호 및 ASLR이 없습니다.)

중복된 매핑으로 보이는 것이 실제로는 gdb다른 권한을 가진 다른 매핑에 해당한다는 것을 위에서 볼 수 있습니다. 텍스트 세그먼트는 읽기 전용 및 실행 가능으로 매핑되고, 데이터 세그먼트는 읽기 전용으로 매핑되며 BSS와 힙은 읽기-쓰기로 매핑됩니다. 이상적으로 데이터 세그먼트, BSS 및 힙은 실행 불가능하지만 이 예에서는 NX 지원이 부족하므로 실행 가능합니다. 각 공유 라이브러리에는 자체 텍스트 세그먼트, 데이터 세그먼트 및 BSS 매핑이 있습니다. 네 번째 맵은 일반적으로 버퍼 오버플로를 방지하는 데 사용되는 읽기 불가능, 쓰기 불가능, 실행 불가능 세그먼트입니다(여기에 사용된 커널 및 C 라이브러리의 수명에 따라 달라질 수 있음).

주어진 오프셋은 파일 내 데이터의 오프셋을 나타내며 주소 공간에서의 위치와 반드시 관련이 있는 것은 아닙니다. 로드할 때 정렬 제약 조건이 적용됩니다. 예를 들어 libc-2.11.2.so프로그램 헤더는 두 개의 "LOAD" 헤더를 지정합니다.

Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align
LOAD           0x000000 0x00000000 0x00000000 0x13d2f4 0x13d2f4 R E 0x1000
LOAD           0x13e1cc 0x0013f1cc 0x0013f1cc 0x027b0  0x0577c  RW  0x1000

( readelf -l이것을 보려면 그것을 사용하십시오.)

세그먼트에 매핑된 부품의 보호 플래그가 서로 다른 경우 동일한 오프셋에서 서로 다른 가상 주소를 사용하여 여러 매핑이 발생할 수 있습니다. 다음 stack6과 같은 경우:

Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
LOAD           0x000000 0x08048000 0x08048000 0x00604 0x00604 R E 0x1000
LOAD           0x000604 0x08049604 0x08049604 0x00114 0x00128 RW  0x1000

proc info mappings(이는 for stack6: 각 헤더 요청이 4KiB 정렬을 사용하여 4KiB보다 작으므로 서로 다른 주소에서 동일한 오프셋을 가진 두 개의 4KiB 맵을 가져오는 작은 크기를 설명합니다.)

빈 매핑은 익명 매핑에 해당합니다.man 5 proc더 알아보기. 당신은 그들이 무엇에 해당하는지 mmap에 대한 깊은 이해가 필요합니다 .gdb

vsyscall커널 맵( 일부 아키텍처의 레거시 맵 제외)은 프로세스 관점에서 중요하지 않기 때문에(액세스할 수 없음) 표시되지 않습니다 .

더 좋은 옵션이 있는지 모르겠어서 gdb항상 /proc/$$/maps.

바라보다프로그램 실행 방법: ELF 바이너리커널이 읽는 ELF 형식과 메모리 할당에 매핑하는 방법에 대한 자세한 내용은 더 많은 참조 자료를 참조하세요.

관련 정보