http://blog.csdn.net/edonlii/article/details/8779075

1. 读取ELF文件头:

$ readelf -h sign
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)
  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 表示文件类型,这里是 32位的 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等。

在 Section Headers 这里,可以看到 .bss 和 .shstrtab 的偏移都为 0xa0 。这是因为,没有被初始化的全局变量,会在加载阶段被用 0 来初始化,这时候它和 .data 段一样可读可写。但在编译阶段,.data 段会被分配一部分空间已存放数据(这里从偏移 0x6c 开始),而 .bss 则没有,.bss 仅有的是 section headers 。
         链接器从 .rel.text  就可以知道哪些地方需要进行重定位(relocate) 。
        .symtab 是符号表。
         Ndx 是符号表所在的 section 的 section header 编号。如 .data 段的 section header 编号是 3,而string1,string2,lenght 都是在 .data 段的。

2. 显示程序头表(目标文件没有该表):

$ readelf -l sign

Elf file type is EXEC (Executable file)
Entry point 0x400510
There are 8 program headers, starting at offset 64

Program Headers:
  Type                          Offset                              VirtAddr                PhysAddr                 FileSiz                    MemSiz                  Flags Align
  PHDR                        0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000001c0 0x00000000000001c0  R E      8
  INTERP                     0x0000000000000200 0x0000000000400200 0x0000000000400200 0x000000000000001c 0x000000000000001c  R         1
      [Requesting program interpreter: /lib64/ld-Linux-x86-64.so.2]
  LOAD                        0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000008a4 0x00000000000008a4  R E    200000
  LOAD                        0x00000000000008a8 0x00000000006008a8 0x00000000006008a8 0x0000000000000220 0x0000000000000230  RW    200000
  DYNAMIC                  0x00000000000008d0 0x00000000006008d0 0x00000000006008d0 0x00000000000001a0 0x00000000000001a0  RW     8
  NOTE                        0x000000000000021c 0x000000000040021c 0x000000000040021c  0x0000000000000044 0x0000000000000044  R         4
  GNU_EH_FRAME       0x00000000000007d8 0x00000000004007d8 0x00000000004007d8 0x000000000000002c 0x000000000000002c  R         4
  GNU_STACK             0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000  RW     8

Section to Segment mapping: (段到节的映射)
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr

.gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07

上述各段组成了最终在内存中执行的程序,其还提供了各段在虚拟地址空间和物理地址空间中的大小、位置、标志、访问授权和对齐方面的信息。各段语义如下:

PHDR保存程序头表

INTERP指定程序从可行性文件映射到内存之后,必须调用的解释器,它是通过链接其他库来满足未解析的引用,用于在虚拟地址空间中插入程序运行所需的动态库。

LOAD表示一个需要从二进制文件映射到虚拟地址空间的段,其中保存了常量数据(如字符串),程序目标代码等。

DYNAMIC段保存了由动态连接器(即INTERP段中指定的解释器)使用的信息。

3. 读取节头表:

$ readelf -S sign.o
There are 13 section headers, starting at offset 0x210:(这里指定的offset是相对于二进制文件)

