Post

컴파일러 - 실행파일 구조

실행파일 구조

1. 개요

우리가 프로그램을 사용할 때 많은 파일들을 접하고 윈도우의 경우 더블클릭으로 리눅스의 경우 명령어로 간단히 실행하지만
실제로 실행하는 가능한 파일의 형태는 한정되어있다.

2. PE FILE FORMAT (윈도우)

윈도우에서 실행 가능한 파일은 모두 PE 파일 포맷을 따르며 해당 파일의 확장자는 아래와 같다.

  • 실행 파일 : EXE, SCR
  • 라이브러리 : DLL, OCX
  • 드라이버 : SYS
  • 오브젝트 파일 : OBJ

(OBJ는 간접적으로든, 직접적으로든 실행할 방법은 없지만 스펙상으로는 PE 파일 포맷을 따른다)

PE 파일의 구조를 나타내면 아래와 같다.

img.png

세부적인 섹션 크기의 경우 파일에 따라 다르며, section header의 경우에도 어떤 섹션은 있고 어떤 섹션은 없는 식으로 달라질 수 있다. 오른쪽의 숫자는 offset으로 0번지부터 몇 개의 바이트로 이루어져있느냐를 말한다.

1) PE Header

DOS header 부터 Section header까지를 모두 더해서 PE HEADER라고 한다.

