ELF文件格式解析

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

   ELF(Executable and Linkable Format) 即可执行可链接文件格式,是目前操作系统上最常见的可执行文件格式。不同系统的目标文件不一样,Windows是PE(Portable Executable),linux是ELF(Executable Linkable Format),它们都是COFF(Common file format)格式的变种。

1、基本格式

      ELF格式的目标文件和可执行文件在结构上没有本质差异,ELF不仅仅描述目标文件,也用于描述可执行文件,Windows下的dll和.lib, Linux下的.so和.a文件都是按照类ELF格式存储,下图描述了ELF链接视图(.o文件、.so文件)和执行视图,链接视图描述了各个段(section)的组成,如.text、.data、bss段。执行视图由segment组成,segment用于表示一个一定长度的区域,按照只读/可读写划分,不区分数据的属性,如代码段、数据段。

ELF文件格式解析

      目标文件是未经过链接的,里面的符号和地址没有调整导致无法运行。例如直接运行目标文件,系统提示无法执行该二进制文件。

$ . hello.o
bash: .: hello.o: cannot execute binary file
$ file hello.o
hello.o: Intel amd64 COFF object file, no line number info, not stripped, 7 sections, symbol offset=0x2a0, 22 symbols, 1st section name ".text"

     ELF文件格式在字节对齐和元素解析时,与系统架构、字长有密切关系,ELF 文件由ELF header和各种段组成,其结构图如下所示。详细文档可以查阅https://elinux.org/Executable_and_Linkable_Format_(ELF)

ELF文件格式解析

 

2、ELF文件头

     ELF 文件的最前面是文件头,描述了ELF文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址。

     详细的描述可以参考:https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html

#define EI_NIDENT 16

typedef struct {
        unsigned char   e_ident[EI_NIDENT];
        Elf32_Half      e_type;
        Elf32_Half      e_machine;
        Elf32_Word      e_version;
        Elf32_Addr      e_entry;
        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;


$ readelf -h /bin/ls 
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 (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x6180
  Start of program headers:          64 (bytes into file)
  Start of section headers:          145256 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

上面结构体里成员类型长度的定义为:

名称

大小

说明

Elf32_Addr

4

无符号程序地址

Elf32_Half

2

无符号中等整数

Elf32_Off

4

无符号文件偏移

Elf32_SWord

4

有符号大整数

Elf32_Word

4

无符号大整数

unsigned char

1

无符号字符型整数

Elf32_Ehdr 各个成员简介:

  • e_ident magic bytes (0x7fELF), class, ABI version....是一组包含多个标志的数组。
  • e_typeobject file type—ET{REL,DYN,EXEC,CORE} 00-未知, 01--RT_REL,02--ET_EXEC, 03---ET_DY
  • e_machine required architecture—EM X86 64, ... 其中3h=386, 28h=ARM
  • e_version EV CURRENT, always ”1”
  • e_entry virt. addr. of entry point, dl start, jmp *%r12
  • e_phoff program header offset
  • e_shoff section header offset
  • e_flags CPU-specific flags
  • e_ehsize ELF header size
  • e_phentsize size of program header entry, consistency check
  • e_phnum number of program header entries
  • e_shentsize size of section header entry
  • e_shnum number of section header entries
  • e_shstrndx section header string table index

     其中e_ident 对应了对各字段,有MAGIC、Class、Data、Version、 ABI这几个参数。

Name

Value

Purpose

EI_MAG0

0

File identification

EI_MAG1

1

File identification

EI_MAG2

2

File identification

EI_MAG3

3

File identification

EI_CLASS

4

File class

EI_DATA

5

Data encoding

EI_VERSION

6

File version

EI_OSABI

7

Operating system/ABI identification

EI_ABIVERSION

8

ABI version

EI_PAD

9

Start of padding bytes

EI_NIDENT

16

Size of e_ident[]

1)MAGIC是ELF标志码:魔数,占4字节,byte0固定为0x7F,byte1--byte3是'E', 'L', 'F' 的ASCII码。

2)EI_CLASS 是CPU字长类型。

