[SP] ELF File

System Programming 2014. 2. 17. 22:48

※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)


그렇다. 매우 오랜만에 System Programming 관련 포스팅이 올라왔다. 갑작스럽게 무슨 내용에 대해서 또 이 사람이 글을 쓰려나~ 하고 있을지 없을지 모르는 독자들은 생각할지 모른다. 다름이 아니라 실행 파일 구조에 대해서 공부를 하고 있어서 공부한 내용에 대해서 포스팅하려고 한다. "공부를 하고 있다"고 했다. 아직 다 하지는 않았다는 뜻이다. 오늘 공부한 내용들 정리해서 올리고 차근 차근 올리려고 한다. 원래의 내 스타일이라면 전부 공부한 다음에 한꺼번에 올리겠지만 이번에는 차근 차근 올려보려고 한다. (가끔 공부하기 싫을 때 포스팅을 하면 재미난다.)


리눅스에서의 실행 파일 구조, 즉 ELF 파일 포멧에 대해서 공부해보자. ELF 파일 포맷은 Executable and Linkable Format의 약자이다. 즉!! 실행 가능하고 링크 가능한 포멧이다. 파일 포멧을 공부하기 전에 우선적으로 알아야 할 내용들이 조금 있다. 바로 기본적인 프로그래밍 Compile/Build 하는 과정이다. 이것을 이해해야 우리는 ELF 파일에 대해서 조금 더 자세하게 공부할 수 있다. 아래의 소스 파일을 보자.


main.c


swap.c

위의 코드는 어떤 과정을 거쳐서 하나의 프로그램이 되는 것일까? 그 과정을 살펴보자.


위의 C파일들이 가장 먼저 거치는 것은 무엇일까? 컴파일러? 아니다. preprocessor다. 이 과정에서는 컴파일을 하기 전에 우선적으로 include되어있는 파일들을 직접 적어 넣어주는 과정이다. 


#include <stdio.h> 라고 선언하므로서 우리는 800줄에 달하는 stdio.h 파일을 일일이 적지 않아도 된다. preprocessor는 stdio.h의 긴 내용을 사람 대신 적어주는 아주 착한 애다. 따라서 main.c와 같은 파일들을 preprocessor를 통해서 돌리면 고작 11줄의 소스코드가 무쟈게 길게 늘어날 것이다. preprocessor를 거치면 .output이 .i 파일로 생기게 된다. 아직까지는 파일의 형태가 우리가 쉽게 읽을 수 있는 C파일이라는 점 기억하자.


다음 과정이 실제로 컴파일하는 과정이다. 컴파일을 거치면 결과물이 .s파일로 나오게 된다. 이는 system programming 포스팅을 하면서 이전에도 소개를 했던 부분이다. 예전에... 이 과정을 거치면 .s파일 즉, 어셈블리언어로 되어있는 파일이 생성된다. 


자 지금까지 우리는 main.c와 swap.c를 preprocessing하고 compiling했다. 이 과정에서 우리가 가지고 있는 파일은 main.i main.s 그리고 swap.i swap.s이다. (물론 preprocessing/compiling 과정에서 생기는 output들을 전부 적어놓을 경우에 해당하는 이야기이다.) 


그 다음에 거치는 것이 assembler이다. assembler는 .s파일을 input으로하여 .o 파일의 output을 내놓는다. .o 파일은 object file을 의미한다. 자!! 여기서부터다. 보통 여기서부터의 파일을 ELF 파일이라고 한다. 아래의 그림으로 정리해보자.


위와 같이 정리될 수 있다. 기본적으로 어셈블러를 거친 후의 파일인 .o파일부터 그 이후는 object file이라고 말한다. 그렇다면 Unix/Linux에서는 저 object file의 구조를 ELF라고 하고 Windows에서는 PE 구조라고 한다. 우리는 Unix/Linux 구조에서 공부하고 있으므로 ELF를 공부하고 있는 것이다.


그렇다면 여기서 질문이 나올 수 있다. .o파일과 여러 개의 .o파일들이 링크되어 만들어진 a.out 파일은 어떻게 다른 것인가? 기본적으로 object file은 아래의 세 가지의 형태를 띈다. 


- Relocatable object file

- Executable object file

- Shared object file


자꾸 object file~ object file 하는데... 무서워할 필요 없다. 그냥 상식적으로 프로그램을 돌리기 위해서는 필요한 요소들이 binary 형태로 나열되어있는 형태의 파일이라고 생각해보자. 가령 아래와 같이 그냥 0101 연속의 형태를 띈 파일일 뿐이다.


0101의 연속의 파일일 뿐인데 특정 영역은 예를 들어 기계어 코드에 해당하는 부분이고 어떤 부분은 프로그램에서 사용하는 변수들에 대한 정보를 담고 있고.. 등등일 뿐이다. (위의 그림은 object file이 별개 아니라는 것을 설명하기 위해서 아무렇게나 막 작성한 것이니 실제 ELF 파일과 비교하지 말자)

Relocatable object file부터 하나하나 설명을 시작할 생각이다. 아!! 한가지 알아두자 Shared object file은 Relocatable object file의 다른 형태라는 것이다. 음.. 뭔가 부족한가? 그래!! 위의 세 가지 type의 object file을 간략하게 맛을 보고 이번 포스팅을 마쳐야겠다. 그래야 나중에 더 이해하기 쉬울 것 같다.


Relocatable object file은 executable object file이 되기 위해 다른 relocatable object file과 결합할 수 있는 파일이다. 


Shared object file은 조금 특별한 형태의 Relocatable object file로 볼 수 있다. 일반적인 relocatable object file처럼 executable object file이 되기 위해 다른 relocatable object file 또는 shared object file과 결합할 수 있으며, 프로그램이 실행 중일 때(run-time) dynamic하게 링크될 수도 있다.(이 두번째 특징 때문에 조금 특별한 형태의 relocatable object file로 정의될 수 있다.)


Executable object file은 메모리에 직접적으로 올라가서 실행될 수 있는 형태의 파일을 의미한다.


자 이제 대충 각각이 어떤 것인지는 설명했다. 다음 포스팅에서 relocatable object file에 대해서 자세하게 이야기해보기로 하자. 조금 포스팅이 짧을 지도 모른다. 왜냐하면 다음 포스팅이 조금 길어질 꺼니까... relocatable object file의 member variable 하나하나 다 설명하려면 아우 장난아니겠다.

Posted by 빛나유
,