ELF格式⽂件符号表全解析及readelf命令使⽤⽅法1、readelf 命令
⽰例:hello.c 程序
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a=100;
printf("hello world!\n");
return 0;
}
1. 读取 ELF ⽂件头:readelf -h hello.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: EXEC(Executable file)(.so⽂件DYN(Shared object file)、.o⽂件REL(Relocatable file)、Core dump⽂件(CORE)) Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400510
Start of program headers: 64 (bytes into file)
Start of section headers: 3072 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
cf名字能用的符号Size of program headers: 56 (bytes)
Number of program headers: 8
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 28
在 readelf 的输出中:
第 1 ⾏,ELF Header: ELF ⽂件头开始。
第 2 ⾏,Magic 魔数,⽤来指名该⽂件是⼀个 ELF ⽬标⽂件。
第⼀个字节 7F 是个固定的数;后⾯的 3 个字节正是 E, L, F 三个字母的 ASCII 形式。
第 3 ⾏,CLASS 表⽰⽂件类型,这⾥是 64位的 ELF 格式。
第 4 ⾏,Data 表⽰⽂件中的数据是按照什么格式组织(⼤端或⼩端)的,
不同处理器平台数据组织格式可能就不同,如x86平台为⼩端存储格式。
第 5 ⾏,当前 ELF ⽂件头版本号,这⾥版本号为 1 。
第 6 ⾏,OS/ABI ,指出操作系统类型,ABI 是 Application Binary Interface 的缩写。
第 7 ⾏,ABI 版本号,当前为 0 。
第 8 ⾏,Type 表⽰⽂件类型。ELF ⽂件有 3 种类型,
⼀种是如上所⽰的 Relocatable file 可重定位⽬标⽂件,
⼀种是可执⾏⽂件(Executable),
另外⼀种是共享库(Shared Library) 。
第 9 ⾏,机器平台类型。
第 10 ⾏,当前⽬标⽂件的版本号。
第 11 ⾏,程序的虚拟地址⼊⼝点,因为这还不是可运⾏的程序,故⽽这⾥为零。
第 12 ⾏,与 11 ⾏同理,这个⽬标⽂件没有 Program Headers。
第 13 ⾏,sections 头开始处,这⾥ 208 是⼗进制,表⽰从地址偏移 0xD0 处开始。
第 14 ⾏,是⼀个与处理器相关联的标志,x86 平台上该处为 0 。
第 15 ⾏,ELF ⽂件头的字节数。
第 16 ⾏,因为这个不是可执⾏程序,故此处⼤⼩为 0。
第 17 ⾏,同理于第 16 ⾏。
第 18 ⾏,sections header 的⼤⼩,这⾥每个 section 头⼤⼩为 40 个字节。
第 19 ⾏,⼀共有多少个 section 头,这⾥是 8 个。
第 20 ⾏,section 头字符串表索引号,从 Section Headers 输出部分可以看到其内容的偏移
在 0xa0 处,从此处开始到0xcf 结束保存着各个 sections 的名字,
如 .data,.text,.bss等。
2. 显⽰程序头表:readelf -l a.out
上述各段组成了最终在内存中执⾏的程序,其还提供了各段在虚拟地址空间和物理地址空间中的⼤⼩、位置、标志、访问授权和对齐⽅⾯的信息。各段语义如下:
PHDR :保存程序头表 ( Program header => PHDR)
INTERP :指定程序从可⾏性⽂件映射到内存之后,必须调⽤的解释器。它是通过链接其他库来满⾜未解析的引⽤,⽤于在虚拟地址空间中插⼊程序运⾏所需的动态库。
LOAD :表⽰⼀个需要从⼆进制⽂件映射到虚拟地址空间的段,其中保存了常量数据(如字符串),程序⽬标代码等。
DYNAMIC :保存了由动态连接器(即INTERP段中指定的解释器)使⽤的信息。
3. 读取节头表:readelf -S
读取 .o ⽂件
段 ( 也叫做 节 ,类⽐ ⽵⼦,⼀节⼀节 的)说明:
.text:已编译程序的机器代码。
.rodata:只读数据,⽐如:printf 语句中的格式串 和 开关(switch)语句的跳转表。
.data:已初始化的全局C变量。局部C变量在运⾏时被保存在栈中,既不出现在.data中,也不出现在.bss节中。
.bss:未初始化的全局C变量。在⽬标⽂件中,未初始化变量不占据实际的空间,它仅仅是⼀个占位符。⽬标⽂件格式区分初始化和未初始化变量是为了空间效率在。
.symtab:⼀个符号表(symbol table),它存放在程序中被定义和引⽤的函数和全局变量的信息。⼀些程序员错误地认为必须通过 -
g 选项来编译⼀个程序,得到符号表信息。实际上,每个可重定位⽬标⽂件在 .symtab 中都有⼀张符号表。然⽽,和编译器中的符号
表不同,.symtab 符号表不包含局部变量的表⽬。
.
<:当链接噐把这个⽬标⽂件和其他⽂件结合时,.text节中的许多位置都需要修改。⼀般⽽⾔,任何调⽤外部函数或者引⽤全局变量的指令都需要修改。另⼀⽅⾯调⽤本地函数的指令则不需要修改。注意,可执⾏⽬标⽂件中并不需要重定位信息,因此通常省略,除⾮使⽤者显式地指⽰链接器包含这些信息。
.rel.data:被模块定义或引⽤的任何全局变量的信息。⼀般⽽⾔,任何已初始化全局变量的初始值是全局变量或者外部定义函数的地址都需要被修改。
.debug:⼀个调试符号表,其有些表⽬是程序中定义的局部变量和类型定义,有些表⽬是程序中定义和引⽤的全局变量,有些是原始的C源⽂件。只有以 -g 选项调⽤编译驱动程序时,才会得到这张表。
.line:原始C源程序中的⾏号和.text节中机器指令之间的映射。只有以 -g 选项调⽤编译驱动程序时,才会得到这张表。
.strtab:⼀个字符串表,其内容包括 .symtab 和 .debug 节中的符号表,以及节头部中的节名字。字符串表就是以null结尾的字符串序列。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论