The-ELF-Binary-Format

这篇博客深入探讨了ELF(Executable and Linkable Format)二进制文件的结构,包括文件类型、程序头、节头、符号和重定位。文章详细介绍了PT_LOAD、PT_DYNAMIC等程序头类型,以及.text、.data、.got.plt等节,强调了它们在程序执行和动态链接中的作用。此外,还讨论了动态链接器如何使用辅助向量、PLT和GOT进行动态链接,并解析了动态段在程序加载过程中的作用。
摘要由CSDN通过智能技术生成

The ELF Binary Format

1. ELF file types

一个ELF文件可以被标记为以下几种类型之一。

  • ET_NONE: 未知类型,不确定或未定义
  • ET_REL:重定位文件, ELF被标记为relocatable意味者该文件被标记一段可重定位的代码,或目标文件。可重定位目标文件通常是还未被链接到可执行程序的一段位置独立的代码Position independent code (PIC)。编译完代码后可以看到.o格式的文件,这种文件包含了创建可执行文件所需要的代码和数据。
  • ET_EXEC: 可执行文件, ELF类型为executable,意味着该文件被标记为可执行文件。 这些类型的文件也称为程序,是一个进程开始执行的入口。
  • ET_DYN: 共享目标文件,ELF类型为dynamic,意味着该文件被标记为了一个动态的可链接的目标文件,也称为共享库。这类共享库会在程序运行时被装载并链接到程序的进程镜像中。
  • ET_CORE: 核心文件,在程序崩溃或者进程传递了一个SIGSEGV信号(分段违规)时,会在核心文件中记录整个进程的镜像消息,可以用GDB读取这类文件来辅助调试并查找程序崩溃的原因。

使用readelf -h 可以查看ELF文件,查看原始的ELF文件头。ELF文件头从文件的0偏移开始,是除了文件头之后剩余部分文件的一个映射。随便找了一个在BSD编辑的EXEC文件,readelf -h 之后如下图

这里写图片描述

ELF头部的结构定义如下:

#define EI_NIDENT 16
           typedef struct {
   
               unsigned char e_ident[EI_NIDENT];
               uint16_t      e_type;
               uint16_t      e_machine;
               uint32_t      e_version;
               ElfN_Addr     e_entry;
               ElfN_Off      e_phoff;
               ElfN_Off      e_shoff;
               uint32_t      e_flags;
               uint16_t      e_ehsize;
               uint16_t      e_phentsize;
               uint16_t      e_phnum;
               uint16_t      e_shentsize;
               uint16_t      e_shnum;
               uint16_t      e_shstrndx;
           } ElfN_Ehdr;

ps:readelf命令

readelf -S <object> //查询节头表
readelf -l <object> //查询程序头表
readelf -s <object> //查询符号表
readelf -e <object> //查询ELF文件头数据
readelf -r <object> //查询重定位入口
readelf -d <object> //查询动态段

2. ELF program headers

ELF程序头是对二进制文件中段的描述,是程序装载必需的一部分。段(segment)是在内存装载时被解析的,描述了磁盘上可执行文件的内存布局以及如何映射到内存中。

程序头描述了可执行文件(包括共享库)中段及其类型(为那种类型的数据或代码而保留的段)。

//ELF32_Phdr结构,构成了32位ELF可执行文件程序头表的一个程序头条目。 program header table
typedef struct {
   
    uint32_t   p_type;   (segment type)
    Elf32_Off  p_offset; (segment offset)
    Elf32_Addr p_vaddr;   (segment virtual address)
    Elf32_Addr p_paddr;    (segment physical address)
    uint32_t   p_filesz;   (size of segment in the file)
    uint32_t   p_memsz; (size of segment in memory)
    uint32_t   p_flags; (segment flags, I.E execute|read|read)
    uint32_t   p_align;  (segment alignment in memory)
  } Elf32_Phdr;
// 这些变量描述了段在文件和内存中的布局

下面讨论5个常见的程序头类型。

1.PT_LOAD

一个可执行文件至少有一个PT_LOAD类型的段

这类程序头描述的是可装载的段(a loadable segment),即这种类型的段将被装载或映射到内存中。

一个需要动态链接的ELF可执行文件通常包含以下两个可装载的段(类型为PT_LOAD)

  • 存放程序代码的text段;
  • 存放全局变量和动态链接信息的data段。

上面的两个段将会被映射到内存中,并根据p_align中存放的值在内存中对齐。

2.PT_DYNAMIC-动态段的Phdr

动态段是动态链接可执行文件所特有的,包含了动态链接器所必需的一些信息。在动态段中包含了一些标记值和指针,包括但不限于以下内容:

  • 运行时需要链接的共享库列表;
  • 全局偏移表(GOT,Global offset table)的地址;
  • 重定位条目的相关信息。

Following is complete list of the tag names:完整的标记名列表

Tag name/标记名 描述
DT_HASH 符号散列表的地址
DT_STRTAB 字符串表的地址
DT_SYMTAB 符号表的地址
DT_RELA 相对地址重定位表的地址
DT_RELASZ Rela表的字节大小
DT_RELAENT Rela表条目的字节大小
DT_STRSZ 字符串表的字节大小
DT_SYMENT 符号表条目的字节大小
DT_INIT 初始化函数的地址
DT_FINT 终止函数的地址
DT_SONAME 共享目标文件名的字符串表偏移量
DT_RPATH 库搜索路径的字符串表偏移量
DT_SYMBOLIC 修改链接器,在可执行文件之前的共享目标文件中搜索符号
DT_REL Rel relocs表的地址
DT_RELSZ Rel表的字节大小
DT_RELENT Rel表条目的字节大小
DT_PLTREL PLT引用的reloc类型(Rela或Rel)
DT_DEBUG 还未进行定义,为测试保留
DT_TEXTREL 缺少此项表明重定位只能应用于可写段
DT_JMPREL 仅用于PLT的重定位条目地址
DT_BIND_NOW 指示动态链接器在将控制权交给可执行文件之前处理所有的重定位
DT_RUNPATH 库搜索路径的字符串表偏移量

动态段包含了一些结构体,在这些结构中存放着与动态链接相关的信息。

//32位ELF文件的动态段结构体:d_tag成员变量控制着d_un的含义。
typedef struct {
   
Elf32_Sword    d_tag;
    union {
   
Elf32_Word d_val;
Elf32_Addr d_ptr;
    } d_un;
} Elf32_Dyn;
extern Elf32_Dyn _DYNAMIC[];

3. PT_NOTE

PT_NOTE类型的段可能保存了与特定供应商或者系统相关的附加消息。

//ELF规范中的定义
Sometimes a vendor or system builder needs to mark an object file with special information that other programs will check for conformance, compatibility, and so on. Sections of type SHT_NOTE and program header elements of type PT_NOTE can be used for this purpose. (SHT_NOTE类型的节section和PT_NOTE类型的程序头元素可以用于这一目的)The note information in sections and program header elements holds any number of entries, each of which is an array of 4-byte words in the format of the target processor. Labels appear below to help explain note information organization, but they are not part of the specification.

这一段只保存了操作系统的规范信息,在可执行文件运行时是不需要这个段的。(since the system will just assume the executable is native either way)。 容易成为病毒感染的一个地方。
NOTE段病毒(http://vxheavens.com/lib/vhe06.html

4. PT_INTERP

PT_INTERP段只将位置和大小信息存放在一个以null为终止符的字符串中,是对程序解释器位置的描述。例如 /lib/linux-ld

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值