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

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_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 vmlinux
ELF Header:Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class:                             ELF64Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              DYN (Shared object file)Machine:                           AArch64Version:                           0x1Entry point address:               0xffff800008000000Start of program headers:          64 (bytes into file)Start of section headers:          220982296 (bytes into file)Flags:                             0x0Size of this header:               64 (bytes)Size of program headers:           56 (bytes)Number of program headers:         5Size of section headers:           64 (bytes)Number of section headers:         40Section 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 programheader, 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))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61159.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LVS集群

目录 1、lvs简介: 2、lvs架构图: 3、 lvs的工作模式: 1) VS/NAT: 即(Virtual Server via Network Address Translation) 2)VS/TUN :即(Virtual Server v…

LeetCode 热题 100 JavaScript--141. 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(…

openGauss学习笔记-36 openGauss 高级数据管理-TRUNCATE TABLE语句

文章目录 openGauss学习笔记-36 openGauss 高级数据管理-TRUNCATE TABLE语句36.1 语法格式36.2 参数说明36.3 示例 openGauss学习笔记-36 openGauss 高级数据管理-TRUNCATE TABLE语句 清理表数据,TRUNCATE TABLE用于删除表的数据,但不删除表结构。也可以…

wonderful-sql 作业

Sql 作业 作业1: 答: create table Employee (Id integer not null, Name varchar(32) , Salary integer, departmentId integer, primary key (Id) );create table Department( Id integer primary key, Name varchar(30) not null );insert into emp…

STM32基于CubeIDE和HAL库 基础入门学习笔记:物联网项目开发流程和思路

文章目录: 第一部分:项目开始前的计划与准备 1.项目策划和开发规范 1.1 项目要求文档 1.2 技术实现文档 1.3 开发规范 2.创建项目工程与日志 第二部分:调通硬件电路与驱动程序 第三部分:编写最基础的应用程序 第四部分&…

Docker desktop使用配置

1. 下载安装 https://www.docker.com/ 官网下载并安装doker desktop 2. 配置镜像 (1)首先去阿里云网站上进行注册:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors (2)注册完成后搜索:容…

java泛型和通配符的使用

泛型机制 本质是参数化类型(与方法的形式参数比较,方法是参数化对象)。 优势:将类型检查由运行期提前到编译期。减少了很多错误。 泛型是jdk5.0的新特性。 集合中使用泛型 总结: ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构② 在实例化集合类时…

MySQL8的特性-MySQL8知识详解

MySQL是一个多用户、多线程的SQL数据库服务器。SQL(结构化查询语言)是世界上最流行和标准化的数据库语言。下面是MySQL的特性。 1、开源性:MySQL是一个开源的关系型数据库管理系统,可以免费使用和修改。 2、可靠性:M…

MySQL—日志

这里写目录标题 undo logundo log的作用undo log页记录的是什么 Buffer Pool为什么需要Buffer PoolBuffer Pool缓存什么 redo log什么是redo logredo log的作用redo log什么时候刷盘undo和redo的区别 binlogbinlog 作用redo log和binlog区别如果数据数据被删了,能用…

宿舍管理系统--前后端分离式项目架构流程复盘

文章目录 🐒个人主页🏅JavaEE系列专栏📖前言:【🎇前端】先创建Vue-cli项目(版本2.6.10,仅包含babel),请选择此项目并创建 【整理简化项目模板】【🎀创建路由】…

Gradio入门,并搭个鸡兔同笼问题小应用,附源码(MindOpt)

应用链接: https://979427749bc9ceec34.gradio.live 是公开访问链接,3天有效。在modelscope中的创空间怎么长期发布我还在研究。后面补上。 应用图如下,源代码见正文。 知道Gradio AI大模型快速生成应用的工具, 在Huggingface …

week3

题解: 前序遍历性质: 节点按照 [ 根节点 | 左子树 | 右子树 ] 排序。 中序遍历性质: 节点按照 [ 左子树 | 根节点 | 右子树 ] 排序。 通过以上三步,可确定 三个节点 :1.树的根节点、2.左子树根节点、3.右子树根节点。 之后进行…