본문 바로가기
임베디드 개발/펌웨어

readelf 명령어와 elf 파일 구조

by eteo 2023. 6. 25.

 

ELF 파일

 

Executable and Linkable Format

 

 

소스코드를 컴파일하면 목적코드로 변환되고, 목적코드와 필요한 라이브러리들을 링커커맨드파일 정보를 통해 링킹하는 과정이 끝나면 실행가능한 이진형식 파일인 Executable and Linkable Format 파일이 생성된다. 

 

 

 

 

 

 

ELF 파일의 구성

 

ELF 파일 기본 정보를 포함한 ELF Header

세그먼트의 정보를 포함한 Program Header Table

섹션에 대한 정보를 포함하는 Section Header Table

Program Header Table 또는 Section Header Table의 엔트리들에 의해 참조되는 데이터

 

이 중섹션들이 링킹과 재배치에 필요한 중요한 정보를 포함하는 반면, 세그먼트들은 파일의 런타임 실행에 필요한 정보를 포함한다. 

 

 

 

 

 

readelf

 

ELF파일의 내부 구조와 내용을 읽고 표시해주는 리눅스 명령어

 

 

readelf 명령어 옵션

 

 

 

 

 

 

 

 

 

ELF header

 

ELF 헤더는 ELF 파일의 시작 부분에 위치하여 ELF 파일의 형식, 아키텍처, 섹션 및 프로그램 헤더의 위치 및 크기 등을 정의한다.

 

 

 

 

구조체 정의

32비트 아키텍처 실행파일이냐, 64비트 실행파일이냐에 따라 ElfN_Ehdr, ElfN_Addr, ElfN_Off의 N부분이 달라진다.

 

#define EI_NIDENT 16

typedef struct {
   unsigned char e_ident[EI_NIDENT];
   uint16_t      e_type;
   uint16_t      e_machine;
   uint32_t      e_version;
   ElfN_Addr     e_entry;
   ElfN_Off      e_phoff;
   ElfN_Off      e_shoff;
   uint32_t      e_flags;
   uint16_t      e_ehsize;
   uint16_t      e_phentsize;
   uint16_t      e_phnum;
   uint16_t      e_shentsize;
   uint16_t      e_shnum;
   uint16_t      e_shstrndx;
} ElfN_Ehdr;

 

 

 

https://ko.wikipedia.org/wiki/ELF_%ED%8C%8C%EC%9D%BC_%ED%98%95%EC%8B%9D

 

 

 

 

 

 

 

 

 

 

Program header (Phdr)

 

프로그램 헤더 테이블은 프로세스가 실행될 때 메모리에 로드되는 세그먼트의 속성과 위치를 지정하는 세그먼트 헤더 엔트리들로 구성되어 있다.

 

따라서 실행 파일을 실행할 때 운영체제가 이 정보를 사용하여 프로그램을 적절한 메모리 위치에 로드하게 된다.

 

 

 

typedef struct {
   uint32_t   p_type;
   Elf32_Off  p_offset;
   Elf32_Addr p_vaddr;
   Elf32_Addr p_paddr;
   uint32_t   p_filesz;
   uint32_t   p_memsz;
   uint32_t   p_flags;
   uint32_t   p_align;
} Elf32_Phdr;

typedef struct {
   uint32_t   p_type;
   uint32_t   p_flags;
   Elf64_Off  p_offset;
   Elf64_Addr p_vaddr;
   Elf64_Addr p_paddr;
   uint64_t   p_filesz;
   uint64_t   p_memsz;
   uint64_t   p_align;
} Elf64_Phdr;

 

 

 

 

 

 

 

 

 

 

Section header (Shdr)

섹션 헤더 테이블은 섹션 헤더들의 배열로 구성되어 있으며, 각 섹션 헤더는 섹션의 속성과 위치 등을 정의한다. 섹션은 프로그램의 코드, 데이터, 심볼 테이블, 디버깅 정보 등이 포함된다.

 

.symtab은 36번, .strtab은 38번에 보인다.

 

 

typedef struct {
   uint32_t   sh_name;
   uint32_t   sh_type;
   uint32_t   sh_flags;
   Elf32_Addr sh_addr;
   Elf32_Off  sh_offset;
   uint32_t   sh_size;
   uint32_t   sh_link;
   uint32_t   sh_info;
   uint32_t   sh_addralign;
   uint32_t   sh_entsize;
} Elf32_Shdr;

typedef struct {
   uint32_t   sh_name;
   uint32_t   sh_type;
   uint64_t   sh_flags;
   Elf64_Addr sh_addr;
   Elf64_Off  sh_offset;
   uint64_t   sh_size;
   uint32_t   sh_link;
   uint32_t   sh_info;
   uint64_t   sh_addralign;
   uint64_t   sh_entsize;
} Elf64_Shdr;

 

 

 

 

 

 

String Table

 

스트링 테이블은 섹션 중 하나로, 다른 섹션 및 테이블에서 사용되는 문자열 데이터를 null-terminated 문자열로 저장한다.

심볼 테이블에서 st_name(문자열 테이블에서 심볼 이름의 오프셋)으로 각 심볼의 이름을 참조할 때 사용되며, 디버깅 정보나 다른 섹션에서 사용되는 문자열 데이터에 대한 인덱스를 제공한다.

 

 

 

 

 

Symbol tables

 

심볼 테이블은 섹션 중 하나로, 프로그램의 변수, 함수, 외부 참조 등에 대한 정보를 담고 있다. 심볼 테이블은 디버깅이나 동적 링킹 등에서 사용된다.

 

 

typedef struct {
   uint32_t      st_name;
   Elf32_Addr    st_value;
   uint32_t      st_size;
   unsigned char st_info;
   unsigned char st_other;
   uint16_t      st_shndx;
} Elf32_Sym;

typedef struct {
   uint32_t      st_name;
   unsigned char st_info;
   unsigned char st_other;
   uint16_t      st_shndx;
   Elf64_Addr    st_value;
   uint64_t      st_size;
} Elf64_Sym;

 

 

 

 

 

 

 

Reference : https://man7.org/linux/man-pages/man5/elf.5.html

'임베디드 개발 > 펌웨어' 카테고리의 다른 글

MIL, SIL, PIL and HIL  (0) 2023.07.11
CAN FD Bus Load Calculator  (0) 2023.06.25
JTAG, SWD  (0) 2023.06.25
PXI  (0) 2023.06.25
UDS (차량용 진단 통신)  (0) 2023.06.09