크래프톤 정글 (컴퓨터 시스템: CSAPP)/7장 링커

컴퓨터 시스템 : CSAPP 7장 정리 - 7.7 재배치

고웅 2025. 4. 18. 07:17

7.7 재배치 (Relocation)

링커가 심볼 결합을 완료하면, 각 심볼 참조가 하나의 정확한 정의와 연결되어 있다. 그다음 링커는 재배치(relocation) 과정을 통해 각 심볼에 실행 시간 주소(run-time address)를 할당한다. 이 과정은 두 단계로 나뉜다.

1단계 : 섹션 및 심볼 정의 재배치

  • 링커는 입력된 목적 파일들에서 동일한 종류의 섹션들을 병합(merge)한다.
    • 예: 모든 .data 섹션을 병합하여 최종 실행 파일의 .data 섹션으로 만든다.
  • 병합된 섹션들과 원래 섹션들 각각에 대해 실행 시간 주소를 할당한다.
  • 모든 전역 변수, 함수, 명령어는 이제 고유한 주소를 가지게 된다.

2단계 : 섹션 내부 심볼 참조 재배치

 

  • .text, .data 섹션 내부에 있는 심볼 참조를 올바른 주소로 수정한다.
  • 이 작업을 위해 재배치 정보(relocation entries)를 사용한다.
    • .rel.text, .rel.data 같은 섹션에 위치함
  • 어셈블러가 만든 이 정보들은 "어떤 위치에 어떤 방식으로 주소를 수정해야 하는지"를 알려주는 데이터다​.

재배치 엔트리의 형식

ELF 형식의 재배치 엔트리는 다음 정보를 포함한다.

 

  • offset: 수정할 참조의 위치
  • symbol: 참조할 심볼
  • type: 어떤 방식으로 주소를 수정할지 (예: PC-relative, absolute)
  • addend: 추가할 값
typedef struct {
    long offset;
    long type:32, symbol:32;
    long addend;
} Elf64_Rela;

 

 

주소 수정 예시

PC-relative (상대 주소) 예시

callq sum   ; sum 함수 호출

 

  • 명령어는 현재 명령어의 주소 기준으로 오프셋을 계산해서 sum 함수로 점프해야 한다.
  • 링커는 다음 계산을 수행:
*refptr = (unsigned) (ADDR(sum) + addend - refaddr);

 

절대 주소 예시

mov $array, %edi  ; array의 주소를 직접 레지스터에 저장
  • 단순히 심볼이 가리키는 주소를 계산해서 삽입:
*refptr = (unsigned) (ADDR(array) + addend);

이처럼 주소 계산 방식은 참조 방식(절대 vs 상대)에 따라 다르며, 그 방식은 type 필드로 구분된다​.