이번 포스팅에서는 컴파일하는 과정에 대해서 심도 깊게 알아보기로 하자.
일단 먼저 그림부터 그려놓고? 보겠음
먼저 위 그림에 나온 과정들은 gcc(GNU C Compiler)를 사용해서 컴파일 한다고 가정하겠다.
gcc도 이름은 컴파일러지만, 실제로 따지고 보면 컴파일러 역할을 한다기 보다 위에
전처리기, 컴파일러, 어셈블러 들을 불러오는 역할을 한다.
* abc.c -> abc.i
코딩한 c 소스파일이 전처리기를 통해 .i 파일로 바뀌는 과정이다.
cpp0 라는 전처리기를 이용하여 전처리 과정을 거치는 것인데.
쉽게 생각하여 #이 붙은 녀석들을 처리하는 것이다.
#include문 같이 특정 라이브러리를 끌어오는 역할
* abc.i -> abc.s
진짜 레알 컴파일하는 과정임. gcc에서 cc1 이라는 진짜 컴파일러를 호출한다.
그리곤 호출한 라이브러리를 참조하여 소스코드를 어셈코드로 변환시킨다.
이것이 컴파일러가 하는 역할이다.
* abc.s -> abc.o -> abc 실행파일
어셈블러를 통해 어셈블리코드가 기계어코드로 바뀌는 과정이다.
여기서 사용되는 어셈블러는 as와 collect2 를 쓴다.
이 바뀐 파일을 오브젝트 파일(object file) 이라고 하는데,
이놈은 당장 이 상태로는 실행할 수가 없다.
#include 된 내용들을 일단 기계어로 변환 시켜놓은 꼴밖에 되지 않는다.
구현된 코드(다른 오브젝트 파일)에 연결을 시켜주어야만 올바르게 실행이 된다.
이 과정을 "링크" 라고하는 것임. 이때 사용하는 '링커'는 ld라는게 있음
이때 완전히 링크를 연결시켜 실행파일을 만들면 정적링크
프로그램 실행 도중에 필요한 부분마다 연결하면 동적링크 라고 한다.
일단 직접 컴파일 과정을 눈으로 보면서 다시 한번 짚어보자.
간단한 코드를 하나 만들어 확인해보자.
다음 컴파일을 해야 하는데, 명령어가 몇개 추가 되어야 한다.
$ gcc -v --save-temp -o abc abc.c
-v : 컴파일 되는 과정을 콘솔에 출력하는 옵션
--save-temp : 컴파일 과정 시에 생성되는 파일을 없애지말고 다 보존 시켜라는 옵션
위에 컴파일 과정에서 보였던 .i, .s, .o 파일이 다 보인다.
그리고 과정을 잘 살펴보면 전처리기 cpp, 컴파일러 cc1, 어셈블러 as, collect2를 불러오는 것을
확인할 수 있음~
abc.i 의 내용
abc.s 의 내용
추가로 gcc 옵션 플레그 간단하게 몇가지 소개함.
-c : 컴파일은 하되, 링킹은 하지 않는 명령
-I : 헤더 파일이 위치한 디렉토리 경로를 지정
-L : 라이브러리 디렉토리 경로를 지정
-l : 라이브러리 지정
-E : 전처리된 코드만 표준 출력으로 내보냄
-S : 어셈블리 코드 저장
+ 추가설명
오브젝트 파일에 대한 간략한 정리
오브젝트 파일은 중요한 개념이다.
오브젝트 파일에 익숙해 지는것이 바이너리 분석에 익숙해지는 걸음마라고 할 수 있음.
아까 설명했다시피 오브젝트 파일은 컴파일 과정에서 '컴파일러'가 생성한 바이너리코드 덩어리다.
덩어리라고 표현한게 맞는지 모르겠다.
그 자체로는 제 기능을 못하고 정보를 담고만 있는 덩어리라는 느낌을 받아서 이렇게 표현함.
컴파일 과정 설명할 때는 오브젝트 파일을 그저 컴파일 과정을 통해 나온 산물이라고 밖에 말안했는데
여기서 부터는 라이브러리, 실행 파일들도 모두 오브젝트 파일의 범주에 포함시키도록 한다.
오브젝트 파일의 종류에는 3가지가 있다.
1. 실행 가능한 오브젝트 파일 (Executable object file)
2. 공유 오브젝트 파일 (Shared object file)
3. 재배치 가능한 오브젝트 파일 (Relocatable object file)
실행 가능한 오브젝트 파일은 링크까지 끝나서 당장 실행이 가능한 파일.
공유 오브젝트 파일은 동적 링크가능한 오브젝트 파일? 이라고 보면 된다.
재배치 가능한 오브젝트 파일은 어셈블러를 통해 생성된 오브젝트 파일 즉, 링크를 하지 않은 상태의
오브젝트 파일을 나타내는 말이다. 나중에 링커를 통해 재배치 가능하다는 뜻이다.
'IT 그리고 정보보안 > Knowledge base' 카테고리의 다른 글
ELF File Format (0) | 2021.04.18 |
---|---|
od(octal dump) (0) | 2021.04.18 |
Shell 실행 함수 종류 (0) | 2021.04.18 |
시스템 콜 (System Call) (0) | 2021.04.18 |
리눅스 find 명령어 활용 (0) | 2021.04.18 |