Name

Value

Meaning

ELFCLASSNONE

0

Invalid class

ELFCLASS32

1

32-bit objects

ELFCLASS64

2

64-bit objects

3)EI_DATA

0:非法格式

1:小端字节序LSB

2:大端字节序MSB

4)EI_VERSION: ELF版本号,为1

5)EI_OSABI

Name

Value

Meaning

ELFOSABI_NONE

0

No extensions or unspecified

ELFOSABI_HPUX

1

Hewlett-Packard HP-UX

ELFOSABI_NETBSD

2

NetBSD

ELFOSABI_LINUX

3

Linux

ELFOSABI_SOLARIS

6

Sun Solaris

ELFOSABI_AIX

7

AIX

ELFOSABI_IRIX

8

IRIX

ELFOSABI_FREEBSD

9

FreeBSD

ELFOSABI_TRU64

10

Compaq TRU64 UNIX

ELFOSABI_MODESTO

11

Novell Modesto

ELFOSABI_OPENBSD

12

Open BSD

ELFOSABI_OPENVMS

13

Open VMS

ELFOSABI_NSK

14

Hewlett-Packard Non-Stop Kernel

 

64-255

Architecture-specific value range

3、段表--Section

1)段表的结构

    ELF 文件中有很多段,段表(Section Header Table)就是保存这些段的基本属性的结构。段表描述了ELF各个段的信息,如段名、段的长度、在文件中的偏移、读写权限等。段表在ELF文件中 的偏移是由文件头的e_shoff成员决定的。

typedef struct{
    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

Elf32_Shdr成员含义:

  • sh_name 段名,但此次只是记录了段名字符串在 .shstrtab 中的偏移
  • sh_type 段的类型
  • sh_flags 段的标志位
  • sh_addr 段的虚拟地址,如果此段可以被加载则表示在进程中的虚拟地址,否则为0
  • sh_offset 如果此段位于文件中则表示此段在文件中的偏移
  • sh_size 段的长度
  • sh_link This member holds a section header table index link, whose interpretation depends on the section type.
  • sh_info This member holds extra information, whose interpretation depends on the section type.
  • sh_addralign 段对齐,以2的n次方表示,如果为0或1,表示没有对齐要求。
  • sh_entsize Section Entry Size段的长度

 sh_type :段的类型。

Name

Value

SHT_NULL

0

SHT_PROGBITS

1

SHT_SYMTAB

2

SHT_STRTAB

3

SHT_RELA

4

SHT_HASH

5

SHT_DYNAMIC

6

SHT_NOTE

7

SHT_NOBITS

8

SHT_REL

9

SHT_SHLIB

10

SHT_DYNSYM

11

SHT_LOPROC

0x70000000

SHT_HIPROC

0x7fffffff

SHT_LOUSER

0x80000000

SHT_HIUSER

0xffffffff

sh_flag:段的标志位,表示该段在进程的虚拟地址空间中的属性,如是否可读、写、执行。

Name

Value

notes

SHF_WRITE

0x1

可读

SHF_ALLOC

0x2

需要分配空间

SHF_EXECINSTR

0x4

可执行

SHF_MASKPROC

0xf0000000

 

sh_link 和 sh_info: 如果段是与链接相关的,比如重定位表符号表等,sh_link和sh_info这两个成员所包含的意义如下所示。

sh_type

sh_link

sh_info

SHT_DYNAMIC

该段所使用的字符串表在段表中的下标

0

SHT_HASH

该段所使用的符号表在段表中的下标

0

SHT_REL

该段所使用的相应符号表在段表中的下标

该重定位表所作用的段在段表中的下标

SHT_RELA

该段所使用的相应符号表在段表中的下标

该重定位表所作用的段在段表中的下标

SHT_SYMTAB

操作系统相关的

操作系统相关的

SHT_DYNAMIC

操作系统相关的

操作系统相关的

other

SHN_UNDEF

0

2)重定位表

    rel.txt段就是重定位表,类型sh_type为SHT_REL(9)。链接器在处理目标文件时,对目标文件某些部位进行重定位,即代码段和数据段中的那部分绝对地址引用。这些重定位信息记录在ELF文件的重定位表中。

