您现在的位置是:首页 > 短信大全

linux remoteproc驱动中elf解析函数实现分析

作者:付梓时间:2024-05-13 12:10:51分类:短信大全

简介  文章浏览阅读1.7k次,点赞40次,收藏39次。在linux中存在的remoteproc的驱动中用到了很多elf解析的函数,比如以及等等接口。当我们直接搜对应的函数时会发现无法找到其定义,其实这些函数的实现被定义在头文件中。_linux remoteproc

点击全文阅读

linux remoteproc驱动中elf解析函数实现分析

1 ELF文件组织结构2 ELF_GEN_FIELD_GET_SET3 elf 各种header解析接口以及其实现3.1 elf header3.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 header3.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 header3.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_phdrelf_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 vmlinuxELF 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_entryelf_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       16typedef 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            0x1typedef 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))

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

我来说两句