C

Object file..

GunwooYun 2025. 1. 14. 00:10

C 소스 파일을 컴파일하면 object 파일 (*.o) 가 생성된다. 보통은 -c 옵션을 생략하기도 하고, Makefile에서 생성되긴 하지만 별 관심없이 그냥 넘어가곤 한다. 갑자기 object 파일 안에는 무슨 내용이 있을까 궁금해져서 역시나 형님께 여쭤봤다.

먼저, 아래 캡쳐 그림은 object 파일들을 각각 다른 컴파일러로 컴파일한 내용이다. 첫번째 그림은 gcc 로 컴파일한 결과이다.

gcc

 

아래 그림은 arm-none-eabi 컴파일러로 object를 생성한 결과이다.

arm-none-eabi

 

C 소스 코드를 컴파일하여 생성된 **Object 파일(객체 파일)**에는 컴파일된 바이너리 코드와 함께 프로그램 실행에 필요한 다양한 메타데이터가 포함됩니다. Object 파일은 기계어 코드로 변환된 **섹션(section)**과 심볼(symbol) 정보를 포함하며, 이 정보는 링크 단계에서 사용됩니다.


Object 파일의 구성 요소

1. 헤더(Header)

  • Object 파일의 기본 정보를 포함.
  • 파일 형식(예: ELF, COFF, PE), 아키텍처, 엔디안, 버전 정보 등을 정의.

헤더에 포함된 정보:

  • 파일 타입: 실행 파일, 재배치 가능 파일(Object 파일), 공유 라이브러리 등.
  • 아키텍처: 타겟 CPU(예: x86, ARM).
  • 엔디안: Little-endian 또는 Big-endian.
  • 섹션 오프셋: 각 섹션의 시작 위치.

2. 섹션(Sections)

Object 파일은 여러 섹션으로 나뉘며, 각각 특정 유형의 데이터를 포함합니다.

주요 섹션:

  1. .text
    • 기계어 코드(실제 실행되는 코드)를 포함.
    • 읽기 전용.
    • 예: 함수의 기계어 명령어.
  2. .data
    • 초기화된 전역 및 정적 변수를 포함.
    • 읽기 및 쓰기 가능.
    • 예: int x = 10;
  3. .bss
    • 초기화되지 않은 전역 및 정적 변수를 포함.
    • 파일 크기를 줄이기 위해, 메모리에서만 초기화됨(값은 0으로 초기화).
    • 예: int y;
  4. .rodata
    • 읽기 전용 데이터(예: 상수, 문자열 리터럴)를 포함.
    • 예: const char *str = "Hello";
  5. .rel.text / .rela.text
    • 재배치 정보. 링크 시 동적으로 주소를 수정하기 위해 사용.
  6. .symtab
    • 심볼 테이블. 함수, 변수, 객체 등의 심볼 정보를 포함.
  7. .strtab
    • 심볼 이름을 저장하는 문자열 테이블.

3. 심볼 테이블(Symbol Table)

  • Object 파일에 정의된 함수 및 변수의 이름과 위치 정보를 포함.
  • 각 심볼에는 다음과 같은 정보가 포함됩니다:
    • 이름: 변수나 함수의 이름.
    • 섹션: 심볼이 속한 섹션(예: .text, .data).
    • 주소: 심볼의 시작 주소.
    • 유형: 함수, 변수, 재배치 심볼 등.

4. 재배치 정보(Relocation Entries)

  • Object 파일의 주소를 재배치하는 데 필요한 정보.
  • 링크 시, 다른 오브젝트 파일이나 라이브러리의 주소와 결합하여 올바른 실행 파일을 생성.

주요 항목:

  • 심볼 참조: 외부 또는 내부 심볼 참조.
  • 오프셋: 수정해야 할 메모리 주소.
  • 재배치 유형: 수정 방법(절대 주소, 상대 주소 등).

5. 디버그 정보(선택적)

  • 디버깅 도구(GDB 등)에서 사용되는 추가 정보.
  • 컴파일 시 -g 옵션을 활성화하면 생성.
  • 주요 구성:
    • 소스 코드와 바이너리 코드 간의 매핑 정보.
    • 함수 이름, 변수 이름, 파일 라인 번호 등.

Object 파일의 실제 예시

1. 컴파일

다음 C 코드를 gcc -c example.c 명령으로 컴파일하면 Object 파일이 생성됩니다.

// example.c
#include <stdio.h>

int x = 10;
const char *message = "Hello, World!";

void printMessage() {
    printf("%s\n", message);
}

2. Object 파일 분석

readelf 명령어를 사용하여 Object 파일을 분석할 수 있습니다.

헤더 정보:

$ readelf -h example.o
ELF Header:
  Class:                             ELF32
  Data:                              2's complement, little endian
  Type:                              REL (Relocatable file)
  Machine:                           ARM

섹션 정보:

$ readelf -S example.o
Section Headers:
  [Nr] Name              Type             Address          Offset
  [ 0] .text             PROGBITS         00000000         0x0000
  [ 1] .data             PROGBITS         00000000         0x0040
  [ 2] .bss              NOBITS           00000000         0x0050
  [ 3] .rodata           PROGBITS         00000000         0x0060
  [ 4] .symtab           SYMTAB           00000000         0x0080
  [ 5] .strtab           STRTAB           00000000         0x00c0

Object 파일의 링크 과정

  1. 개별 Object 파일 생성:
    • 소스 파일을 컴파일하여 각각의 Object 파일 생성.
  2. 링커(Linker):
    • 여러 Object 파일과 라이브러리를 결합하여 실행 파일 생성.
    • 재배치 정보를 사용하여 심볼을 올바르게 연결.
  3. 실행 파일 생성:
    • 최종적으로 실행 가능한 바이너리 파일 생성.

결론

Object 파일은 다음과 같은 요소로 구성됩니다:

  • 헤더: 파일 정보.
  • 섹션: .text, .data, .bss 등 프로그램 데이터.
  • 심볼 테이블: 함수와 변수의 이름 및 위치 정보.
  • 재배치 정보: 링크 시 주소 수정에 필요한 정보.

Object 파일은 컴파일된 코드와 프로그램 실행에 필요한 메타데이터를 포함하여, 링커가 실행 파일을 생성하는 데 필요한 중요한 역할을 합니다.