컴파일(Compile)에 대한 이해

한호성·2022년 5월 24일
1

JVM

목록 보기
1/3

Compile 에 대한 이해

개념

컴파일은 인간이 이해할 수 있는 언어로 작성된 소스코드를 CPU가 이해할 수 있는 언어 (기계어)로 변환하는 작업이다.

소스 코드는 컴파일을 통해 기계어로 이루어진 실행 파일이 된다. 이 파일을 실행하면 실행 파일 내용 운영체제의 Loader를 통해 메모리에 적재되어 동작한다.

컴파일 과정

  1. Pre-processing (전처리)
  2. compliation (컴파일)
  3. Assembly( 어셈블리)
  4. Linking (링킹)

이 4가지 과정을 묶어서 컴파일 과정, 빌드과정 이라고 부른다. 빌드 과정 (컴파일 + 링킹 )은 컴파일 과정보다 넓은 의미로 사용되는데 상황에 맞게 이해하면 좋을 거 같다.

1. 전처리 과정

전처리 과정은 전처리기를 통해 소스코드 파일을 전처리 된 소스 코드 파일로 전환하는 과정이다

  • 주석제거
  • 헤더 파일 삽입 : ex) c 언어의 #include 문을 만나면 해당하는 헤더 파일을 찾아 헤더 파일의 내용을 복사해서 소스코드에 삽입한다

2. 컴파일(Compilation) 과정

컴파일 과정은 컴파일러를 통해 전처리된 소스코드 파일을 어셈블리어 파일로 변환하는 과정이다.

이 과정에서 언어의 문법 검사 및 static한 영역의 메모리 할당을 수행한다.

컴파일러 구조

컴파일러는 3단계로 구성되어 있다. (프론트엔드-미들엔드-백엔드)

-1) 프론트 엔드

언어 종속적인 부분을 처리한다.

소스코드의 문법 검사하고 미들엔드로 넘겨주기 위한 GIMPL 트리 ( 소스코드를 트리 형태로 표현한 자료구조 ) 생성한다.

-2) 미들엔드

미들엔드에서는 아키텍쳐 비종속적인 최적화를 수행한다.

아키텍쳐 비종속적인 최적화란 CPU 아키텍처가 무엇이든 상관없이 할 수 있는 최적화를 말한다.

프론트엔드에서 념겨받은 gimple 트리를 이용해 아키텍쳐 비종속적인 최적화 수행후 백엔드에서 사용하는 rtl (고급 언어와 어셈블리 언어의 중간형태)를 생성한다.

-3) 백엔드

백엔드에서는 아키텍쳐 종속적인 최적화를 수행한다.

같은 기능을 수행하더라도 cpu 아키텍쳐별로 더욱 효율적인 명령어로 대체하여 성능을 높이는 작업

미들엔드로부터 받은 RTL을 이용해 최적화 진행후 어셈블리 코드를 생성한다.
아키텍처 종속적인 최적화 수행하면 아키텍쳐만 이해할 수 있는 언어가 되기 때문에 아키텍처가 다르면 어셈블리 코드를 해석할 수 없다.

3. 어셈블리(Assembly) 과정

어셈블리 과정은 어셈블러를 통해 어셈블리어 파일을 오브젝트 파일로 변경하는 과정이다.

오브젝트 파일 정의

어셈블리 코드는 기계어로 변환되는데 이를 오브젝트 코드라고 부른다.

*cf) 오브젝트 파일 포맷 종류는 windows 경우 PE ,Linux 같은 경우 ELF로 나뉘어진다.

오브젝트 파일 포맷 (Object File Format)

오브젝트 파일 헤더(Object File Header) : 오브젝트 파일의 기초 정보를 가지고 있는 헤더

텍스트 섹션(Text Section) : 기계어로 변환된 코드가 들어 있는 부분

데이터 섹션(Data Section) : 데이터(전역 변수, 정적 변수)가 들어 있는 부분

심볼 테이블 섹션(Symbol Table Section) : 소스 코드에서 참조되는 심볼들의 이름과 주소가 정의 되어 있는 부분.

재배치 정보 섹션(Relocation Information Section) : 링킹 전까지 심볼의 위치를 확정할 수 없으므로 심볼의 위치가 확정 나면 바꿔야 할 내용을 적어놓은 부분

디버깅 정보 섹션(Debugging Information Secion) : 디버깅에 필요한 정보가 있는 부분

*cf) 우리는 오브젝트 파일을 독립적으로 실행할 수 없다 (외부 라이브러리 파일 사용시) 전처리 과정에서 라이브러리에서 가져온 함수의 원형은 복사 했지만, 내용이 들어있지는 않기 때문이다. 즉 오브젝트 파일을 실행하기 위해서는 printf 함수를 사용하는 오브젝트 파일과 printf 함수를 구현한 오브젝트 파일을 연결시키는 작업이 필요하다 이 작업은 링킹이라고 부른다.

4. 링킹 과정

링킹과정은 링커를 통해 오브젝트 파일들을 묶어 실행 파일로 만드는 과정이다.

이 과정에서 오브젝트 파일들과 프로그램에서 사용하는 라이브러리 파일들을 링크하여 하나의 실행 파일을 만든다.

링커의 역할

링커의 역할은 크게 심볼 해석과 재배치로 나눌 수 있다.

-1) 심볼해석

심볼 해석은 각 오브젝트 파일에 있는 심볼 참조를 어떤 심볼 정의에 연관시킬지 결정하는 과정.

-2) 재배치

오브젝트 파일에 있는 데이터의 주소나 코드의 메모리 참소 주소를 알맞게 배치하는 과정

링커가 컴파일러가 생성한 오브젝트 파일을 모아서 하나의 실행 파일을 만들 때, 각 오브젝트 파일에 있는 데이터의 주소나 코드의 메모리 참조 주소가 링커에 의해 합쳐진 실행 파일에서의 주소와 다르게 때문에 그것을 알맞게 수정해줘야 한다.

각 오브젝트파일이 Linker에 의해서 실행파일로 묶여지는 사진

Reference

https://bradbury.tistory.com/226

profile
개발자 지망생입니다.

0개의 댓글