2016-06-16 3 views
1

elf 실행 파일에는 섹션 테이블이 포함되어 있습니다. 이 섹션은 프로그램이 메모리에로드 될 때 세그먼트에 매핑됩니다. 메모리에서 세그먼트 주소를 결정하는 것은 컴파일러라고 생각합니까? 프로그램이로드 될 때 운영 체제가 세그먼트 주소를 변경할 수 있다고 생각합니까?Linux 실행 메모리 매핑

나는 하나의 elf 실행 파일에 대해 이야기하고 있습니다. 이것은 도서관이 아닙니다. 사실, 바이너리가 있습니다. 메모리의 함수 주소를 알고 있고 외부 프로그램에서이 함수를 연결하고 싶습니다. 나는이 주소가 결코 바뀌지 않을 것이라고 확신하고 싶다. 대상 프로그램에서 아무 것도 재 컴파일하거나 변경하지 않 았습니다.

답변

2

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.

+0

감사합니다. "ET_DYN (PIE 바이너리라고도 함)에 대해 말하면 임의의 주소에서로드가 가능하고 예상됩니다.": 주 함수와 foo 함수가 포함 된 elf 실행 파일 (라이브러리 아님)을 컴파일한다고 가정합니다. 그 함수가 임의의 주소에도로드되어야한다는 의미입니까? 그러나 엔트리 포인트는 2 번의 실행 사이를 이동할 수 없습니다! – Bob5421

+0

@ Bob5421 실행 파일을'-pie' 플래그로 연결하면 실행 파일은'ET_DYN' 타입이되고 공유 라이브러리처럼 동작합니다. https://stackoverflow.com/questions/1449987/building-a-so-that-is-also-an-executable –

+0

이 경우 메인과 foo는 임의의 주소에있게 될까요? – Bob5421