a. DOS header

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct _IMAGE_DOS_HEADER {     
    WORD   e_magic;          // DOS signature : 4D5A ("MZ")
    WORD   e_cblp;                    
    WORD   e_cp;                      
    WORD   e_crlc;                    
    WORD   e_cparhdr;                 
    WORD   e_minalloc;                
    WORD   e_maxalloc;                
    WORD   e_ss;                      
    WORD   e_sp;                      
    WORD   e_csum;                    
    WORD   e_ip;                      
    WORD   e_cs;                      
    WORD   e_lfarlc;                  
    WORD   e_ovno;                    
    WORD   e_res[4];                  
    WORD   e_oemid;                   
    WORD   e_oeminfo;                 
    WORD   e_res2[10];                  
    LONG   e_lfanew;         // offset to NT header 
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

제일 앞에 MZ 시그니처(DOS 실행파일 설계자인 Mark Zbikowski 의 이니셜)가 2바이트로 기재되어있으며 e_lfanew는 NT header가 어디부터 시작하는지 offset을 가르키고 있다.

b. DOS stub

이 부분은 있어도 되고 없어도 되는 옵션부분이다. 사실 DOS stub은 없어도 실행간에는 아무런 문제가 없다. 다만 notepad.exe를 열어보면 이부분이 있는 것을 확인 할 수 있는데, DOS에서 실행시 “This program cannot be run in DOS mode”라고 출력되게 되어있다.

따라서 이 부분의 존재 유무는 개발툴에 의존한다.

c. NT header

1
2
3
4
5
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                          // PE Signature : 50450000 ("PE"00)
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

NT 헤더는 처음에 PE 라는 시그니처를 4Bytes로 갖고 시작하며 그 아래로는 FileHeader와 OptionalHeader를 갖는다. FileHeader의 구조체는 아래와 같다.

1
2
3
4
5
6
7
8
9
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

여기서 중요한건 총 4가지 값이다.

  • Machine : CPU 별로 고유한 값이있는데, 32 bit intel의 경우 0x014c, 64bit intel의 경우 0x0200을 갖는다.
  • NumberOfSections : 총 세션의 개수이며, 코드, 데이터, 리소스 등이 각각 섹션에 나눠서 저장되기 때문에 최소 1 이상이다.
  • sizeOfOptionalHeader : 실제 OptionalHeader의 크기는 정해져있지만 윈도우에서는 이 값을 가지고 OptionalHeader의 크기를 인식한다.
  • Characteristic : 실행 가능한지 혹은 DLL 인지 bit OR로 조합되어있으며 내용은 아래와 같다.
값 (16진수)플래그 이름설명
0x0001IMAGE_FILE_RELOCS_STRIPPED재배치 정보(relocations)가 제거됨
0x0002IMAGE_FILE_EXECUTABLE_IMAGE실행 가능한 이미지임
0x0004IMAGE_FILE_LINE_NUMS_STRIPPED라인 번호 정보(line numbers)가 제거됨
0x0008IMAGE_FILE_LOCAL_SYMS_STRIPPED로컬 심볼(local symbols)이 제거됨
0x0010IMAGE_FILE_AGGRESIVE_WS_TRIM워크셋(workset) 공격적 축소
0x0020IMAGE_FILE_LARGE_ADDRESS_AWARE2 GB 초과 주소 공간을 사용할 수 있음
0x0080IMAGE_FILE_BYTES_REVERSED_LO저(低) 바이트 순서가 뒤바뀜(사용 안 함)
0x0100IMAGE_FILE_32BIT_MACHINE32비트 머신용
0x0200IMAGE_FILE_DEBUG_STRIPPED디버그 정보가 제거됨
0x0400IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP스왑 파일에서 실행 (이동식 미디어)
0x0800IMAGE_FILE_NET_RUN_FROM_SWAP스왑 파일에서 실행 (네트워크 드라이브)
0x1000IMAGE_FILE_SYSTEM시스템 파일
0x2000IMAGE_FILE_DLLDLL
0x4000IMAGE_FILE_UP_SYSTEM_ONLY멀티프로세서 사용자 모드(UP) 시스템 전용
0x8000IMAGE_FILE_BYTES_REVERSED_HI고(高) 바이트 순서가 뒤바뀜(사용 안 함)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;
    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

_IMAGE_OPTIONAL_HEADER에서 주요 값들은 아래의 10개이다.

  • Magic : 해당 파일이 32비트(PE32)인지 64비트(PE32+)인지를 나타내는 값
  • AddressOfEntryPoint : 프로그램이 시작되는 코드의 가상 주소(RVA)
  • ImageBase : 로드될 때 기본적으로 매핑되는 메모리 상의 시작 주소
  • SectionAlignment : 메모리에 로드할 때 각 섹션의 정렬 단위(바이트)
  • FileAlignment : 디스크상에 저장될 때 각 섹션의 정렬 단위(바이트)
  • SizeOfImage : 메모리에 로드된 전체 이미지(헤더 + 모든 섹션 포함)의 크기 (바이트)
  • SizeOfHeader : DOS 헤더, PE 헤더 및 모든 섹션 헤더를 합친 크기 (바이트)
  • Subsystem : 이 실행 파일이 어떤 환경에서 동작할지를 지정
  • NumberOfRvaAndSizes : 데이터 디렉터리(Data Directory)의 엔트리 개수
  • DataDirectory : 배열의 각 항목마다 정의된 값을 가지게 되는데 그 값은 아래와 같다.
인덱스디렉터리 이름설명
0EXPORT_TABLE이 모듈이 외부에 제공(export)하는 함수·데이터의 목록 및 주소 테이블
1IMPORT_TABLE모듈이 참조(import)하는 외부 DLL의 함수·데이터 목록 및 주소 테이블
2RESOURCE_TABLE리소스 섹션(.rsrc)의 시작 주소와 크기 (아이콘, 문자열 테이블, 대화상자 리소스 등)
3EXCEPTION_TABLE예외 처리 루틴과 언와인드 정보(64-bit의 경우 사용됨)
4CERTIFICATE_TABLE디지털 서명(Certificate Table)의 시작 주소와 크기
5BASE_RELOCATION_TABLE재배치(relocation) 정보(.reloc 섹션)의 시작 주소와 크기
6DEBUG디버그 정보(심볼, 매핑 정보 등)의 시작 주소와 크기
7ARCHITECTURE예약(과거 IA-64용으로 사용되었으나 현재 무의미)
8GLOBAL_PTR전역 포인터(global pointer) 테이블 주소 (MIPS 등 특정 아키텍처용)
9TLS_TABLEThread-Local Storage 초기화 및 콜백 정보
10LOAD_CONFIG_TABLE보안 쿠키, 스택 검사, SEH 보호 등 로드 구성 정보
11BOUND_IMPORT바인드된 임포트 목록(Import Table과 함께 사용, 로딩 시 바인딩 최적화)
12IAT실제 Import Address Table(Import Table과 유사하지만, 실행 시 패치된 주소를 담음)
13DELAY_IMPORT_DESCRIPTOR지연 로딩(Delay-Load) DLL의 목록 및 로딩 시점 정보
14CLR_RUNTIME_HEADER.NET 어셈블리용 CLR 헤더(.NET 런타임 메타데이터 시작 주소와 크기)
15RESERVED예약(향후 확장 또는 특별 용도로 사용될 수 있음)

d. Section header

각 섹션의 속성을 정의하기 위한 헤더이다. 기본적인 섹션 헤더의 구조는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define IMAGE_SIZEOF_SHORT_NAME              8

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  • VirtualSize : 메모리에서 섹션이 차지하는 크기
  • VirtualAddress : 메모리에서 섹션의 시작 주소 (RVA)
  • SizeOfRawData : 파일에서 섹션이 차지하는 크기
  • PointerToRawData : 파일에서 섹션의 시작 위치
  • Characteristics : 섹션의 특징 (bit OR), 아래의 표를 참조하면 된다.
값 (16진수)플래그 이름설명
0x00000008IMAGE_SCN_TYPE_NO_PAD섹션 패딩 없음
0x00000020IMAGE_SCN_CNT_CODE실행 코드(.text) 섹션
0x00000040IMAGE_SCN_CNT_INITIALIZED_DATA초기화된 데이터(.rdata/.data) 섹션
0x00000080IMAGE_SCN_CNT_UNINITIALIZED_DATA초기화 안 된 데이터(.bss) 섹션
0x00000100IMAGE_SCN_LNK_OTHER기타 링커 제어
0x00000200IMAGE_SCN_LNK_INFO디버그/설명용 정보
0x00000800IMAGE_SCN_LNK_REMOVE링커가 제거할 섹션
0x00001000IMAGE_SCN_LNK_COMDATCOMDAT(overloadable) 섹션
0x00008000IMAGE_SCN_GPREL전역 포인터 상대 주소 사용
0x00020000IMAGE_SCN_MEM_PURGEABLE퓨저블(purgeable)
0x00040000IMAGE_SCN_MEM_LOCKED메모리 잠김
0x00080000IMAGE_SCN_MEM_PRELOAD미리 로드
0x00100000IMAGE_SCN_ALIGN_1BYTES1바이트 정렬
0x00200000IMAGE_SCN_ALIGN_2BYTES2바이트 정렬
0x00300000IMAGE_SCN_ALIGN_4BYTES4바이트 정렬
0x00400000IMAGE_SCN_ALIGN_8BYTES8바이트 정렬
0x00500000IMAGE_SCN_ALIGN_16BYTES16바이트 정렬
0x00600000IMAGE_SCN_ALIGN_32BYTES32바이트 정렬
0x00700000IMAGE_SCN_ALIGN_64BYTES64바이트 정렬
0x00800000IMAGE_SCN_ALIGN_128BYTES128바이트 정렬
0x00900000IMAGE_SCN_ALIGN_256BYTES256바이트 정렬
0x00A00000IMAGE_SCN_ALIGN_512BYTES512바이트 정렬
0x00B00000IMAGE_SCN_ALIGN_1024BYTES1 024바이트 정렬
0x00C00000IMAGE_SCN_ALIGN_2048BYTES2 048바이트 정렬
0x00D00000IMAGE_SCN_ALIGN_4096BYTES4 096바이트 정렬
0x00E00000IMAGE_SCN_ALIGN_8192BYTES8 192바이트 정렬
0x01000000IMAGE_SCN_LNK_NRELOC_OVFL재배치 수 초과(OVFL)
0x02000000IMAGE_SCN_MEM_DISCARDABLE디스크로부터 제거 가능(discardable)
0x04000000IMAGE_SCN_MEM_NOT_CACHED캐시 불가
0x08000000IMAGE_SCN_MEM_NOT_PAGED페이징 불가
0x10000000IMAGE_SCN_MEM_SHARED공유 메모리
0x20000000IMAGE_SCN_MEM_EXECUTE실행 가능
0x40000000IMAGE_SCN_MEM_READ읽기 가능
0x80000000IMAGE_SCN_MEM_WRITE쓰기 가능

※ VA? RVA?

몇몇 속성의 주소가 RVA로 나타나있는 것을 확인 할 수 있는데 여기서 RVA란 상대적 가상주소(Relative Virtual Address)를 말한다.
이 RVA를 말하기 위해서는 먼저 VA부터 알아야하는데 VA는 가상 주소(Virtual Address)를 말한다.
아마 OS시간에 페이징과 가상 메모리 주소에 대해서 배웠을 것이다. (혹시 배우지 않았다면? 이곳 을 참고하라)

페이징간에 말하는 가상 메모리 주소가 바로 이 VA인데, RVA는 Optional_header에 있는 ImageBase 주소에서 부터 상대 주소를 말한다. 만약 RVA를 VA로 바꾸고 싶다면 아래와 같이 바꿀 수 있다.

\[RVA + ImageBase = VA\]

위와 같은 구조를 따른다면 주소의 relocation이 일어나도 기준 위치(ImageBase)에 대한 상대주소가 바뀐게 아니기 때문에 해당 주소를 찾아갈 수 있다.

2) PE Body

