Linux
gcc compiler - 1부
chbae
2023. 4. 18. 14:35
728x90
유닉스 리눅스 필수 유틸리티 도서 3부 (컴파일과 링킹)을 보고 정리해보고자 한다. 그 첫번째 순서로 3부 4장. gcc compiler에 대해서 알아본다.
1. 컴파일의 의미
인간이 이해할 수 있는 형식 언어 (C, C++등)로 작성된 소스코드를 CPU가 이해할 수 있는 기계어(machine instruction)로 번역하는 과정
gcc로 빌드할 대 -g 옵션을 주면 이후 objdump -S 옵션으로 생성된 결과 파일의 디버깅 정보와 함께 instruction, instruction에 대응하는 assemble 코드를 함께 볼 수 있다.
$ gcc -g -o like like.c
$ objdump -S like
2. 알아 두면 정말 유용한 C 소스 컴파일 과정
/usr/bin/gcc는 실제 컴파일 과정을 담당하지 않고 전처리기와 C 컴파일러, 어셈블러, 링크럴 각각 호출해주는 역할만 담당한다.
1) C 소스의 전체 컴파일 과정
- cc1: C 컴파일러, -E 옵션을 붙이면 C 전처리기로 동작
- cc1plus: C++ 컴파일러, -e 옵션을 붙이면 c++ 전처리기로 동작
- collect2: 링커 (내부에서 링크인 ld를 호출해 링크함)
- f951: 포트란 컴파일러
위의 과정을 gcc 컴파일시 확인해 보고 싶으면 "gcc -v -save-temps -o like like.c" 처럼 -v와 -save-temps 옵션을 주면 된다.
- -v 옵션: 컴파일 되는 과정을 화면에 출력
- -save-temps 옵션: 컴파일 과정에서 발생되는 중간 파일을 지우지 말고 저장
2) cc1 -E에 의한 전처리 과정
- header 파일 삽입
- macro 치환 및 적용
3) cc1에 의한 assemble 소스 파일로 컴파일 (실제 컴파일 단계)
- front-end: 언어 종속적인 부분 처리
소스 코드가 올바르게 작성되었는지 분석하고, middle end에 넘겨주기 위한 GIMPLE 트리(소스 코드를 트리 형태로 표현한 자료구조)를 생성 - middle-end: 아키텍처 비 종속적 최적화
GIMPLE 트리를 이용해 아키텍처 비종속적인 최적화 수정 후 back end에서 사용하는 RTL(Register Transfer Language: 고급 언어와 assemble 언어 중간형태) 생성. cc1에서 수행하는 최적화 중 많은 부분이 여기서 이루어짐. - back-end: instruction scheduling, register allocation
아키텍처 비종속적/종속적 최적화 수행하고 이후 object 코드(assemble 코드) 생성
front/middle/back end에 대한 아주 자세한 설명은 아래 참고로 나온 도서를 보기 바란다.
4) as에 의한 기계어 코드 생성
as에 의해 생성되는 object파일은 ELF 바이너리 포맷 구조를 가진다.
위의 그림은 전형적인 ELF relocatable object file 구조이다.
- .text: instruction이 들어 있는 부분
- .rodata: read only data 가 있는 부분
- .data: data가 들어가 있는 부분
- .bss: 초기 값이 0인 전역변수가 들어가는 부분
참고 (명령어)
- readelf -a [object 파일이름]: ELF 헤더 정보를 볼 수 있음
- xxd [object 파일이름]: object 파일 구조를 볼 수 있음
5) collect2에 의한 링킹 과정
최종적으로 표준 C 라이브러리와 링크된다.
참고
- ELF 파일 포맷과 구조: https://fiv3star.wordpress.com/2011/10/10/63/
- 유닉스 리눅스 프로그래밍: http://www.yes24.com/24/Goods/4157871?Acode=101