동적 링킹
IT 위키
(정적 링킹에서 넘어옴)
- Dynamic Linking
- 외부 라이브러리를 실행 파일에 포함시키지 않고, 실행 시점에 공유 라이브러리를 찾아 연결하는 방식
- 리눅스의 .so, 윈도우의 .dll이 공유 라이브러리다.
- 실행 파일이 작아지고 여러 프로그램이 같은 라이브러리를 공유한다. 라이브러리를 고쳐도 프로그램을 다시 컴파일할 필요가 없다.
- 대신 실행할 때 라이브러리가 없거나 버전이 다르면 실행되지 않는다.
| 구분 | 정적 링킹 | 동적 링킹 |
|---|---|---|
| 연결 시점 | 컴파일(링크) 시점 | 실행 시점 |
| 실행 파일 크기 | 크다 | 작다 |
| 메모리 | 프로세스마다 사본을 가진다 | 여러 프로세스가 공유한다 |
| 라이브러리 갱신 | 다시 링크해야 한다 | 라이브러리만 교체하면 된다 |
| 실행 속도 | 호출이 직접적이라 약간 빠르다 | 첫 호출에 주소 해석 비용이 있다 |
- 컴파일 시점에는 외부 함수가 메모리 어디에 올라올지 알 수 없다. 그래서 표 두 개를 두고 실행 시점에 주소를 채운다.
| 표 | 이름 | 역할 |
|---|---|---|
| PLT | Procedure Linkage Table | 외부 함수를 호출할 때 거쳐 가는 표. 코드 영역에 있다 |
| GOT | Global Offset Table | 외부 함수의 실제 주소가 저장되는 표. 데이터 영역에 있다 |
- 호출 흐름은 프로그램 → PLT → GOT → 실제 함수 순이다.
- 처음 호출할 때는 GOT에 주소가 없으므로 동적 링커가 함수를 찾아 GOT에 기록한다. 두 번째 호출부터는 GOT를 통해 바로 간다. 이를 지연 바인딩(lazy binding)이라 한다.
- GOT는 쓰기 가능한 영역이므로 버퍼 오버플로우 등으로 값을 바꾸면 실행 흐름을 공격자가 원하는 함수로 돌릴 수 있다. 이를 GOT Overwrite라 한다.
- 대응으로 RELRO(Relocation Read-Only)를 적용한다. Full RELRO는 지연 바인딩을 끄고 시작할 때 모든 주소를 채운 뒤 GOT를 읽기 전용으로 바꾼다.
