Symbol Resolution 단계에서 링커는 파일들과 컴파일러 드라이버의 명령줄 라인에 나타난 것과 같은 순차적인 순서로 좌에서 우로 재배치가능 목적파일들과 아카이브들을 스캔한다. 이 스캔 과정에서 링커는 집합 E, U, D를 유지하게 되는 데 각각의 역할을 다음과 같다.

  • 집합 E: 실행파일을 구성하기 위해 합쳐질 재배치가능 목적파일들의 집합
  • 집합 U: 미해석 심볼 집합 (Unresolved symbol, 참조되긴 하지만 아직 정의되지 않은)
  • 집합 D: 이전 입력 파일에서 정의(Defined 즉, resolve 완료)된 심볼 집합

초기 상태에서 모든 집합은 비어 있게 된다. 이때 링커의 resolution 동작을 앞서 설명한 집합과 함께 설명하면 다음과 같다.

  1. 명령줄 상의 매 입력 파일 f에 대해서, 링커는 만약 f가 목적 파일인지 아카이브인지를 결정한다. 만일 f가 목적파일이라면 링커는 f를 E에 추가하고 심볼 정의와 f에서의 참조를 반영하도록 U와 D를 갱신하고 다음 입력 파일로 넘어간다.

  2. 만일 f가 아카이브라면, 링커는 U 안의 미해석 심볼들을 아카이브의 멤버들에 의해 정의된 심볼들과 매칭하려고 시도한다. 만일 일부 아카이브 멤버 m이 U 내의 참조를 해결하는 심볼을 정의하려면 m은 E에 추가되고 링커는 U와 D를 m에 있는 심볼 정의와 참조를 반영하도록 갱신한다. 이 과정은 U와 D가 더이상 바뀌지 않는 일정 지점까지 아카이브 내의 멤버 목적 파일들에 대해 반복 실행된다. 이 시점까지 E에 포함되지 않은 모든 멤버 함수들은 간단히 버리고 링커는 다음 입력 파일로 진행한다.

  3. 링커가 명령줄의 입력 파일들을 스캔하는 작업을 끝마칠 때, U가 비어있지 않다면 에러를 출력하고 종료한다. 그렇지 않다면 E에 있는 목적파일들을 합치고 재배치(relocation)해서 출력 실행파일을 작성한다.

때문에 만약 gcc를 통해 링커를 동작시키는 경우, 컴파일 옵션 순서를 잘못 주게 되어 심볼을 정의하는 라이브러리가 심볼을 참조하는 목적파일 전에 명령줄에 나타난다면, 이 참조는 해결되지 않으며 링킹 작업은 실패한다. 다음의 예시를 살펴보자.

unix> gcc -static ./libvector.a main.c
libvector.o: In function `main':
libvector.o(.text+0x18): undefined reference to `addvec'

 

목적파일과 아카이브에는 아무런 문제가 없다고 가정한다. 

링커가 실행되고 libvector.a가 처리될 때, U는 비어있었다. 때문에 아카이브 파일이 제공되었지만 그 어떤 심볼도 U에서 D로 이동하지 못했다. 끝까지 D가 비어있었다면, 문제 없이 링커의 동작이 완료되었겠지만, 마지막에 main.c가 입력으로 제공되며 해당 파일에 존재하는 unresolved symbol 들이 U에 들어가게 된다. 결과적으로 링커가 더 입력파일을 제공받지 못했고, 여전히 U에는 심볼 목록들이 남아있기 때문에 E는 하나의 실행가능 목적파일로 합쳐지지 못하고 링커에서 에러를 출력한다.