Section Headers:
  [Nr] Name              Type             Address           Offset       Size              EntSize          Flags  Link  Info  Align
  [ 0]                     NULL             0000000000000000  00000000       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040       00000000000000e5  0000000000000000  AX       0     0     4
  [ 2] .rela.text        RELA             0000000000000000  000006f8       00000000000000a8  0000000000000018          11     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000128       0000000000000000  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  00000128       0000000000000000  0000000000000000  WA       0     0     4
  [ 5] .rodata           PROGBITS         0000000000000000  00000128       000000000000000b  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  00000133       000000000000001d  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  00000150       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  00000150       0000000000000058  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  000007a0       0000000000000030  0000000000000018          11     8     8
  [10] .shstrtab         STRTAB           0000000000000000  000001a8       0000000000000061  0000000000000000           0     0     1
  [11] .symtab           SYMTAB           0000000000000000  00000550       0000000000000168  0000000000000018          12     9     8
  [12] .strtab           STRTAB           0000000000000000  000006b8       0000000000000039  0000000000000000           0     0     1

  • .text:已编译程序的机器代码。
  • .rodata:只读数据,比如printf语句中的格式串和开关(switch)语句的跳转表。
  • .data:已初始化的全局C变量。局部C变量在运行时被保存在栈中,既不出现在.data中,也不出现在.bss节中。
  • .bss:未初始化的全局C变量。在目标文件中这个节不占据实际的空间,它仅仅是一个占位符。目标文件格式区分初始化未初始化变量是为了空间效率在:在目标文件中,未初始化变量不需要占据任何实际的磁盘空间。
  • .symtab:一个符号表(symbol table),它存放在程序中被定义和引用的函数和全局变量的信息。一些程序员错误地认为必须通过-g选项来编译一个程序,得到符号表信息。实际上,每个可重定位目标文件在.symtab中都有一张符号表。然而,和编译器中的符号表不同,.symtab符号表不包含局部变量的表目。
  • .rel.text:当链接噐把这个目标文件和其他文件结合时,.text节中的许多位置都需要修改。一般而言,任何调用外部函数或者引用全局变量的指令都需要修改。另一方面调用本地函数的指令则不需要修改。注意,可执行目标文件中并不需要重定位信息,因此通常省略,除非使用者显式地指示链接器包含这些信息。
  • .rel.data:被模块定义或引用的任何全局变量的信息。一般而言,任何已初始化全局变量的初始值是全局变量或者外部定义函数的地址都需要被修改。
  • .debug:一个调试符号表,其有些表目是程序中定义的局部变量和类型定义,有些表目是程序中定义和引用的全局变量,有些是原始的C源文件。只有以-g选项调用编译驱动程序时,才会得到这张表。
  • .line:原始C源程序中的行号和.text节中机器指令之间的映射。只有以-g选项调用编译驱动程序时,才会得到这张表。
  • .strtab:一个字符串表,其内容包括.symtab和.debug节中的符号表,以及节头部中的节名字。字符串表就是以null结尾的字符串序列。

$ readelf -S sign

There are 31 section headers, starting at offset 0xc00

Section Headers:
  [Nr] Name                    Type                Address                        Offset              Size                                 EntSize                          Flags  Link  Info  Align
  [ 0]                                 NULL             0000000000000000   00000000      0000000000000000   0000000000000000           0     0     0
  [ 1] .interp                     PROGBITS   0000000000400200   00000200      000000000000001c   0000000000000000   A          0        0     1
  [ 2] .note.ABI-tag         NOTE             000000000040021c   0000021c       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-id NOTE             000000000040023c  0000023c       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .hash             HASH             0000000000400260  00000260       0000000000000030  0000000000000004   A       6     0     8
  [ 5] .gnu.hash         GNU_HASH         0000000000400290  00000290       000000000000001c  0000000000000000   A       6     0     8
  [ 6] .dynsym           DYNSYM           00000000004002b0  000002b0       00000000000000a8  0000000000000018   A       7     1     8
  [ 7] .dynstr           STRTAB           0000000000400358  00000358       0000000000000065  0000000000000000   A       0     0     1
  [ 8] .gnu.version      VERSYM           00000000004003be  000003be       000000000000000e  0000000000000002   A       6     0     2
  [ 9] .gnu.version_r    VERNEED          00000000004003d0  000003d0       0000000000000030  0000000000000000   A       7     1     8
  [10] .rela.dyn         RELA             0000000000400400  00000400       0000000000000018  0000000000000018   A       6     0     8
  [11] .rela.plt         RELA             0000000000400418  00000418       0000000000000078  0000000000000018   A       6    13     8
  [12] .init             PROGBITS         0000000000400490  00000490       0000000000000018  0000000000000000  AX       0     0     4
  [13] .plt              PROGBITS         00000000004004a8  000004a8       0000000000000060  0000000000000010  AX       0     0     4
  [14] .text             PROGBITS         0000000000400510  00000510       00000000000002a8  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         00000000004007b8  000007b8       000000000000000e  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         00000000004007c8  000007c8       000000000000000f  0000000000000000   A       0     0     4
  [17] .eh_frame_hdr     PROGBITS         00000000004007d8  000007d8       000000000000002c  0000000000000000   A       0     0     4
  [18] .eh_frame         PROGBITS         0000000000400808  00000808       000000000000009c  0000000000000000   A       0     0     8
  [19] .ctors            PROGBITS         00000000006008a8  000008a8       0000000000000010  0000000000000000  WA       0     0     8
  [20] .dtors            PROGBITS         00000000006008b8  000008b8       0000000000000010  0000000000000000  WA       0     0     8
  [21] .jcr              PROGBITS         00000000006008c8  000008c8       0000000000000008  0000000000000000  WA       0     0     8
  [22] .dynamic          DYNAMIC          00000000006008d0  000008d0       00000000000001a0  0000000000000010  WA       7     0     8
  [23] .got              PROGBITS         0000000000600a70  00000a70       0000000000000008  0000000000000008  WA       0     0     8
  [24] .got.plt          PROGBITS         0000000000600a78  00000a78       0000000000000040  0000000000000008  WA       0     0     8
  [25] .data             PROGBITS         0000000000600ab8  00000ab8       0000000000000010  0000000000000000  WA       0     0     8
  [26] .bss              NOBITS           0000000000600ac8  00000ac8       0000000000000010  0000000000000000  WA       0     0     8
  [27] .comment          PROGBITS         0000000000000000  00000ac8       0000000000000038  0000000000000001  MS       0     0     1
  [28] .shstrtab         STRTAB           0000000000000000  00000b00       00000000000000fe  0000000000000000           0     0     1
  [29] .symtab           SYMTAB           0000000000000000  000013c0       0000000000000678  0000000000000018          30    47     8
  [30] .strtab           STRTAB           0000000000000000  00001a38       000000000000023c  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

