ELF介绍

ELF: Executable Linkable Format

是一种Unix-like系统上的二进制文件格式标准

ELF标准中的ELF格式有4类

  • Relocatable File: 可重定位文件,内容包含了代码和数据,可以被链接成可执行文件或者共享目标文件,比如Linux上的 .o 文件。
  • Executable File: 可执行文件,是可以直接执行的程序,比如Linux上的a.out。
  • Shared Object File:共享目标文件,包含code和data, 可以作为链接器的输入,在链接阶段和Relocatable File或者Shared Object File一起链接成新的Object File,比如.a文件; 或者在运行阶段,作为动态链接器的输入和Executable File结合,作为进程的一部分来运行,比如 .so 文件。
  • CoreDump File:核心转储文件,进程意外终止时,系统可以将该进程的部分内容和终止时的其他状态信息保存到该文件中以供调试分析,比如Linux上的core文件

ELF文件格式

在这里插入图片描述

  • 链接视图:

ELF Header

test@hfeng:~/workspace/c$ readelf -h foo.o
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:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          704 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 12

程序头包含了很多重要的信息,每个字段的含义可参考ELF结构文档。主要看下:

  • Entry point address:程序的入口地址,这是没有链接的目标文件所以值是0x00
  • Start of section headers:段表开始位置的首字节
  • Size of section headers:段表的长度(字节为单位)
  • Number of section headers:段表中项数,也就是有多少段
  • Start of program headers:程序头的其实位置(对于可执行文件重要,现在为0)
  • Size of program headers:程序头大小(对于可执行文件重要,现在为0)
  • Number of program headers:程序头中的项数,也就是多少Segment(和Section有区别,后面介绍)
  • Size of this header:当前ELF文件头的大小,这里是52字节

Section Header Table

test@hfeng:~/workspace/c$ readelf -SW foo.o
There are 13 section headers, starting at offset 0x2c0:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000000000 000040 000017 00  AX  0   0  1
  [ 2] .rela.text        RELA            0000000000000000 000210 000030 18   I 10   1  8
  [ 3] .data             PROGBITS        0000000000000000 000057 000000 00  WA  0   0  1
  [ 4] .bss              NOBITS          0000000000000000 000057 000000 00  WA  0   0  1
  [ 5] .rodata           PROGBITS        0000000000000000 000057 00000d 00   A  0   0  1
  [ 6] .comment          PROGBITS        0000000000000000 000064 00002a 01  MS  0   0  1
  [ 7] .note.GNU-stack   PROGBITS        0000000000000000 00008e 000000 00      0   0  1
  [ 8] .eh_frame         PROGBITS        0000000000000000 000090 000038 00   A  0   0  8
  [ 9] .rela.eh_frame    RELA            0000000000000000 000240 000018 18   I 10   8  8
  [10] .symtab           SYMTAB          0000000000000000 0000c8 000120 18     11   9  8
  [11] .strtab           STRTAB          0000000000000000 0001e8 000027 00      0   0  1
  [12] .shstrtab         STRTAB          0000000000000000 000258 000061 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

.text 段

.text段保存代码编译后的指令,可以用objdump -s -d foo.o查看foo.o代码段的内容。

test@hfeng:~/workspace/c$ objdump -S foo.o 

foo.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
 */

#include <stdio.h>

int main ()
{
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
	printf("Hello World!\n");
   4:	48 8d 3d 00 00 00 00 	lea    0x0(%rip),%rdi        # b <main+0xb>
   b:	e8 00 00 00 00       	callq  10 <main+0x10>

	return 0;
  10:	b8 00 00 00 00       	mov    $0x0,%eax
}
  15:	5d                   	pop    %rbp
  16:	c3                   	retq   

.data段

data段保存的是已经初始化了的全局静态变量局部静态变量。使用objdump -x -s -d foo.o查看

.bss 段

用来存放程序中未初始化全局变量的一块内存区域,一般在初始化时bss段部分将会清零

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 ELF 文件段表结构体,可以使用以下 C 语言代码来定义: ``` typedef struct { 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_Word p_type; // 段类型 Elf64_Word p_flags; // 段标志 Elf64_Off p_offset; // 段在文件中的偏移 Elf64_Addr p_vaddr; // 段的虚拟地址 Elf64_Addr p_paddr; // 段的物理地址 Elf64_Xword p_filesz; // 段在文件中的大小 Elf64_Xword p_memsz; // 段在内存中的大小 Elf64_Xword p_align; // 段在内存中的对齐方式 } Elf64_Phdr; ``` 其中 `Elf32_Phdr` 和 `Elf64_Phdr` 分别代表了 ELF 文件段表在 32 位系统和 64 位系统中的结构体定义。各字段的含义如下: - `p_type`:段类型,例如可执行代码、数据、符号表等。 - `p_offset`:段在 ELF 文件中的偏移地址。 - `p_vaddr`:段在虚拟地址空间中的起始地址。 - `p_paddr`:段在物理地址空间中的起始地址。 - `p_filesz`:段在 ELF 文件中的大小。 - `p_memsz`:段在内存中的大小。 - `p_flags`:段标志,例如可读、可写、可执行等。 - `p_align`:段在内存中的对齐方式。 这些字段组成了 ELF 文件段表的基本结构体,用于描述 ELF 文件中各个段的属性信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值