Section

실질적으로 프로그램이 실행될 때 사용되는 코드와 데이터가 저장된 부분이다.
해당 섹션에 대한 크기와 속성은 각 섹션에 해당하는 IMAGE_SECTION_HEADER에 명시되어있다.

아래의 정보는 일반적으로 많이 사용하는 섹션에 대해서 적어둔 것이며, 개발자가 임의의 커스텀된 섹션을 제작할 수도 있다. 물론 그 경우에는 section header에 형식에 따라 관련 내용을 기재해두어야한다.

a. .text 섹션

실제 프로그램이 실행되는 코드이다. 실행 파일을 olly dbg 같은 걸로 뜯어볼때 실제 실행되는 코드들이 포함된 곳이다.
라이브러리 호출이나, 분기, 루프, 조건문 등이 모두 포함되어있으며 컴파일된 함수들이 포함되어있다.

해당 text 섹션의 header의 Characteristics 값은 아래와 같은 값을 포함한다.

  • IMAGE_SCN_CNT_CODE : 0x00000020
  • IMAGE_SCN_MEM_EXECUTE : 0x20000000
  • IMAGE_SCN_MEM_READ : 0x40000000

b. .data 섹션

초기화된 전역 변수나 정적 변수를 담는데 사용되는 섹션이다. 구조체나 배열, 변수등 초기화된 데이터를 담는데 사용되며 주소값이 지정되어야하는 포인터 배열 역시 해당 섹션에 포함된다.

