[TIL/크래프톤 정글] DAY 44

배재준·2025년 4월 22일

크래프톤 정글 - TIL

목록 보기
37/93
post-thumbnail

2025.04.22

TIL(TODAY I LEARN)


  • 오늘한 내용 : CS - 링커 ~7.5, 7.9

  • WEEK06: 메모리 누수, 균형 이진 탐색 트리(AVL Tree, Red-Black Tree)


7. 링커(Linker)

  • 링크는 다양한 코드와 데이터를 하나의 파일로 모아, 메모리에 적재하고 실행할 수 있도록 만드는 과정임.
  • 링크는 다음 시점 중 하나에 수행될 수 있음:
    1. 컴파일 시 (정적 링크)
    2. 로드 시 (실행 전에 링커가 수행됨)
    3. 실행 시 (동적 라이브러리 호출)

7.1 컴파일러 드라이버

  • 대부분의 시스템에서 gcc와 같은 컴파일러 드라이버(driver)는 다음 네 단계를 자동으로 실행
단계역할명령어 예시
전처리매크로 처리, 헤더 포함cpp main.c → main.i
컴파일C → 어셈블리 변환cc1 main.i → main.s
어셈블어셈블리 → 목적 코드 변환as main.s → main.o
링크목적 코드 → 실행파일 생성ld main.o sum.o → prog

7.2 정적 연결

  • 정적 링크(static linking)는 여러 개의 재배치 가능한 오브젝트 파일(relocatable object files)들을 결합하여 완전히 링크된 실행 파일을 생성하는 과정
  • 이 과정을 담당하는 프로그램은 보통 ld (링커)

1단계. 심볼 해석(Symbol Resolution)

  • 심볼 : 변수명, 함수명 등 엔티티를 식별하기 위해 사용하는 이름
  • 오브젝트 파일에는 정의된 심볼(함수, 전역 변수 등)참조된 심볼이 존재함
  • 링커는 각 참조를 하나의 정의와 정확히 연결해야 함
  • 예:
    • sum() 함수가 sum.c에 정의되어 있고 main.c에서 참조됨
    • 링커는 main.o의 참조를 sum.o의 정의와 연결

2단계. 재배치(Relocation)

  • 컴파일러와 어셈블러는 코드와 데이터를 주소 0부터 시작하는 것처럼 생성
  • 링커는 실제 실행 시 주소를 할당하고,
    • 참조를 해당 주소로 수정
    • 이 과정은 재배치 엔트리(relocation entry)를 통해 수행됨

7.3 목적 파일

오브젝트 파일(object file)기계어로 번역된 중간 결과물로, 컴파일 또는 어셈블 후 생성되는 파일임. 실행 파일이 아니며, 링커(linker)에 의해 다른 오브젝트 파일들과 합쳐져 실행 파일로 만들어짐.

오브젝트 파일의 3가지 형태

  1. 재배치 가능 목적 파일 - Relocatable object file (.o)
    • 컴파일러와 어셈블러가 생성
    • 여러 파일들과 함께 링크되어 실행파일 생성 가능
  2. 실행 가능 목적 파일 - Executable object file
    • 링커가 생성
    • 메모리에 적재되어 실행 가능한 상태
  3. 공유 목적 파일 - Shared object file (.so)
    • 동적 링크를 위해 사용되는 특수한 relocatable 오브젝트 파일
    • 로드 시점 또는 실행 시점에 동적으로 링크됨
  • ELF는 Executable and Linkable Format 오브젝트 파일과 실행 파일의 표준 포맷
ELF header
Program Header table
ELF 섹션설명
.text기계어 코드
.rodata읽기 전용 데이터 (ex. printf 포맷 문자열)
.data초기화된 전역/정적 변수
.bss초기화되지 않은 전역/정적 변수 (파일 공간은 차지하지 않음)
.symtab심볼 테이블 (전역 변수, 함수 등)
.rel.text.text에 대한 재배치 정보
.rel.data.data에 대한 재배치 정보
.debug디버깅 정보
.line소스 코드 라인 정보
.strtab심볼 이름 문자열
Section header table

