linux remoteproc驱动中elf解析函数实现分析
- 1 ELF文件组织结构
- 2 ELF_GEN_FIELD_GET_SET
- 3 elf 各种header解析接口以及其实现
- 3.1 elf header
- 3.1.1 elf header解析接口
- 3.1.2 elf header各个解析函数为:
- 3.1.2.1 ELF_GEN_FIELD_GET_SET(hdr, e_entry, u64)
- 3.1.2.2 ELF_GEN_FIELD_GET_SET(hdr, e_phnum, u16)
- 3.1.2.3 ELF_GEN_FIELD_GET_SET(hdr, e_shnum, u16)
- 3.1.2.4 ELF_GEN_FIELD_GET_SET(hdr, e_phoff, u64)
- 3.1.2.5 ELF_GEN_FIELD_GET_SET(hdr, e_shoff, u64)
- 3.1.2.6 ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
- 3.1.2.7 ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
- 3.1.2.8 ELF_GEN_FIELD_GET_SET(hdr, e_machine, u16)
- 3.1.2.9 ELF_GEN_FIELD_GET_SET(hdr, e_type, u16)
- 3.1.2.10 ELF_GEN_FIELD_GET_SET(hdr, e_version, u32)
- 3.1.2.11 ELF_GEN_FIELD_GET_SET(hdr, e_ehsize, u32)
- 3.1.2.12 ELF_GEN_FIELD_GET_SET(hdr, e_phentsize, u16)
- 3.1.2.13 ELF_GEN_FIELD_GET_SET(hdr, e_shentsize, u16)
- 3.2 elf program header
- 3.2.1 elf program header解析接口
- 3.2.2 elf program header各个解析函数为
- 3.2.2.1 ELF_GEN_FIELD_GET_SET(phdr, p_paddr, u64)
- 3.2.2.2 ELF_GEN_FIELD_GET_SET(phdr, p_vaddr, u64)
- 3.2.2.3 ELF_GEN_FIELD_GET_SET(phdr, p_filesz, u64)
- 3.2.2.4 ELF_GEN_FIELD_GET_SET(phdr, p_memsz, u64)
- 3.2.2.5 ELF_GEN_FIELD_GET_SET(phdr, p_type, u32)
- 3.2.2.6 ELF_GEN_FIELD_GET_SET(phdr, p_offset, u64)
- 3.2.2.7 ELF_GEN_FIELD_GET_SET(phdr, p_flags, u32)
- 3.2.2.8 ELF_GEN_FIELD_GET_SET(phdr, p_align, u64)
- 3.3 elf section header
- 3.3.1 elf section header解析接口
- 3.3.2 elf section header各个解析函数为:
- 3.3.2.1 ELF_GEN_FIELD_GET_SET(shdr, sh_type, u32)
- 3.3.2.2 ELF_GEN_FIELD_GET_SET(shdr, sh_flags, u32)
- 3.3.2.3 ELF_GEN_FIELD_GET_SET(shdr, sh_entsize, u16)
- 3.3.2.4 ELF_GEN_FIELD_GET_SET(shdr, sh_size, u64)
- 3.3.2.5 ELF_GEN_FIELD_GET_SET(shdr, sh_offset, u64)
- 3.3.2.6 ELF_GEN_FIELD_GET_SET(shdr, sh_name, u32)
- 3.3.2.7 ELF_GEN_FIELD_GET_SET(shdr, sh_addr, u64)
在linux中存在的remoteproc的驱动中用到了很多elf解析的函数,比如
elf_size_of_phdr
,
elf_phdr_get_p_paddr
以及
elf_hdr_get_e_phnum
等等接口。当我们直接搜对应的函数时会发现无法找到其定义,其实这些函数的实现被定义在
drivers/remoteproc/remoteproc_elf_helpers.h
头文件中。
1 ELF文件组织结构
下面以ELF64为例
- Start of program headers: 64 (bytes into file)
- Start of section headers: 220982296 (bytes into file)
- Size of this header: 64 (bytes)
- Size of program headers: 56 (bytes)
- Size of section headers: 64 (bytes)
$ readelf -hW vmlinux
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: AArch64
Version: 0x1
Entry point address: 0xffff800008000000
Start of program headers: 64 (bytes into file)
Start of section headers: 220982296 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 5
Size of section headers: 64 (bytes)
Number of section headers: 40
Section header string table index: 39
$
2 ELF_GEN_FIELD_GET_SET
ELF_GEN_FIELD_GET_SET是对应组织hdr,phdr,shdr各个头解析函数的最根本的函数。
其实现为如下所示:
ELF_GEN_FIELD_GET_SET
最终会生成两个inline函数,一个为elf_##__s##_get_##__field
一个为elf_##__s##_set_##__field
,具体函数名字会依据ELF_GEN_FIELD_GET_SET
参数的不同而不同。- ##表示的是字符串链接符,比如
ELF_GEN_FIELD_GET_SET(hdr, e_entry, u64)
,最终会被解析为elf_hdr_get_e_entry
和elf_hdr_set_e_entry
两个函数,两个函数的返回类型为u64。
/* Generate getter and setter for a specific elf struct/field */
#define ELF_GEN_FIELD_GET_SET(__s, __field, __type) \
static inline __type elf_##__s##_get_##__field(u8 class, const void *arg) \
{ \
if (class == ELFCLASS32) \
return (__type) ((const struct elf32_##__s *) arg)->__field; \
else \
return (__type) ((const struct elf64_##__s *) arg)->__field; \
} \
static inline void elf_##__s##_set_##__field(u8 class, void *arg, \
__type value) \
{ \
if (class == ELFCLASS32) \
((struct elf32_##__s *) arg)->__field = (__type) value; \
else \
((struct elf64_##__s *) arg)->__field = (__type) value; \
}
3 elf 各种header解析接口以及其实现
3.1 elf header
elf32和elf64 header数据结构如下所示,其分别对应于下面的elf header解析函数。
#define EI_NIDENT 16
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; /* Entry point */
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct elf64_hdr {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
3.1.1 elf header解析接口
ELF_GEN_FIELD_GET_SET(hdr, e_entry, u64)
ELF_GEN_FIELD_GET_SET(hdr, e_phnum, u16)
ELF_GEN_FIELD_GET_SET(hdr, e_shnum, u16)
ELF_GEN_FIELD_GET_SET(hdr, e_phoff, u64)
ELF_GEN_FIELD_GET_SET(hdr, e_shoff, u64)
ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
ELF_GEN_FIELD_GET_SET(hdr, e_machine, u16)
ELF_GEN_FIELD_GET_SET(hdr, e_type, u16)
ELF_GEN_FIELD_GET_SET(hdr, e_version, u32)
ELF_GEN_FIELD_GET_SET(hdr, e_ehsize, u32)
ELF_GEN_FIELD_GET_SET(hdr, e_phentsize, u16)
ELF_GEN_FIELD_GET_SET(hdr, e_shentsize, u16)
3.1.2 elf header各个解析函数为:
3.1.2.1 ELF_GEN_FIELD_GET_SET(hdr, e_entry, u64)
static inline u64 elf_hdr_get_e_entry(u8 class, const void *arg)
static inline u64 elf_hdr_set_e_entry(u8 class, void *arg, u64 value))
3.1.2.2 ELF_GEN_FIELD_GET_SET(hdr, e_phnum, u16)
static inline u16 elf_hdr_get_e_phnum(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_phnum(u8 class, void *arg, u16 value))
3.1.2.3 ELF_GEN_FIELD_GET_SET(hdr, e_shnum, u16)
static inline u16 elf_hdr_get_e_shnum(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_shnum(u8 class, void *arg, u16 value))
3.1.2.4 ELF_GEN_FIELD_GET_SET(hdr, e_phoff, u64)
static inline u64 elf_hdr_get_e_phoff(u8 class, const void *arg)
static inline u64 elf_hdr_set_e_phoff(u8 class, void *arg, u64 value))
3.1.2.5 ELF_GEN_FIELD_GET_SET(hdr, e_shoff, u64)
static inline u64 elf_hdr_get_e_shoff(u8 class, const void *arg)
static inline u64 elf_hdr_set_e_shoff(u8 class, void *arg, u64 value))
3.1.2.6 ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
static inline u16 elf_hdr_get_e_shstrndx(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_shstrndx(u8 class, void *arg, u16 value))
3.1.2.7 ELF_GEN_FIELD_GET_SET(hdr, e_shstrndx, u16)
static inline u16 elf_hdr_get_e_shstrndx(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_shstrndx(u8 class, void *arg, u16 value))
3.1.2.8 ELF_GEN_FIELD_GET_SET(hdr, e_machine, u16)
static inline u16 elf_hdr_get_e_machine(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_machine(u8 class, void *arg, u16 value))
3.1.2.9 ELF_GEN_FIELD_GET_SET(hdr, e_type, u16)
static inline u16 elf_hdr_get_e_type(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_type(u8 class, void *arg, u16 value))
3.1.2.10 ELF_GEN_FIELD_GET_SET(hdr, e_version, u32)
static inline u32 elf_hdr_get_e_version(u8 class, const void *arg)
static inline u32 elf_hdr_set_e_version(u8 class, void *arg, u32 value))
3.1.2.11 ELF_GEN_FIELD_GET_SET(hdr, e_ehsize, u32)
static inline u32 elf_hdr_get_e_ehsize(u8 class, const void *arg)
static inline u32 elf_hdr_set_e_ehsize(u8 class, void *arg, u32 value))
3.1.2.12 ELF_GEN_FIELD_GET_SET(hdr, e_phentsize, u16)
static inline u16 elf_hdr_get_e_phentsize(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_phentsize(u8 class, void *arg, u16 value))
3.1.2.13 ELF_GEN_FIELD_GET_SET(hdr, e_shentsize, u16)
static inline u16 elf_hdr_get_e_shentsize(u8 class, const void *arg)
static inline u16 elf_hdr_set_e_shentsize(u8 class, void *arg, u16 value))
3.2 elf program header
elf32和elf64 program header数据结构如下所示,其分别对应于下面的elf program header解析函数。
/* These constants define the permissions on sections in the program
header, p_flags. */
#define PF_R 0x4
#define PF_W 0x2
#define PF_X 0x1
typedef struct elf32_phdr{
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct elf64_phdr {
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset; /* Segment file offset */
Elf64_Addr p_vaddr; /* Segment virtual address */
Elf64_Addr p_paddr; /* Segment physical address */
Elf64_Xword p_filesz; /* Segment size in file */
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment, file & memory */
} Elf64_Phdr;
3.2.1 elf program header解析接口
ELF_GEN_FIELD_GET_SET(phdr, p_paddr, u64)
ELF_GEN_FIELD_GET_SET(phdr, p_vaddr, u64)
ELF_GEN_FIELD_GET_SET(phdr, p_filesz, u64)
ELF_GEN_FIELD_GET_SET(phdr, p_memsz, u64)
ELF_GEN_FIELD_GET_SET(phdr, p_type, u32)
ELF_GEN_FIELD_GET_SET(phdr, p_offset, u64)
ELF_GEN_FIELD_GET_SET(phdr, p_flags, u32)
ELF_GEN_FIELD_GET_SET(phdr, p_align, u64)
3.2.2 elf program header各个解析函数为
3.2.2.1 ELF_GEN_FIELD_GET_SET(phdr, p_paddr, u64)
static inline u64 elf_phdr_get_p_paddr(u8 class, const void *arg)
static inline u64 elf_phdr_set_p_paddr(u8 class, void *arg, u64 value))
3.2.2.2 ELF_GEN_FIELD_GET_SET(phdr, p_vaddr, u64)
static inline u64 elf_phdr_get_p_vaddr(u8 class, const void *arg)
static inline u64 elf_phdr_set_p_vaddr(u8 class, void *arg, u64 value))
3.2.2.3 ELF_GEN_FIELD_GET_SET(phdr, p_filesz, u64)
static inline u64 elf_phdr_get_p_filesz(u8 class, const void *arg)
static inline u64 elf_phdr_set_p_filesz(u8 class, void *arg, u64 value))
3.2.2.4 ELF_GEN_FIELD_GET_SET(phdr, p_memsz, u64)
static inline u64 elf_phdr_get_p_memsz(u8 class, const void *arg)
static inline u64 elf_phdr_set_p_memsz(u8 class, void *arg, u64 value))
3.2.2.5 ELF_GEN_FIELD_GET_SET(phdr, p_type, u32)
static inline u32 elf_phdr_get_p_type(u8 class, const void *arg)
static inline u32 elf_phdr_set_p_type(u8 class, void *arg, u32 value))
3.2.2.6 ELF_GEN_FIELD_GET_SET(phdr, p_offset, u64)
static inline u64 elf_phdr_get_p_offset(u8 class, const void *arg)
static inline u64 elf_phdr_set_p_offset(u8 class, void *arg, u64 value))
3.2.2.7 ELF_GEN_FIELD_GET_SET(phdr, p_flags, u32)
static inline u32 elf_phdr_get_p_flags(u8 class, const void *arg)
static inline u32 elf_phdr_set_p_flags(u8 class, void *arg, u32 value))
3.2.2.8 ELF_GEN_FIELD_GET_SET(phdr, p_align, u64)
static inline u64 elf_phdr_get_p_align(u8 class, const void *arg)
static inline u64 elf_phdr_set_p_align(u8 class, void *arg, u64 value))
3.3 elf section header
elf32和elf64 section header数据结构如下所示,其分别对应于下面的elf section header解析函数。
typedef struct elf32_shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct elf64_shdr {
Elf64_Word sh_name; /* Section name, index in string tbl */
Elf64_Word sh_type; /* Type of section */
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Size of section in bytes */
Elf64_Word sh_link; /* Index of another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
3.3.1 elf section header解析接口
ELF_GEN_FIELD_GET_SET(shdr, sh_type, u32)
ELF_GEN_FIELD_GET_SET(shdr, sh_flags, u32)
ELF_GEN_FIELD_GET_SET(shdr, sh_entsize, u16)
ELF_GEN_FIELD_GET_SET(shdr, sh_size, u64)
ELF_GEN_FIELD_GET_SET(shdr, sh_offset, u64)
ELF_GEN_FIELD_GET_SET(shdr, sh_name, u32)
ELF_GEN_FIELD_GET_SET(shdr, sh_addr, u64)
3.3.2 elf section header各个解析函数为:
3.3.2.1 ELF_GEN_FIELD_GET_SET(shdr, sh_type, u32)
static inline u32 elf_shdr_get_sh_type(u8 class, const void *arg)
static inline u32 elf_shdr_set_sh_type(u8 class, void *arg, u32 value))
3.3.2.2 ELF_GEN_FIELD_GET_SET(shdr, sh_flags, u32)
static inline u32 elf_shdr_get_sh_flags(u8 class, const void *arg)
static inline u32 elf_shdr_set_sh_flags(u8 class, void *arg, u32 value))
3.3.2.3 ELF_GEN_FIELD_GET_SET(shdr, sh_entsize, u16)
static inline u16 elf_shdr_get_sh_entsize(u8 class, const void *arg)
static inline u16 elf_shdr_set_sh_entsize(u8 class, void *arg, u16 value))
3.3.2.4 ELF_GEN_FIELD_GET_SET(shdr, sh_size, u64)
static inline u64 elf_shdr_get_sh_size(u8 class, const void *arg)
static inline u64 elf_shdr_set_sh_size(u8 class, void *arg, u64 value))
3.3.2.5 ELF_GEN_FIELD_GET_SET(shdr, sh_offset, u64)
static inline u64 elf_shdr_get_sh_offset(u8 class, const void *arg)
static inline u64 elf_shdr_set_sh_offset(u8 class, void *arg, u64 value))
3.3.2.6 ELF_GEN_FIELD_GET_SET(shdr, sh_name, u32)
static inline u32 elf_shdr_get_sh_name(u8 class, const void *arg)
static inline u32 elf_shdr_set_sh_name(u8 class, void *arg, u32 value))
3.3.2.7 ELF_GEN_FIELD_GET_SET(shdr, sh_addr, u64)
static inline u64 elf_shdr_get_sh_addr(u8 class, const void *arg)
static inline u64 elf_shdr_set_sh_addr(u8 class, void *arg, u64 value))