3)字符串表

    ELF中有很多字符串,如变量名段名等,但是字符串长度是不定长的,如果用固定的长度来表示比较困难,常见的做法是把字符串集中起来放到一个表中,然后使用字符串在表中的偏移来引用字符串。

4)符号表

    在ELF文件中,把函数和变量统称为符号(Sysbol),每个符号有一个相应的值叫做符号值。对函数和变量来说,符号值就是它们的地址。在ELF文件中,用.symtab这个段来记录符号表。

typedef struct{
    Elf32_Word st_name;
    Elf32_Addr st_value;
    Elf32_Word st_size;
    unsigned char st_info;
    unsigned char st_other;
    Elf32_Half st_shndx;
}Elf32_Sym
  • st_name 符号名,符号名称在字符串表中的索引
  • st_value 符号相应的值,可能是地址或一个绝对值数
  • st_size 符号大小
  • st_info 符号类型和绑定值
  • st_other 默认0
  • st_shndx 符号所在的段

st_info 高4位表示符号绑定信息,低4位表示符号类型。

Symbol Binding, ELF32_ST_BIND

Name

Value

STB_LOCAL

0

STB_GLOBAL

1

STB_WEAK

2

STB_LOPROC

13

STB_HIPROC

15

Symbol Types, ELF32_ST_TYPE

Name

Value

STT_NOTYPE

0

STT_OBJECT

1

STT_FUNC

2

STT_SECTION

3

STT_FILE

4

STT_LOPROC

13

STT_HIPROC

15

5)全局偏移表和跳转表

.plt和.got 动态链接的跳转表和全局入口表。

 

6)其它

代码段(.text): 代码数据

数据段(.data): 初始化过了的全局变量和局部静态变量

只读数据段(.rodata) 只读数据如const值、字符串常量。

.bss段:未初始化的全局变量和局部变量,是否为全局变量和局部变量预留空间和编译器的实现相关。

自定义段:在变量和函数前加__attribute__((section("name"))) 属性就可以把相应的函数或变量放到以name作为段名的段中。

 

4、ELF文件加载视图

    虽然ELF把可变数据和不可变数据分的很细,用户也可以自己添加段或命名一个段,但加载器把ELF文件加载到内存时,并不按照ELF的结构读取。例如目标文件.o里的代码段.text是section,链接时多个可重定位文件整合成一个可执行的文件,为了提高程序的效率,链接器把目标文件中相同的section 整合成一个segment,方便运行时加载器加载程序。由于虚拟内存的映射和优化的存在,ELF文件在加载到虚拟内存时,也会合并不同的段来达到节约资源的目的。

ELF文件格式解析

 

5、参考文献

1、Linux Referenced Specifications https://refspecs.linuxbase.org/

2、Executable and Linkable Format (ELF) https://elinux.org/Executable_and_Linkable_Format_(ELF)   

3、Executable and Linkable Format - Wikipedia  https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#Section_header

4、ELF文件格式 https://zhuanlan.zhihu.com/p/286088470

尊重原创技术文章,转载请注明: https://www.cnblogs.com/pingwen/p/17323862.html文章来源地址https://www.toymoban.com/news/detail-415574.html