해당 data 섹션의 header의 Characteristics 값은 아래와 같은 값을 포함한다.

  • IMAGE_SCN_CNT_INITIALIZED_DATA : 0x00000040
  • IMAGE_SCN_MEM_READ : 0x40000000
  • IMAGE_SCN_MEM_WRITE : 0x80000000

c. .rdata 섹션

읽기 전용 상수나 포인터 테이블을 포함하는데 사용되는 섹션이다. 문자열 상수나 const로 지정된 값들, 그리고 IAT(Import Address Table), INT(Import Name Table) 값이 포함되있다. (IAT와 INT는 추가 포스팅 예정이다)

해당 rdata 섹션의 header의 Characteristics 값은 아래와 같은 값을 포함한다.

  • IMAGE_SCN_CNT_INITIALIZED_DATA : 0x00000040
  • IMAGE_SCN_MEM_READ : 0x40000000

d. .rsrc 섹션

아이콘이나, 대화상자, 메뉴, 버전 정보등 리소스를 포함하고 있으며, 다국어 문자열이나 UI 구성요소 역시 해당 섹션에 포함된다.

해당 rsrc 섹션의 header의 Characteristics 값은 아래와 같은 값을 포함한다.

  • IMAGE_SCN_CNT_INITIALIZED_DATA : 0x00000040
  • IMAGE_SCN_MEM_READ : 0x40000000

