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

这篇具有很好参考价值的文章主要介绍了linux remoteproc驱动中elf解析函数实现分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


在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:                             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
$

linux remoteproc驱动中elf解析函数实现分析,linux嵌入式开发,linux,remoteproc驱动,elf解析函数实现分析

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       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解析函数。文章来源地址https://www.toymoban.com/news/detail-640083.html

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))

到了这里,关于linux remoteproc驱动中elf解析函数实现分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式音频开发:ES8311驱动开发及源代码解析

    嵌入式音频开发:ES8311驱动开发及源代码解析 嵌入式系统在现代科技应用中起着重要的作用,而其中音频开发更是一个关键领域。本文将重点讨论如何开发 ES8311 驱动程序,并提供相应的源代码。 一、ES8311芯片概述 ES8311 是一款集成了低功耗立体声CODEC功能的音频编解码芯片

    2024年01月18日
    浏览(139)
  • 正点原子嵌入式linux驱动开发——Linux WIFI驱动

    WIFI的使用已经很常见了,手机、平板、汽车等等,虽然可以使用有线网络,但是有时候很多设备存在布线困难的情况,此时WIFI就是一个不错的选择。 正点原子STM32MP1开发板支持USB和SDIO这两种接口的WIFI ,本章就来学习一下如何在STM32MP1开发板上使用USB和SDIO这两种WIFI。 正点原

    2024年02月05日
    浏览(68)
  • 正点原子嵌入式linux驱动开发——Linux CAN驱动

    CAN是目前应用非常广泛的现场总线之一,主要应用于汽车电子和工业领域 ,尤其是汽车领域,汽车上大量的传感器与模块都是通过CAN总线连接起来的。CAN总线目前是自动化领域发展的热点技术之一,由于其高可靠性,CAN总线目前广泛的应用于工业自动化、船舶、汽车、医疗和

    2024年02月06日
    浏览(75)
  • 【ARM 嵌入式 编译系列 10 -- GCC 编译缩减可执行文件 elf 文件大小】

    请阅读 【ARM GCC 编译专栏导读】 上篇文章:ARM 嵌入式 编译系列 9-- GCC 编译符号表(Symbol Table)的详细介绍 下篇文章:ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小 在开发过程总,总是希望编译出来的可执行文件尽量小,因为这样可以节省更多的磁盘空间

    2024年02月09日
    浏览(52)
  • 正点原子嵌入式linux驱动开发——Linux 网络设备驱动

    网络驱动是linux里面驱动三巨头之一 ,linux下的网络功能非常强大,嵌入式linux中也常常用到网络功能。前面已经讲过了字符设备驱动和块设备驱动,本章就来学习一下linux里面的 网络设备驱动 。 本次笔记中讨论的都是有线网络! 提起网络,一般想到的硬件就是“网卡”。在

    2024年01月17日
    浏览(68)
  • 【嵌入式Linux驱动】驱动开发调试相关的关系记录

    https://www.processon.com/mindmap/64537772b546c76a2f37bd2f

    2024年02月02日
    浏览(51)
  • 嵌入式Linux驱动开发 04:基于设备树的驱动开发

    前面文章 《嵌入式Linux驱动开发 03:平台(platform)总线驱动模型》 引入了资源和驱动分离的概念,这篇文章将在前面基础上更进一步,引入设备树的概念。 在平台总线驱动模型中资源和驱动已经从逻辑上和代码组织上进行了分离,但每次调整资源还是会涉及到内核,所以现

    2024年02月16日
    浏览(66)
  • 嵌入式Linux驱动开发 02:将驱动程序添加到内核中

    在上一篇文章 《嵌入式Linux驱动开发 01:基础开发与使用》 中我们已经实现了最基础的驱动功能。在那篇文章中我们的驱动代码是独立于内核代码存放的,并且我们的驱动编译后也是一个独立的模块。在实际使用中将驱动代码放在内核代码中,并将驱动编译到内核中也是比较

    2023年04月09日
    浏览(70)
  • 嵌入式Linux开发-USB驱动

    哥们马上就要被裁了,总得整理一下技术方面的积累,准备开始下一轮的面试和找工作之旅了。。。。 通用串行总线(USB)是主机和外围设备之间的一种连接。 从拓扑上来看,是一颗由几个点对点的连接构建而成的树。这些连接是连接设备和集线器(hub)的四线电缆(底线、电源线

    2024年02月20日
    浏览(70)
  • 嵌入式Linux驱动开发之点灯

      使用驱动开发的方式点亮一个LED灯。看看两者有啥区别不? 首先查看原理图,看看我们的板子上的LED等接在哪一个IO口上面。 好了,看原理图我们知道LED灯接在芯片的GPIO1的第三个引脚上面,也就是GPIO1_IO03。 先掌握三个名词 CCM: Clock Controller Module (时钟控制模块) IOMUXC : I

    2024年02月01日
    浏览(97)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包