到了这里,关于ELF文件格式解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【嵌入式】ELF格式文件分析工具汇总

    🧑 作者简介 :阿里巴巴嵌入式技术专家,深耕嵌入式+人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍 :分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导、简历面试辅导、技术架构设计优化、开发外包等

    2024年03月10日
    浏览(37)
  • STM32下载ELF文件、可执行bin文件的最小size测试

    答:可以。因为所谓的bin文件就是ELF文件的.text代码段和.data数据段。 当然前提是下载工具能识别ELF文件格式,STM32下载ELF文件并不意味着STM32可以把ELF download到Flash上,而是下载工具能从ELF提取到bin文件,下载时通信链路上传输的也只有要bin文件。 例如有elf文件: arm-none-ea

    2023年04月21日
    浏览(29)
  • 【ARM 嵌入式 编译系列 10 -- GCC 编译缩减可执行文件 elf 文件大小】

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

    2024年02月09日
    浏览(31)
  • ros编译正常,生成可执行文件无法找到的解决方法Couldn‘t find executable named 。。

    最近初学ros,出现了ros编译正常,生成可执行文件正常,但是无法用rosrun命令执行的情况。  可以看出这里的编译是没有问题的  但是电脑找不到可执行文件,我在.bashrc文件里面已经source了 cmakelists.txt我也配置完了catkin_package,add_executable,target_link_libraries,声明的顺序也没有什

    2024年02月12日
    浏览(38)
  • whisper执行ffmpeg时,报错: hp, ht, pid, tid = _winapi.CreateProcess(executable, args, 系统找不到指定的文件。

    最近在用openai/whisper-small进行语音转文字任务时,想着自己下载模型在本地离线跑,但是遇到了一下问题: 执行代码后,报错:     这个时候很大可能是这个_winapi.CreateProcess( executable , args,.....)中 executable 的问题。 当我们直接调用模型进行语音转问文字时,会调用 fmpeg对数

    2024年02月03日
    浏览(28)
  • 编译工具链 之二 详解 ELF 格式及标准、UNIX 发展、ABI

      在计算机及嵌入式系统中,二进制文件也有一定的标准格式,通常会包含在各平台的应用程序二进制接口 (Application Binary Interface,ABI)规范中。它是编译工具链必须要遵守的规范(编译工具链产生符合 ABI 的二进制文件)。   在计算机系统中,应用程序二进制接口 (

    2024年02月07日
    浏览(55)
  • ELF解析05 - hash表

    这个表叫 hash 表,它的作用是用于快速索引符号在符号表中的位置。 先看一张图: 查找一个符号的位置步骤如下: 首先,计算出符号字符串的 hash 值 然后,根据 hash 值获取 bucket 索引 index bucket[index] 里面储存的是符号表的 index,但是由于 hash 冲突问题,所以又建立了一个

    2024年01月17日
    浏览(26)
  • linux remoteproc驱动中elf解析函数实现分析

    在linux中存在的remoteproc的驱动中用到了很多elf解析的函数,比如 elf_size_of_phdr , elf_phdr_get_p_paddr 以及 elf_hdr_get_e_phnum 等等接口。当我们直接搜对应的函数时会发现无法找到其定义,其实这些函数的实现被定义在 drivers/remoteproc/remoteproc_elf_helpers.h 头文件中。 下面以ELF64为例 S

    2024年02月13日
    浏览(34)
  • Python基础——format格式化

      在python中,我们在输出字符串常用format方法设置一些特定的格式,以美化结果,同时便于更改字符串中指定内容。本文总结了format的常用方法。   format通过字符串中的花括号{}来识别和替换字符串,由此达到格式化字符串的目的。填充内容位置的识别,有按顺序自动替

    2024年02月02日
    浏览(35)
  • COCO2017标注文件格式和YOLO标注文件格式的解析

    声明:本篇博客内容是作者在制作数据集时的一些记录,引用了一些博客的内容,并结合个人理解进行了归纳,引用出处在“参考内容”章节,若有侵权,请联系作者删除。若有纰漏和错误,敬请指正! 1、COCO2017数据集的标注格式及含义 COCO 的全称是Common Objects in COntext,是

    2024年02月08日
    浏览(33)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包