PROGBITS(程序必须解释的信息,如二进制代码),STRTAB用于存储与ELF格式有关的字符串,但与程序没有直接关联,如各个节的名称(.text, .comment)

.data保存初始化过的数据,这是普通程序数据的一部分,可以在程序运行期间修改。

.rodata保存了只读数据,可以读取但不能修改,例如printf语句中的所有静态字符串封装到该节。

.init.fini保存了进程初始化和结束所用的代码,这通常是由编译器自动添加的。

.hash是一个散列表,允许在不对全表元素进行线性搜索的情况下,快速访问所有符号表项。

4. 符号表机制(readelf -s

符号表保存了程序实现或使用的所有全局变量和函数,如果程序引用一个自身代码未定义的符号,则称之为未定义符号,这类引用必须在静态链接期间用其他目标模块或库解决,或在加载时通过动态链接解决。

实现:

.symtab确定符号的名称与其值之间的关联,其中名称不是直接以字符串形式出现的,而是表示为某一字符串数组(.strtab)的索引。

.strtab保存了字符串数组(.shstrtab包含了节名称字符串表)。

.hash保存了一个散列表,以帮助快速查找符号。

typedef struct elf64_sym {

Elf64_Word st_name;          // 符号名称,字符串表中的索引

// STT_OBJECT表示符号关联到一个数据对象,如变量、数组或指针;

// STT_FUNC表示符号关联到一个函数;

// STT_NOTYPE表示符号类型未指定,用于未定义引用

unsigned char st_info;         // 类型和绑定属性:STB_LOCAL/STB_GLOBAL/STB_WEAK

unsigned char st_other;      // 语义未定义,0

Elf64_Half st_shndx;           // 相关节的索引,符号将绑定到该节,此外SHN_ABS指定符号是绝对值,不因重定位而改变,SHN_UNDEF标识未定义符号。

Elf64_Addr st_value;           // 符号的值

Elf64_Xword st_size;          // 符号的长度,如一个指针的长度或struct对象中包含的字节数。

}Elf64_Sym;

实例:

readelf 用来显示 ELF 格式文件信息,该命令选项很多,其中 -a 选项可以用来显示 ELF 文件的所有信息。

下面对 -a 选项的输出内容进行分析。

源码如下:

进行gcc编译,等操作:

a.info即为a.out 的ELF文件。

打开可见上面介绍的各个部分的内容。

以上就是-a选项所有符号表的内容。。。

下面是一个应用,例如我想解析出我在a.c文件中写的全局变量的内容。

我们可以看162-233行的内容,其中字段中有OBJECT 和 GLOBAL 的即为全局变量,我们在a.c中定义的全局变量会出现在里面,221和225行。

以及一些函数等内容都可以在这段区域内找到相应的地址和大小信息等。。。

具体的参数及用法如下图:

ELF格式文件符号表全解析及readelf命令使用方法的更多相关文章

  1. ELF格式文件分析以及运用

    基于本文的一个实践<使用Python分析ELF文件优化Flash和Sram空间的案例>. 1.背景 ELF是Executable and Linkable Format缩写,其官方规范在& ...

  2. Hex、bin、axf、elf格式文件小结

    转自Hex.bin.axf.elf格式文件小结 一.HEX Hex文件,一般是指Intel标准的十六进制文件.Intelhex 文件常用来保存单片机或其他处理器的目标程序代码.它保存物理程序存储区中的 ...

  3. 查看MDB格式文件数据表

    当打开一个MDB格式的ACCESS文件后,如果里面默认的都是窗体视图,要查看数据表的信息,可以“创建-查询设计”查看表信息,或是在SQL视图中编写SQL语句来实现. 或按着Shift键打开文件.

  4. boot.img格式文件拆解实例结构解析

    以msm8226为例,讲解android源码编译生成boot.img的结构.boot.img包括boot.img header.kernel以及ramdisk文件系统.下面是对boot.img的结构进 ...

  5. DedeCMS模板文件不存在,无法解析文档! 问题定位方法

    生成静态的时候,经常会遇到“模板文件不存在,无法解析文 档!”的问题.很多朋友试过论坛里很多方法,都是针对某些人可以解决,某些人的问题依旧,为什么呢?其实问题很可能确实是多种多样的,表现结果却是一样, ...

  6. 【shell脚本】通过遍历文件的一种批量执行shell命令的方法。

    在分析数据时,经常会有许多机械重复的命令带入,作为一个半路出家的程序猿,我曾经对这种工作束手无策.不像一个熟手那样举重若轻的分析,感觉自己的生信分析完全是个体力活.为了打开这样的局面,我开始学习如何批 ...

  7. Linux文件打包压缩、解压缩、备份命令使用方法(转载)

    对于刚刚接触Linux的人来说,一定会给Linux下一大堆各式各样的文件名给搞晕.别个不说,单单就压缩文件为例,我们知道在Windows下最常见的压缩文件就只有两种,一是,zip,另一个是.rar.可 ...

  8. 从实例分析ELF格式的.gnu.hash区与glibc的符号查找

    前言 ELF格式的.gnu.hash节在设计上比较复杂,直接从glibc源码进行分析的难度也比较大.今天静下心来看了这篇精彩的文章,终于将布隆滤波器.算数运算转为位运算等一系列细节搞懂了(值得一提的是 ...

  9. 鸿蒙内核源码分析(ELF格式篇) | 应用程序入口并不是main | 百篇博客分析OpenHarmony源码 | v51.04

    百篇博客系列篇.本篇为: v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应用程序入口并不是main | 51.c.h.o 加载运行相关篇为: v51.xx 鸿蒙内核源码分析(ELF格式篇) | ...

随机推荐

  1. python3 读取表格的数据

    python3 读取表格的数据 xlrd1.1.0的下载网址:https://pypi.python.org/pypi/xlrd. xlrd1.1.0兼容python2和python3. python ...

  2. jconsole如何查看

    https://www.jdon.com/idea/jvm-gc.html 场景: https://www.cnblogs.com/yszzu/p/9648579.html    查看大对象到底占用多 ...

  3. Java类名 方法名 常量 变量的命名习惯

    1.包 用于将完成不同功能的类分门别类,放在不同的目录(包)下,包的命名规则:将公司域名反转作为包名,对于包名,每个字母都需要小写. 如果定义类的时候没有使用package(包),那么java就认为我 ...

  4. java——注解Annotation

    http://www.cnblogs.com/xdp-gacl/p/3622275.html 元注解: @Retention:当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的 ...

  5. 学习Laravel遇到的问题纪录

    1.更换git  remote $ git remote rm origin $ git remote add origin git@github.com:your_username/hello_la ...

  6. swagger demo code

    //Application 开启注解 @EnableSwagger2public class Application { public static void main(String[] args) ...

  7. Dev Express Report 学习总结(五)在分组中使用聚集表达式AggregateExpression

    聚集表达式AggregateExpression主要包括几种:Avg(),Count(),Exists(),Max(),Min(),Single()和Sum().其中对于Sum(),在我看来主要有两种 ...

  8. c++ 封装线程库 1

    1.Pthread条件变量简介 条件变量也是线程间同步一个重要的内容,如果说互斥是一个种竞争关系,那么条件变量用于协调线程之间的关系,是一种合作关系. 条件变量的应用很多,例如:BlockingQue ...

  9. sql server 2017安装

    下载: 1. 2. 3. 安装步骤: https://www.cnblogs.com/ksguai/p/5869558.html 管理工具: Microsoft SQL Server Manageme ...

  10. CAD安装失败怎样卸载CAD 2018?错误提示某些产品无法安装

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...