7.4 재배치 가능 오브젝트 파일 (Relocatable Object Files)
재배치 가능 오브젝트 파일은 컴파일된 프로그램의 기본 단위로, 여러 소스 파일에서 생성된 오브젝트 파일들을 링크하여 하나의 실행 파일을 만들기 위해 사용된다. 각 오브젝트 파일은 기계어 코드와 데이터, 메타데이터(심볼 테이블)를 포함하고 있으며, 이 파일들은 링킹 과정에서 결합되어 최종 실행 파일을 생성한다. 이 재배치 가능 오브젝트 파일의 주요 기능은 프로그램을 재배치할 수 있도록 설계되어 있다는 것이다.
재배치 가능 오브젝트 파일의 각 섹션은 실행 시점에 특정 메모리 주소에 고정되지 않으며, 링커에 의해 실제 실행 시 필요한 주소로 "재배치"될 수 있다. 이를 통해 여러 모듈(소스 파일)을 독립적으로 컴파일하고, 링커가 나중에 이들을 결합할 때 올바르게 작동할 수 있도록 한다.
재배치 가능 오브젝트 파일의 주요 구성
- 코드와 데이터 섹션:
소스 파일에서 컴파일된 기계어 코드와 전역 또는 정적 데이터가 포함된 섹션이다.- .text 섹션: 실행할 코드가 들어있는 섹션이다.
- .data 섹션: 초기화된 전역 변수와 정적 변수가 저장된 섹션이다.
- .bss 섹션: 초기화되지 않은 전역 변수와 정적 변수가 저장되는 섹션이다.
- 심볼 테이블 (Symbol Table):
심볼 테이블은 각 오브젝트 파일 내에서 정의된 함수와 변수의 이름 및 위치 정보를 담고 있는 테이블이다. 이 테이블을 통해 링커는 다른 오브젝트 파일이나 라이브러리에서 필요한 함수 및 변수를 참조할 수 있다. - 재배치 정보 (Relocation Information):
링커가 재배치할 수 있도록 각 기계어 명령어와 데이터에 대한 재배치 정보가 포함된다. 이 정보는 링커가 오브젝트 파일을 결합할 때, 특정 함수나 변수가 어디에 위치할지 결정하도록 돕는다.
재배치 가능 오브젝트 파일의 동작 예시
예를 들어, 다음과 같은 두 개의 소스 파일 main.c
와 sum.c
가 있다고 가정하자.
// main.c
#include <stdio.h>
int sum(int a, int b);
int main() {
int result = sum(3, 4);
printf("Sum: %d\n", result);
return 0;
}
// sum.c
int sum(int a, int b) {
return a + b;
}
1. 컴파일 단계:
gcc -c main.c sum.c
명령어로 각 파일을 컴파일하면, main.o
와 sum.o
라는 재배치 가능 오브젝트 파일이 생성된다.
main.o
:main.o
파일에는main()
함수의 기계어 코드가 들어 있고, 이 코드는sum()
함수를 호출하려고 하지만,sum()
함수의 정의는 아직 존재하지 않는다. 따라서sum()
함수는 외부 심볼로 처리되며, 심볼 테이블에sum
함수가 존재하는지 나중에 링킹 과정에서 확인된다.
sum.o
:sum.o
파일에는sum()
함수의 기계어 코드가 들어 있다. 링커는 이 파일을 이용해sum()
함수를 정의하고,main.o
에서 참조하는sum()
의 위치를 재배치할 수 있도록 한다.
2. 심볼 테이블 및 재배치 정보
각 오브젝트 파일에는 다음과 같은 정보가 포함된다.
main.o
심볼 테이블:main
: 정의됨 (정의된 함수)sum
: 참조됨 (정의되지 않았지만 나중에 결합될 외부 함수)
sum.o
심볼 테이블:sum
: 정의됨 (이 함수는sum.o
내에서 정의됨)
링커는 각 오브젝트 파일의 심볼 테이블을 확인하고, main.o
에서 참조된 sum()
함수가 sum.o
에서 정의된 것을 발견하게 된다.
3. 주소 재배치
링킹 과정에서 링커는 main.o
와 sum.o
를 결합하며, 이때 재배치 정보가 사용된다. main.o
의 main()
함수가 sum()
을 호출할 때 실제로 어느 주소로 이동해야 하는지를 결정하게 된다. 이 과정에서 sum()
함수의 주소는 sum.o
파일 내에서 계산된 후, main.o
의 호출 코드에서 해당 주소로 재배치된다.
# main.o에서 sum 함수를 호출하는 부분
call sum ; 링킹 전에 sum의 실제 주소는 알 수 없음
; 링커는 이 부분을 수정하여 sum의 실제 주소로 대체
# sum.o에서 sum 함수의 정의 부분
sum:
add %edi, %esi
ret
링킹 후 call sum
명령어는 sum
함수의 실제 메모리 주소로 대체되며, 최종 실행 파일에서 main()
함수가 sum()
함수를 올바르게 호출할 수 있게 된다.
4. 실행 파일 생성
링커가 재배치 가능 오브젝트 파일을 결합하여 최종 실행 파일을 생성하면, 프로그램은 각 함수와 변수가 메모리에서 정확한 주소에 배치된 상태로 실행될 준비가 완료된다. 결과적으로, main()
함수는 sum()
함수를 호출하고, 최종적으로 "Sum: 7"이라는 출력이 나타난다.
gcc main.o sum.o -o prog
./prog
# 출력: Sum: 7
결론
재배치 가능 오브젝트 파일은 프로그램을 독립적인 모듈로 컴파일하고, 나중에 링킹을 통해 결합할 수 있는 유연성을 제공한다. 이 파일들은 실행 시점에 정확한 메모리 주소로 재배치되기 때문에, 각 오브젝트 파일은 링커에 의해 결합되기 전까지 특정 메모리 주소에 고정되지 않는다. 이를 통해 대규모 프로젝트에서 여러 모듈을 병렬로 컴파일하고, 나중에 결합할 수 있는 효율성을 제공한다.
'cs' 카테고리의 다른 글
[크래프톤 정글] 시그널(CSAP 8.5장) (0) | 2024.10.12 |
---|---|
[크래프톤 정글] 예외상황(CSAP 8.1장) (1) | 2024.10.12 |
[크래프톤 정글] 컴파일러 와 링커(CSAP 7.1장)* (0) | 2024.10.11 |
[크래프톤 정글] 가상 메모리 와 페이징 * (0) | 2024.10.07 |
[크래프톤 정글] cpu의 명령어 사이클 (0) | 2024.10.01 |