e. .reloc 섹션

실행시에 주소 재배치를 위한 정보이다. 이미지가 기본주소가 아닌곳에 로드될 경우를 위한 섹션이라고 할 수 있다.

해당 reloc 섹션의 header의 Characteristics 값은 아래와 같은 값을 포함한다.

  • IMAGE_SCN_CNT_INITIALIZED_DATA : 0x00000040
  • IMAGE_SCN_MEM_DISCARDABLE : 0x02000000
  • IMAGE_SCN_MEM_READ : 0x40000000

f. .pdata 섹션

x64에서 예외처리 테이블을 위한 섹션이다.

해당 pdata 섹션의 header의 Characteristics 값은 아래와 같은 값을 포함한다.

  • IMAGE_SCN_CNT_INITIALIZED_DATA : 0x00000040
  • IMAGE_SCN_MEM_READ : 0x40000000

3. ELF(Executable and Linkable Format, 유닉스, 리눅스등)

PE 파일 포맷이 그러했듯이 ELF 파일도 범주내에 라이브러리와 같은 파일들이 포함된다. 가령 컴파일 후 어셈블러로 번역된 오브젝트 파일이나 공유 라이브러리 같은 파일 뿐만 아니라 프로세스의 메모리 상태를 저장하는 파일인 코어 덤프 파일도 ELF 구조를 따른다.

이러한 ELF 구조를 그림으로 나타내면 아래와 같다.

img1.png

크게 볼때 ELF 구조는 ELF 헤더, 프로그램 헤더 테이블, 섹션, 섹션 헤더 테이블로 구성되어있다.
각 요소를 하나씩 알아보겠다.

1) ELF Header

ELF Header는 아래와 같이 정의되어있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define EI_NIDENT 16
typedef struct {
    unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
    ElfN_Half e_type;                 /* Object file type */
    ElfN_Half e_machine;              /* Architecture */
    ElfN_Word e_version;              /* Object file version */
    ElfN_Addr e_entry;                /* Entry point virtual address */
    ElfN_Off e_phoff;                 /* Program header table file offset */
    ElfN_Off e_shoff;                 /* Section header table file offset */
    ElfN_Word e_flags;                /* Processor-specific flags */
    ElfN_Half e_ehsize;               /* ELF header size in bytes */
    ElfN_Half e_phentsize;            /* Program header table entry size */
    ElfN_Half e_phnum;                /* Program header entry count */
    ElfN_Half e_shentsize;            /* Section header table entry size */
    ElfN_Half e_shnum;                /* Section header table entry count */
    ElfN_Half e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

a. e_ident

오프셋상수 이름의미주요 값(예) 및 설명
0x00EI_MAG0매직 넘버(식별) 바이트 00x7F
0x01EI_MAG1매직 넘버(식별) 바이트 1'E' (ASCII 0x45)
0x02EI_MAG2매직 넘버(식별) 바이트 2'L' (ASCII 0x4C)
0x03EI_MAG3매직 넘버(식별) 바이트 3'F' (ASCII 0x46)
0x04EI_CLASS파일 클래스0 = ELFCLASSNONE (없음)
1 = ELFCLASS32 (32비트)
2 = ELFCLASS64 (64비트)
0x05EI_DATA데이터 인코딩 방식0 = ELFDATANONE
1 = ELFDATA2LSB (리틀엔디안)
2 = ELFDATA2MSB (빅엔디안)
0x06EI_VERSIONELF 헤더 버전0 = EV_NONE (유효하지 않음)
1 = EV_CURRENT (현재 버전)
0x07EI_PAD[0]패딩의 시작 (0x07~0x0F까지 전부 0)향후 확장용으로 예약된 영역 — 반드시 0x00으로 채움

b. 그 외의 값

필드 이름오프셋크기설명
e_type0x102바이트파일 타입 (예: ET_EXEC, ET_DYN, ET_REL, ET_CORE)
e_machine0x122바이트대상 아키텍처 (예: EM_X86_64, EM_AARCH64 등)
e_version0x144바이트ELF 버전 (EV_CURRENT = 1)
e_entry0x188바이트프로그램 진입점 가상주소 (entry point)
e_phoff0x208바이트프로그램 헤더 테이블 시작 오프셋
e_shoff0x288바이트섹션 헤더 테이블 시작 오프셋
e_flags0x304바이트아키텍처별 플래그
e_ehsize0x342바이트ELF 헤더 전체 크기 (바이트)
e_phentsize0x362바이트프로그램 헤더 한 엔트리 크기
e_phnum0x382바이트프로그램 헤더 엔트리 개수
e_shentsize0x3A2바이트섹션 헤더 한 엔트리 크기
e_shnum0x3C2바이트섹션 헤더 엔트리 개수
e_shstrndx0x3E2바이트섹션 이름 문자열 테이블 인덱스 (섹션 헤더 테이블 내 위치)

2) Program Header Table

