귀하의 주장은 실제로 어느 정도 정확합니다.
실행 가능한 ELF 파일의 경우 링커는 링커 스크립트를 사용하여 가상 공간의 주소를 프로그램의 모든 기호에 할당합니다.이 기호는 모두 시작 주소와 크기를 갖는 섹션으로 그룹화됩니다. ld --verbose
을 호출하여 사용되는 기본 스크립트를 볼 수 있습니다. 바이너리 섹션과 그 주소는 readelf
또는 objdump
과 같은 도구를 사용하여 볼 수 있습니다. readelf -l /bin/cat
. 그런 다음 cat /proc/self/maps
을 실행하면 /bin/cat
이 매핑되는 주소가 일치해야합니다. 따라서 커널 시스템 호출 execve
은 다음을 수행합니다. 현재 프로세스의 주소 공간을 인수로 주어진 실행 파일이 매핑 된 새로운 주소 공간으로 바꾸십시오.
물론 코드의 모든 비트에 정적 주소가 할당되어 있으면 공유 라이브러리의 문제를 해결할 수 있습니다. 공유 라이브러리는 위치 독립적 코드를 사용하므로 프로세스 주소 공간의 모든 곳에서 매핑 될 수 있습니다. 여기서 커널은 진행 방법을 결정합니다.
mmap
은 (1) 또는 (2) 중 어느 것도 수행하지 않으며, 주소 공간의 지정된 주소에 파일 또는 메모리 일부를 매핑합니다 (또는 커널이 사용할 주소를 결정하게합니다). 실제로 프로그램에서 사용하는 공유 라이브러리를 매핑하는 데 사용됩니다.방법을 보려면 strace /bin/true
을 실행하고 이진 파일에서 프로세스의 주소 공간을 생성하기 위해 먼저 execve
을 호출하는 방법과 프로그램 로더가 libc 파일을 열고 관련 섹션을 올바른 권한으로 mmap 한 방법을 확인하십시오.
:
execve("/bin/true", ["/bin/true"], [/* 69 vars */]) = 0
...
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
mmap(NULL, 3804080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f224f351000
mprotect(0x7f224f4e8000, 2097152, PROT_NONE) = 0
mmap(0x7f224f6e8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x197000) = 0x7f224f6e8000
다음 기사도 읽어 볼 가치가있을 수 있습니다