elf 실행 파일에는 섹션 테이블이 있습니다.
거짓 : 섹션 테이블이 완전히 연결 ET_EXEC
또는 ET_DYN
바이너리에서 제거되는 것이 완벽하게 유효합니다.
이 섹션은 프로그램을 메모리에로드 할 때 세그먼트에 매핑됩니다.
거짓 : 구역 간 세그먼트 매핑은 런타임이 아닌 정적 링크에서 발생합니다.
메모리의 세그먼트 주소를 결정하는 컴파일러라고 생각하십니까?
거짓 : ET_EXEC
에 대해 이것을 결정하는 정적 링커입니다. ET_DYN
의 경우 정적 링커와 런타임 로더가 협조합니다.
프로그램을로드 할 때 운영 체제가 세그먼트 주소를 변경할 수 있다고 생각하십니까?
는 ET_EXEC
를 들어, 바이너리는 정적 링커가 이진 연결되는 주소에로드 항상 입니다. 다른 곳에로드하면 프로그램이 중단됩니다. 임의의 주소에로드도 PIE
바이너리로 알려진 ET_DYN
를 들어
는 모두 예상 가능한 및입니다.
이진수가 있습니다. 메모리의 함수 주소를 알고 있고 외부 프로그램에서이 함수를 연결하고 싶습니다. 나는이 주소가 결코 바뀌지 않을 것이라고 확신하고 싶다.
이진수가 ET_EXEC
인 경우 모든 세그먼트는 항상 링크 된 주소에로드되므로 예입니다.
업데이트하십시오 PIE
바이너리에서
, 같은 이전 (재배치가 정상적으로 실행 실행에서 다양하여 함께 이동합니다 모든 (main
, foo
, _start
등)하지만 GDB 주소 공간의 랜덤 화를 무효화하므로, (gdb) set disable-randomization off
를 실행해야한다).
은 GDB의 재배치를 찾으려면, 당신은 할 수 있습니다 :는 (gdb) p &main
(gdb) start
(gdb) p &main
프로세스가 시작되기 전에 &main
의 첫 번째 값은 nm test | grep main
의 출력과 동일해야합니다. 두 번째 값 (프로세스가 시작된 후)은 값을 재배치해야합니다 (main
이 메모리에 있음). 이 둘의 차이는 (페이지 정렬 된) 재배치입니다.
런타임에이 재배치를 찾으려면 (프로그램 자체 내에서) dl_iterate_phdr()
을 사용해야하고 dlpi_addr
을 사용해야합니다. Documentation.
감사합니다. "ET_DYN (PIE 바이너리라고도 함)에 대해 말하면 임의의 주소에서로드가 가능하고 예상됩니다.": 주 함수와 foo 함수가 포함 된 elf 실행 파일 (라이브러리 아님)을 컴파일한다고 가정합니다. 그 함수가 임의의 주소에도로드되어야한다는 의미입니까? 그러나 엔트리 포인트는 2 번의 실행 사이를 이동할 수 없습니다! – Bob5421
@ Bob5421 실행 파일을'-pie' 플래그로 연결하면 실행 파일은'ET_DYN' 타입이되고 공유 라이브러리처럼 동작합니다. https://stackoverflow.com/questions/1449987/building-a-so-that-is-also-an-executable –
이 경우 메인과 foo는 임의의 주소에있게 될까요? – Bob5421