1
2
3
4
5
6
7
8
9
10
typedef struct {
    Elf64_Word   p_type;   
    Elf64_Word   p_flags;  
    Elf64_Off    p_offset; 
    Elf64_Addr   p_vaddr;  
    Elf64_Addr   p_paddr;  
    Elf64_Xword  p_filesz; 
    Elf64_Xword  p_memsz; 
    Elf64_Xword  p_align; 
} Elf64_Phdr;
필드타입크기설명
p_typeElf64_Word4바이트세그먼트 유형 (PT_LOAD, PT_DYNAMIC, PT_INTERP 등)
p_flagsElf64_Word4바이트읽기·쓰기·실행 권한 (PF_R/PF_W/PF_X)
p_offsetElf64_Off8바이트ELF 파일 내 이 세그먼트가 시작하는 오프셋
p_vaddrElf64_Addr8바이트이 세그먼트를 매핑할 가상 메모리 주소
p_paddrElf64_Addr8바이트물리 주소 (일반 유저 공간에서는 무시)
p_fileszElf64_Xword8바이트파일에 저장된 데이터 크기
p_memszElf64_Xword8바이트메모리에 로드될 때 확보할 전체 크기
p_alignElf64_Xword8바이트파일·메모리 상의 정렬 경계 (예: 페이지 크기)

3) Section Header Table

링커가 주로 읽는 테이블로, “섹션(section)” 단위로 코드·데이터를 분리 관리한다.

필드설명
sh_name섹션 이름(문자열 테이블 인덱스)
sh_type섹션 유형(PROGBITS, SYMTAB, STRTAB, RELA 등)
sh_flags속성(ALLOC, WRITE, EXECINSTR 등)
sh_addr메모리 내 가상 주소
sh_offset파일 내 오프셋
sh_size섹션 크기
sh_link연관된 섹션 인덱스
sh_info추가 정보(심볼 테이블일 때 심볼 개수 등)
sh_addralign정렬 단위
sh_entsize엔트리 크기(테이블 형 섹션일 때)
  • .text: 실행 코드

  • .data: 초기화된 전역/정적 변수

  • .bss: 초기화되지 않은 전역/정적 변수 (파일엔 없고, 메모리만 확보)

  • .rodata: 읽기 전용 상수

  • .symtab/.dynsym: 심볼 테이블 (정적/동적)

  • .strtab/.dynstr: 문자열 테이블 (심볼·섹션 이름)

  • .rel(a).text/.rel(a).data: 재배치(relocation) 정보

참고자료

This post is licensed under CC BY 4.0 by the author.