Dynamic Loader: 로딩 + 재배치

섹션 요소
.interp : 동적 링커(ld.so)의 full path 이름을 저장
.plt : 외부 참조 함수 이름 정보
.got : load-time에 ld.so가 재배치할 전역변수 주소
.got.plt : run-time에 ld.so가 재배치 할 (.plt와 대응되는) 함수들의 실제 주소
(RW-)를 (R—) + (RW-)로 재배치 하는 이유
- 변경될 필요가 없는 영역은 Read-Only로 설정하고, 변경이 필요한 영역만 RW-로 유지하는 것이 더 안전하고 효율적인 방식이다.
- 보안 강화
- 실행 가능한 코드(
.text)가 변경 가능(Read-Write)하면 보안 취약점이 발생할 수 있다.
- 메모리 공유 최적화
- 여러 프로세스가 같은 라이브러리 코드를 공유 가능
- 페이지 보호
- 잘못된 쓰기를 방지하여 Segmentation Fault 예방
- 실행 성능 최적화
Shared Library 생성 후 (정적) 링킹

fPIC옵션으로 add.c, add.c를 컴파일한다.
- 동적 링커를 이용해
add.o, sub.o를 합쳐 공유 라이브러리 libcalc.so 생성
main.o, 내가 만든 공유 라이브러리(libcalc.so), 기존 라이브러리(libc.so)를 정적 링킹하여 실행파일 sum-d 생성
- 정적 로더(
execve)로 실행(./sum-d)
- ELF 헤더를 확인하여 실행 파일이 동적 링킹을 필요로 하는지 검사
.interp 섹션을 참조하여 동적 링커를 로딩
.interp가 존재하므로 동적 링커가 실행되야 함
- 동적 링커가
.dynamic를 확인하여 필요한 모든 공유 라이브러리들(libcalc.so, libc.so)을 차례로 로딩
- 동적 링커가 (RW-) 세그먼트를 (R—, RW-)로 재배치
- 메모리 보호 및 공유 최적화

정적 로딩 vs 동적 로딩 기준
- 로딩 방식은 실행 파일이 정적/동적 라이브러리를 포함하는지 여부에 따라 결정됨
정적 로딩
- 정적 라이브러리(
*.a 또는 *.lib)만 사용한 경우
동적 로딩
- 동적 라이브러리(
*.so또는 *.dll)를 하나라도 사용한 경우
- 실행할 때 정적 로더(
execve())가 동작하지만, 결국 동적 로더(ld.so)가 공유 라이브러리를 로드하여 동적 로딩이 수행됨
- 대부분의 프로그램은 표준 C 라이브러리를 포함하기 때문에, 대부분 동적 로딩을 수행함
리눅스 커널이 실행파일을 동적 로딩하는 과정

./sum-s : 사용자가 실행파일 실행
- Shell이 해당 실행 파일을 찾아 실행 요청
execve("sum-s") : Shell이 실행 파일 실행 요청
sys_execve() : 파일 시스템을 통해 sum-s 실행 파일 검색
do_execve() : 실행 파일 로딩 시작
- 실행 파일의 형식을 확인하고(ELF), 적절한 실행 파일 로더를 선택함
search_binary_hanlder() : 실행 파일 핸들러 선택
- 실행 파일의 형식을 확인하고(ELF), 적절한 핸들러를 선택함
load_elf_binary() : ELF 실행 파일을 메모리에 적재
.interp 섹션 확인 및 동적 링커(ld-linux.so) 로드
do_map() : 각 섹션(TEXT, DATA, BSS등)을 메모리에 적재
start_thread(): EIP(명령어 포인터)를 ELF 실행 파일의 진입점(Entry Point)로 설정
- 동적 링커(
ld.so) 실행 및 공유 라이브러리 로딩 시작
- ELF 실행 파일의
.dynamic 섹션을 참조하여 필요한 공유 라이브러리를 로드 시작
- 11~12 반복
_dl_map_object()를 호출하여 공유 라이브러리 매핑(1차 ping pong)
- 공유 라이브러리를 적절한 메모리 영역에 매핑함
dl_relocate_object()를 호출하여 심볼 재배치 (2차 ping pong)
- 모든 공유 라이브러리가 로드되면
main() 실행

- 실행파일의 진입점
_start() 실행
__libc_start_main()에서 실행 환경을 설정한 후 main() 호출
main() 실행이 종료되면, exit()를 호출하여 프로그램 종료 과정 시작
exit()내부에서 _destructor()가 실행되어 리소스 해제 및 정리 수행
출처