
2025.04.22
오늘한 내용 : CS - 링커 ~7.5, 7.9
WEEK06: 메모리 누수, 균형 이진 탐색 트리(AVL Tree, Red-Black Tree)
gcc와 같은 컴파일러 드라이버(driver)는 다음 네 단계를 자동으로 실행| 단계 | 역할 | 명령어 예시 |
|---|---|---|
| 전처리 | 매크로 처리, 헤더 포함 | cpp main.c → main.i |
| 컴파일 | C → 어셈블리 변환 | cc1 main.i → main.s |
| 어셈블 | 어셈블리 → 목적 코드 변환 | as main.s → main.o |
| 링크 | 목적 코드 → 실행파일 생성 | ld main.o sum.o → prog |
ld (링커)sum() 함수가 sum.c에 정의되어 있고 main.c에서 참조됨main.o의 참조를 sum.o의 정의와 연결오브젝트 파일(object file)은 기계어로 번역된 중간 결과물로, 컴파일 또는 어셈블 후 생성되는 파일임. 실행 파일이 아니며, 링커(linker)에 의해 다른 오브젝트 파일들과 합쳐져 실행 파일로 만들어짐.
| 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 |
ELF 헤더 : 바이트 순서, 워드 크기, 파일 타입, 대상 머신, 섹션 헤더 테이블 위치 등 정보
섹션 : 실제 코드와 데이터
섹션 헤더 테이블 : 각 섹션의 위치, 크기, 타입 등을 기술
각 섹션 7.3의 표 참고
목적 파일(.o) → 실행 파일 → 가상 메모리
.o 파일 (Relocatable Object File).text, .data, .bss, .symtab, .rel.*, .debug 등 다양한 ELF 섹션 포함ld)가 이 조각들을 결합하여 실행파일 생성.text 섹션들을 하나로 합쳐 코드 영역 생성.data, .bss도 마찬가지로 합쳐짐.rel.*)와 심볼 정보(.symtab)를 참고해서 주소 수정 작업 수행.text → 텍스트 세그먼트 .data → 데이터 세그먼트 .bss → BSS 세그먼트.symtab, .debug, .rel.* 같은 건 메모리에 올리지 않음[스택] (상위 주소)
[ ]
[힙]
[BSS] ← .bss (0으로 초기화됨)
[DATA] ← .data (초기화된 전역/정적 변수)
[RODATA] ← 상수
[TEXT] ← .text (기계어 코드)
| 종류 | 설명 |
|---|---|
| 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 데이터 |
| binding | local or global |
| section | 어떤 섹션(.text, .data 등)에 속하는지 |
| 섹션 이름 | 의미 |
|---|---|
ABS | 절대 주소. 재배치 필요 없음 |
UNDEF | 정의되지 않은 심볼 (외부 심볼) |
COMMON | 초기화되지 않은 글로벌 변수 (링커가 할당 결정) |
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 호출됨)