seven05
[CSAPP] 7.Linking 링킹 (7.1,7.4,7.9) 본문
(7단원 전체를 볼수있으면 당연히 좋지만 시간이 모자라는 관계로 일단은 코치님이 강조하신 부분들만 볼수밖에없었다.
다음에 시간이 생기면 다시 추가로 공부해보자!)
링킹이란?: 링킹(Linking)이란 프로그램 코드 및 데이터의 조각들을 결합하여 메모리에 로드되어 실행될 수 있는 하나의 실행 파일을 만드는 과정
링커(Linker)는 링킹을 수행하는 프로그램, 각 모듈의 독립적인 컴파일을 가능하게 함
링킹을 공부해야하는이유?
- 큰 규모의 프로그램을 개발하면서 링킹과 관련된 에러를 많이 만나기때문
- 프로그래밍 언어의 스코프규칙이 어떻게 구현되는지 이해(지역변수와 전역변수의 차이 static의 의미)
- 공유 라이브러리를 활용할줄 알아야하기때문
- 링킹과 관련된 많은 시스템 개념들을 이해하기위해
링킹 종류
- 컴파일 타임에 이뤄지는 정적 링킹(Static Linking)
- 로드 타임 시 이뤄지는 공유 라이브러리의 동적 링킹(Dynamic Linking of Shared Libraries at Load Time)
- 런타임 시 이뤄지는 공유 라이브러리의 동적 링킹(Dynamic Linking of Shared Libraries at Run Time)
7.1 컴파일러 드라이버
컴파일러 드라이버란 전처리기(preprocessor), 컴파일러, 어셈블러, 그리고 링커를 요구사항에 따라 차례대로 실행시켜주는 프로그램이다. 대표적으로 gcc 가 이에 해당한다.
Linux> gcc -Og -o prog main.c sum.c
라고 입력한다고 가정해보자. gcc는 4번의 단계에 걸쳐서 실행가능한 객체(executable object)를 생성한다.
- C 전처리기 cpp(C Preprocessor)를 돌린다. 이는 C 소스파일 main.c 를 ASCII 중간파일인 main.i로 번역
cpp [other arguments] main.c /tmp/main.i - C 컴파일러(cc1)를 돌려서 main.i를 ASCII 언어파일인 main.s로 번역
cc1 /tmp/main.i -Og [other arguments] -o /tmp/main.s - 어셈블러(as)를 돌려서 main.s를 재배치 가능한 목적파일인 main.o로 번역한다.
as [other arguments] -o /tmp/main.o /tmp/main.s
(sum.o도 위와 같은 과정을 반복해서 만들어준다.) - 마지막으로 링커프로그램(ld)를 실행해서 실행가능한 목적파일 prog를 생성하기위해 main.o와 sum.o를 연결한다.
ld -o prog [system object files and args] /tmp/main.o /tmp/sum.o
7.4 재배치 가능한 목적파일
(이 부분은 사진 한장과 함께 기능별로 구간이 나눠져있어서 이해를 한다기보다는 아 그렇구나의 느낌에 가깝다.)
위의 그림은 ELF포맷을 따르는 재배치 가능한 오브젝트 파일의 내부구조를 나타낸다.
- ELF 헤더: word size나 byte 순서와 같은 시스템의 속성정보를 저장,링커가 이파일을 읽어서 분석할 때 알아야하는 정보들 저장 (헤더의 크기, 파일 유형, 타겟머신-유형 x86-64 등등)
- .text: 컴파일된 프로그램의 기계어 코드들
- .rodata: 문자열같은 상수나 switch 점프 테이블 같은 읽기전용값 저장
- .data: 0이 아닌 값으로 초기화되는 전역 변수 및 static 변수(non-static 지역 변수는 스택에 저장됨)
- .bss: (Block Started by Symbol) 0으로 초기화되거나 초기화 되지 않는 전역 변수 및 static 변수들이 저장. 프로그램이 실행되기 전까지는 메모리를 차지하지 않는다 ( 어차피 전부 0으로 초기화될 것이기 때문에 미리 공간을 차지하고 있을 필요가 없다.)
- .symtab: 이 모듈에서 정의 or 참조 하는 모든 심볼들의 정보를 저장(함수, 전역변수, static 변수)
- .rel.text: (relocation) 링킹 시 재배치가 필요한 .text 섹션 내 메모리 로케이션들의 정보 저장 (외부 함수를 호출하거나 전역변수를 참조하는 명령어들은 재배치가 필요하기때문)
- .rel.data: (relocation) 링킹 시 재배치가 필요한 .data 섹션 내 메모리 주소 정보를 저장(bss의 데이터들은 어차피 0으로 초기화 되므로 재배치 작업이 필요가 없다.)
- .debug: 정의 or 참조 하는 전역변수, C 소스 파일 등 디버깅에 필요한 정보들 저장 (-g 옵션에만 포함)
- .line: 원본 C 소스 파일의 라인들과 .text 섹션에 존재하는 기계어 코드들의 맵핑 정보가 저장(-g 옵션에만 포함)
- .strtab: .symtab 과 .debug 에 존재하는 문자열들을 저장
- Section Header Table: 각 섹션의 크기와 위치 정보 저장
7.9 실행 가능 목적파일의 로딩
Linux> ./prog -> 로더(loader) 실행 (로더는 메모리에 언제나 상주) -> 디스크에 있는 실행 파일로부터 프로그램의 코드와 데이터를 메모리에 복사 -> Entry Point에 해당하는 첫 번째 명령어의 주소로 점프함으로써 해당 프로그램을 실행
이러한 과정을 로딩(loading)이라 한다.
코드 세그먼트, 데이터 세그먼트, 런타임 힙(heap)(malloc을 할때마다 주소가 큰 방향으로 확장), 공유 라이브러리 영역, 유저 스택(유저가 접근가능한 가장큰 주소에서 부터 작은 방향으로 확장), 커널의 코드와 데이터를 위한 영역 순서대로 메모리 주소가 커지는 방향으로 예약된다
참조: CSAPP, [CSAPP] Linking (tistory.com), [CS:APP] Chapter 7. Linking (velog.io)
'SW JUNGLE 9기 > CSAPP' 카테고리의 다른 글
[CSAPP] 8. 예외적인 제어흐름(8.1,8.5) (0) | 2024.09.05 |
---|---|
[CSAPP] 3.7~3.9,11 어셈블리어가 함수와 배열을 표현하는 방법 (3) | 2024.09.04 |
[CSAPP] 3.1~3.6 어셈블리어 공부 (3) | 2024.09.04 |
[CSAPP] 부동소수점 부분 공부하다가 발견한 신기한 알고리즘 1/sqrt(x) (2) | 2024.09.04 |