7.4 재배치 가능 목적 파일

  • ELF 헤더 : 바이트 순서, 워드 크기, 파일 타입, 대상 머신, 섹션 헤더 테이블 위치 등 정보

  • 섹션 : 실제 코드와 데이터

  • 섹션 헤더 테이블 : 각 섹션의 위치, 크기, 타입 등을 기술

  • 각 섹션 7.3의 표 참고

  • 목적 파일(.o) → 실행 파일 → 가상 메모리

    1. .o 파일 (Relocatable Object File)
      • .text, .data, .bss, .symtab, .rel.*, .debug다양한 ELF 섹션 포함
      • 이건 중간 결과물이고 실행 불가능함
      • 컴파일러가 만든 조각들
    2. 링커(ld)가 이 조각들을 결합하여 실행파일 생성
      • 링커는 .text 섹션들을 하나로 합쳐 코드 영역 생성
      • .data, .bss도 마찬가지로 합쳐짐
      • 재배치 정보(.rel.*)와 심볼 정보(.symtab)를 참고해서 주소 수정 작업 수행
    3. 운영체제 로더가 실행파일을 메모리에 적재
      • 이때 ELF의 Program Header Table을 참고하여
      • .text → 텍스트 세그먼트 .data → 데이터 세그먼트 .bss → BSS 세그먼트
      • .symtab, .debug, .rel.* 같은 건 메모리에 올리지 않음
[스택] (상위 주소)
[   ]
[]
[BSS].bss (0으로 초기화됨)
[DATA].data (초기화된 전역/정적 변수)
[RODATA]     ← 상수
[TEXT].text (기계어 코드)

7.5 심볼과 심볼 테이블

  • 심볼(Symbol) :오브젝트 파일에서 심볼은 변수, 함수, 섹션 이름 링커는 심볼을 기반으로 함수 호출, 변수 참조 등을 서로 연결함.
종류설명
Global 정의 심볼현재 모듈에서 정의되고 다른 모듈에서 참조 가능한 심볼→ int g = 3;
Global 참조 심볼현재 모듈에서 참조하지만 정의는 다른 모듈에 있음extern int g;
Local 심볼현재 모듈에서만 사용되는 심볼 (정적 변수, static 함수 등)→ static int a;
변수 종류선언 위치키워드저장 위치수명접근 범위
지역 변수함수 내부없음스택(stack)함수 호출 중함수 내부
정적 지역 변수함수 내부static.data/.bss프로그램 전체함수 내부
전역 변수함수 외부없음.data/.bss프로그램 전체모든 파일에서 접근 가능
정적 전역 변수함수 외부static.data/.bss프로그램 전체선언된 파일 내부에서만 접근 가능
외부 변수함수 외부 참조extern참조만 함선언된 전역 변수 수명 따름외부 파일의 전역 변수 참조
레지스터 변수함수 내부register레지스터(요청)함수 호출 중함수 내부
  • .symtab : 심볼 테이블
필드의미
name문자열 테이블(.strtab)의 오프셋 (심볼 이름 위치)
value섹션 내 오프셋 또는 런타임 주소
size객체 크기 (바이트 단위)
type함수 or 데이터
bindinglocal or global
section어떤 섹션(.text, .data 등)에 속하는지
  • 특수 섹션 값
섹션 이름의미
ABS절대 주소. 재배치 필요 없음
UNDEF정의되지 않은 심볼 (외부 심볼)
COMMON초기화되지 않은 글로벌 변수 (링커가 할당 결정)

7.9 실행 가능 목적파일의 로딩

  • 7.9절은 “이미 링킹과 재배치가 끝난 실행 파일(a.out)”을 운영체제가 메모리에 어떻게 적재하고 실행하는가
  • 즉,“링커 이후의 이야기” → “로더(loader)”의 역할을 설명해줌
linux> ./prog  (== ./a.out) 
  • 이미 재배치된 상태이기 때문에 섹션에 .rel 존재하지 않음ㅏ
  • 주요 섹션: .text, .data, .rodata, .bss, .init
그림 7.15 : 실행시 메모리 구조
----------------------------------
<높은 주소>  2^48 - 1
   ↓
[     Stack (↓ 방향 성장)       ]
[              ↓               ]
[              ↑               ] 
[      Shared libraries        ]
[              ↑               ]
[ Heap (↑ 방향 성장, malloc 등) ]
[  BSS (zero-initialized data) ]
[   Initialized Data (.data)   ]
[     Read-only Data (.rodata) ]
[           Code (.text)       ]
   ↓
<낮은 주소>  0x400000
  • 실행 파일 로딩 과정 (정적 링크 기준)
1. 사용자가 실행 파일 실행 (ex: ./a.out)
2. → 쉘이 execve() 시스템 콜 호출
3. → 운영체제 커널의 로더(loader) 동작 시작
4. → ELF의 Program Header Table 읽음
5. → 각 세그먼트(.text, .data 등)를 메모리에 매핑 (mmap 등으로)
6. → 런타임 환경 준비 (stack, heap, 라이브러리 등)
7. → entry point 주소로 점프 (보통 _start → main 호출됨)

0개의 댓글