ELF 란 용어를 많이 들어보셨을텐데요, ELF는 Executable and Linking Format의 약어입니다. UNIX / LINUX 기반에서 사용되는 실행 및 링킹 파일 포맷입니다. 이번 글에서는 ELF 파일 포맷에 대해 알아보겠습니다.
개념 및 사전 지식 정의
ELF는 하나의 ELF Header와 파일데이터로 구성되어 있습니다. 아래 그림을 보시면 파일의 가장 위에 ELF Header 정보가 들어있고, 그 아래 program header table이 있습니다. 그 이후 Segment 정보와 Section 관련 정보들이 나오네요.
ELF header |
Program header table |
Segment 1 |
Segment 2 |
... |
Section header table optional |
ELF header는 ELF 파일의 Metadata를 가진 Header일텐데 Segment와 Section은 뭘까요? 그리고 ELF 포맷을 이해하기 위해 필요한 개념들이 무엇인지 정리하고
Segment
: 동일한 메모리 속성(read-only, writable, ...)을 가진 하나 또는 그 이상의 섹션의 집합Section
: 특정 정보(machine instructions, symbol table, ..)를 포함하고 있는 ELF file의 작은 조각Symbol
: ELF file내에 저장된 함수 또는 변수의 디스크립션입니다. 간단한 함수 또는 변수의 정보를 포함하고 있습니다.Objec file
: 컴퓨터에서 읽을 수 있는 소스파일 버전입니다. Object file은 소스파일의 전역, 정적 변수 이름같은 심볼 정보들이 아직 남아있는 파일입니다. 하지만 이 파일은 메모리에 어떻게 로드되어야 하는지 정보가 명시되어 있지 않기 때문에 직접 실행은 불가능합니다.Shared Library
: 하나 또는 그 이상의 Object 파일의 심볼들로 구성된 파일입니다. 주소 공간 어디에든 로드 되어질 수 있습니다.Executables
: Shared Library와 매우 유사하지만 메모리 내 특정 주소에 로드될 수 있는 파일입니다. 프로그램 시작을 위한 함수를 가지고 있습니다. 해당 함수에서 Executables 파일은 시작됩니다.Core Files
: ELF 의 특별한 타입의 파일입니다. 실행된 프로세스에 의해 사용된 여러 메모리 세그먼트 들을 포함한 메모리 이미지 정보를 가지고 있습니다.Linking
: object 파일들로 부터 심볼 정도들을 가져와 특정 순서에 맞게 정렬을 해주는 과정입니다. 오브젝트의 각 섹션들을 공유 라이브러리나 실행파일 내에 각 세그먼트내에 정렬해 주는 과정입니다.
- ELF Header
보시면 struct Elf64_Ehdr 구조체에 매핑되어 질 수 있습니다. 각 변수의 이름과 사이즈는 왼쪽 표를 참고해 주세요. 내용을 보시면 ELF의 매직넘버를 포함하는 e_ident 변수를 시작으로 타입이나 아키텍쳐 정보 그리고 처음들어보시는 분들도 계실텐데 프로그램 헤더나 섹션 헤더에 관련된 정보들이 들어있습니다. 프로그램 헤더와 섹션 헤더는 뒤에서 계속 알아볼 예정입니다. 궁금증은 잠시 묻어두고 조금씩 분석해보겠습니다.
테스트 프로그램을 빌드한 후 만들어진 ELF 파일을 hex형태로 표현해보고 구조체에 매칭해 보겠습니다. 처음 8바이트는 e_ident 값이라고 했습니다. 이 안에 매직넘버가 포함되어 있는데 오른쪽 스트링 값을 보면 ELF란 문자열이 보이네요. ELF의 매직넘버는 16진수로 0x7f 0x45 0x4c 0x46 입니다. 그럼 이 파일이 ELF인지 아닌지 판단할 수 있는 소중한 정보가 될 수 있겠네요.
그 뒤로 e_type, e_machine, e_version등의 정보가 연속되어 위치하고 있습니다. 그럼 그 뒤에 연속된 영역도 위에서 말씀드린 구조체와 매칭시켜 보시죠. 아래 보면 e_flags, e_ehsize 등에 매칭되어 집니다.
위의 16진수 정보로는 분석하기 쉽지 않습니다. 이 때 쉽게 ELF를 분석할 수 있는 툴이 readelf 입니다. 이 툴을 이용해서 어떻게 분석할 수 있는지는 readelf 를 설명하는 글이 아니라 자세하게 다루지는 않겠습니다. 그럼 readelf로 ELF Header를 출력한 결과를 보시죠.
readelf -h 옵션은 ELF Header를 출력하는 옵션입니다. 그럼 위에서 나온 정보와 매칭해서 살펴보시죠. Magic Number는 ELF 파일을 설명하고 있습니다. 그리고 ELF64이며 little endian이네요. Machine 정보는 x86-64네요. 이 정도로도 이 ELF 파일의 내용을 살펴볼 수 있습니다. 그리고 추가로 살펴볼 내용이 있는데요. 하늘색, 노란색 테두리로 표시된 Program 과 Section Header에 관련된 정보들입니다. 이 내용들을 자세히 살펴봐 주세요. 각 Header들이 어디에 위치하고 있는지 헤더의 크기는 얼마인지가 나와있습니다. Program Header와 Section Header는 다음 글에서 자세히 살펴보겠습니다.
[참고자료]
Tool Interface Standards – Portable Formats Specification, Version 1.1
Self-Service Linux , MarkWilding and Dan Behman
How To Write Shared Libraries, Ulrich DrepperLinking, Randy Bryant and Dave O’Hallaron
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
http://man7.org/linux/man-pages/man5/elf.5.html
http://egloos.zum.com/recipes/v/5010841
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
https://en.wikipedia.org/wiki/Weak_symbol
'Linux > Debugging & Testing' 카테고리의 다른 글
[ELF] Sections and the Section header table (0) | 2018.09.07 |
---|---|
[ELF] Segment와 Program Header (1) | 2018.08.29 |
[커널분석] Architecture 별 분석을 위한 설정 (ctags & cscope) (0) | 2018.08.21 |
[gdb] The GNU Debugger : 3. Stack 정보 분석하기 (0) | 2018.08.15 |
[gdb] The GNU Debugger : 2. 중단점 설정하기 (0) | 2018.08.14 |