본 문서는 링커의 동작에 대해 다룬다.
먼저 링커가 하는일을 전부 알아보기는 힘드니까, 정적 파일에서 Symbol Table Section과 Relocation Table Section이 왜 필요하고 어떻게 동작하는지 알아보자.
파일구조는 다음과 같다.
본 문서에서는 링커의 아주 부분적인 기능인 Symbol Table Section과 Relocation Table Section 부분만 확인할것이다.
먼저 소스코드가 링킹 되기 직전의 시간대로 가보자.
cl.exe /c 옵션을 이용해서 링킹 직전의 파일 상태를 확인할수 있다.
예를들어 전역변수 int bar = 10; 가 초기화 되어있다면,
이전 글을 통해 변수 bar는 data섹션에 존재할것임을 예상할수 있다. 그런데 bar는 실제로 data섹션에 저장되어있지만,
코드(=text)섹션에서 bar에 대한 참조가 발생할수 있다.
이때 코드(=text)섹션은 data섹션의 bar를 알고싶지만 아직 알수 없다.
그래서 링킹되지 않은 파일은 bar에 대한 참조가 발생하는 그 주소위치를 offset 으로 기록한다.
다양한 위치에서 bar에 대한 참조가 발생하므로, 이를 관리하기 위해 Relocation Table 을 정의한다.
여러 offset에서 bar를 참조하려고 한다는 정보를 이 테이블에 기록하고 별도의 섹션으로 관리한다.
그렇다면 bar의 실제 data섹션 주소는 어디일까?
링커는 Relocation Table Section을 참조해서 bar를 참조하는 위치를 관리한다고 이야기 했다.
그런데 실제로 bar의 위치를 연결해주려다보니 bar의 위치를 찾으려면 data섹션을 모두 탐색해야하는 문제가 발생한다.
때문에 bar를 참조할때마다 data 섹션에 대한 탐색이 이루어진다면 프로그램의 오버헤드는 엄청날것이 자명하다.
이를 위해 bar와 같은 전역변수, 함수(전역,지역,외부), 등의 주소위치를 따로 관리해야겠다는 아이디어가 채택되었다.
이것을 구현한게 Symbol Table이다.
이 테이블에 자주 참조되는 global/static변수와 함수등의 위치를 심볼(이름)과 함께 매핑시켜둔것이다.
이런 원리로 Symbol Table Section과 Relocation Table Section은 링커에서 동작하며 링킹이 끝난 이후에는 정적 파일과 다른 모습을 보인다.(디버깅용 정보로 사용되는 경우를 제외하면 대부분 삭제되거나 무시된다.)