Linux 可重定位文件 ELF结构

Linux下ELF文件类型分为以下几种:
1、可重定位文件,例如SimpleSection.o;
2、可执行文件,例如/bin/bash;
3、共享目标文件,例如/lib/libc.so。


再接下来的文章中,我们会使用objdump,readelf,hexdump,nm等来分析一个Linux中可重定位文件SimpleSection.o。


首先附上SimpleSection.c源代码:

int printf( const char* format, ... ); int global_init_var = 84; int global_uninit_var; void func1( int i ) { printf( "%d\n", i ); }int main(void) { static int static_var = 85; static int static_var2; int a = 1; int b; func1( static_var + static_var2 + a + b ); return a; }

使用命令:
gcc -c SimpleSection.c
得到SimpleSection.o,下面我们首先附上SimpleSection.o的二进制内容以及整体轮廓。


使用命令:
hexdump -C SimpleSection.o,得到SimpleSection.o的二进制内容。
计算机科学中,二进制0 1可以代表代码,字母,数字(十进制数和十六进制数)。

000000007f 45 4c 46 02 01 01 0000 00 00 00 00 00 00 00|.ELF............| 0000001001 00 3e 00 01 00 00 0000 00 00 00 00 00 00 00|..>.............| 0000002000 00 00 00 00 00 00 0088 01 00 00 00 00 00 00|................| 0000003000 00 00 00 40 00 00 0000 00 40 00 0d 00 0a 00|....@.....@.....| 0000004055 48 89 e5 48 83 ec 1089 7d fc 8b 45 fc 89 c6|UH..H....}..E...| 00000050bf 00 00 00 00 b8 00 0000 00 e8 00 00 00 00 c9|................| 00000060c3 55 48 89 e5 48 83 ec10 c7 45 f8 01 00 00 00|.UH..H....E.....| 000000708b 15 00 00 00 00 8b 0500 00 00 00 01 d0 03 45|...............E| 00000080f8 03 45 fc 89 c7 e8 0000 00 00 8b 45 f8 c9 c3|..E.........E...| 0000009054 00 00 00 55 00 00 0025 64 0a 00 00 47 43 43|T...U...%d...GCC| 000000a03a 20 28 55 62 75 6e 7475 2f 4c 69 6e 61 72 6f|: (Ubuntu/Linaro| 000000b020 34 2e 36 2e 33 2d 3175 62 75 6e 74 75 35 29| 4.6.3-1ubuntu5)| 000000c020 34 2e 36 2e 33 00 0014 00 00 00 00 00 00 00| 4.6.3..........| 000000d001 7a 52 00 01 78 10 011b 0c 07 08 90 01 00 00|.zR..x..........| 000000e01c 00 00 00 1c 00 00 0000 00 00 00 21 00 00 00|............!...| 000000f000 41 0e 10 86 02 43 0d06 5c 0c 07 08 00 00 00|.A....C..\......| 000001001c 00 00 00 3c 00 00 0000 00 00 00 2f 00 00 00|....<......./...| 0000011000 41 0e 10 86 02 43 0d06 6a 0c 07 08 00 00 00|.A....C..j......| 0000012000 2e 73 79 6d 74 61 6200 2e 73 74 72 74 61 62|..symtab..strtab| 0000013000 2e 73 68 73 74 72 7461 62 00 2e 72 65 6c 61|..shstrtab..rela| 000001402e 74 65 78 74 00 2e 6461 74 61 00 2e 62 73 73|.text..data..bss| 0000015000 2e 72 6f 64 61 74 6100 2e 63 6f 6d 6d 65 6e|..rodata..commen| 0000016074 00 2e 6e 6f 74 65 2e47 4e 55 2d 73 74 61 63|t..note.GNU-stac| 000001706b 00 2e 72 65 6c 61 2e65 68 5f 66 72 61 6d 65|k..rela.eh_frame| 0000018000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| * 000001c000 00 00 00 00 00 00 0020 00 00 00 01 00 00 00|........ .......| 000001d006 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000001e040 00 00 00 00 00 00 0050 00 00 00 00 00 00 00|@.......P.......| 000001f000 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 0000020000 00 00 00 00 00 00 001b 00 00 00 04 00 00 00|................| 0000021000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 00000220b0 06 00 00 00 00 00 0078 00 00 00 00 00 00 00|........x.......| 000002300b 00 00 00 01 00 00 0008 00 00 00 00 00 00 00|................| 0000024018 00 00 00 00 00 00 0026 00 00 00 01 00 00 00|........&.......| 0000025003 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 0000026090 00 00 00 00 00 00 0008 00 00 00 00 00 00 00|................| 0000027000 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 0000028000 00 00 00 00 00 00 002c 00 00 00 08 00 00 00|........,.......| 0000029003 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000002a098 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 000002b000 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 000002c000 00 00 00 00 00 00 0031 00 00 00 01 00 00 00|........1.......| 000002d002 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000002e098 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 000002f000 00 00 00 00 00 00 0001 00 00 00 00 00 00 00|................| 0000030000 00 00 00 00 00 00 0039 00 00 00 01 00 00 00|........9.......| 0000031030 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|0...............| 000003209c 00 00 00 00 00 00 002b 00 00 00 00 00 00 00|........+.......| 0000033000 00 00 00 00 00 00 0001 00 00 00 00 00 00 00|................| 0000034001 00 00 00 00 00 00 0042 00 00 00 01 00 00 00|........B.......| 0000035000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 00000360c7 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 0000037000 00 00 00 00 00 00 0001 00 00 00 00 00 00 00|................| 0000038000 00 00 00 00 00 00 0057 00 00 00 01 00 00 00|........W.......| 0000039002 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000003a0c8 00 00 00 00 00 00 0058 00 00 00 00 00 00 00|........X.......| 000003b000 00 00 00 00 00 00 0008 00 00 00 00 00 00 00|................| 000003c000 00 00 00 00 00 00 0052 00 00 00 04 00 00 00|........R.......| 000003d000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000003e028 07 00 00 00 00 00 0030 00 00 00 00 00 00 00|(.......0.......| 000003f00b 00 00 00 08 00 00 0008 00 00 00 00 00 00 00|................| 0000040018 00 00 00 00 00 00 0011 00 00 00 03 00 00 00|................| 0000041000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 0000042020 01 00 00 00 00 00 0061 00 00 00 00 00 00 00| .......a.......| 0000043000 00 00 00 00 00 00 0001 00 00 00 00 00 00 00|................| 0000044000 00 00 00 00 00 00 0001 00 00 00 02 00 00 00|................| 0000045000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 00000460c8 04 00 00 00 00 00 0080 01 00 00 00 00 00 00|................| 000004700c 00 00 00 0b 00 00 0008 00 00 00 00 00 00 00|................| 0000048018 00 00 00 00 00 00 0009 00 00 00 03 00 00 00|................| 0000049000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000004a048 06 00 00 00 00 00 0066 00 00 00 00 00 00 00|H.......f.......| 000004b000 00 00 00 00 00 00 0001 00 00 00 00 00 00 00|................| 000004c000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| * 000004e001 00 00 00 04 00 f1 ff00 00 00 00 00 00 00 00|................| 000004f000 00 00 00 00 00 00 0000 00 00 00 03 00 01 00|................| 0000050000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 0000051000 00 00 00 03 00 03 0000 00 00 00 00 00 00 00|................| 0000052000 00 00 00 00 00 00 0000 00 00 00 03 00 04 00|................| 0000053000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 0000054000 00 00 00 03 00 05 0000 00 00 00 00 00 00 00|................| 0000055000 00 00 00 00 00 00 0011 00 00 00 01 00 03 00|................| 0000056004 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 0000057021 00 00 00 01 00 04 0000 00 00 00 00 00 00 00|!...............| 0000058004 00 00 00 00 00 00 0000 00 00 00 03 00 07 00|................| 0000059000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000005a000 00 00 00 03 00 08 0000 00 00 00 00 00 00 00|................| 000005b000 00 00 00 00 00 00 0000 00 00 00 03 00 06 00|................| 000005c000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 000005d032 00 00 00 11 00 03 0000 00 00 00 00 00 00 00|2...............| 000005e004 00 00 00 00 00 00 0042 00 00 00 11 00 f2 ff|........B.......| 000005f004 00 00 00 00 00 00 0004 00 00 00 00 00 00 00|................| 0000060054 00 00 00 12 00 01 0000 00 00 00 00 00 00 00|T...............| 0000061021 00 00 00 00 00 00 005a 00 00 00 10 00 00 00|!.......Z.......| 0000062000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00|................| 0000063061 00 00 00 12 00 01 0021 00 00 00 00 00 00 00|a.......!.......| 000006402f 00 00 00 00 00 00 0000 53 69 6d 70 6c 65 53|/........SimpleS| 0000065065 63 74 69 6f 6e 2e 6300 73 74 61 74 69 63 5f|ection.c.static_| 0000066076 61 72 2e 31 35 39 3400 73 74 61 74 69 63 5f|var.1594.static_| 0000067076 61 72 32 2e 31 35 3935 00 67 6c 6f 62 61 6c|var2.1595.global| 000006805f 69 6e 69 74 5f 76 6172 00 67 6c 6f 62 61 6c|_init_var.global| 000006905f 75 6e 69 6e 69 74 5f76 61 72 00 66 75 6e 63|_uninit_var.func| 000006a031 00 70 72 69 6e 74 6600 6d 61 69 6e 00 00 00|1.printf.main...| 000006b011 00 00 00 00 00 00 000a 00 00 00 05 00 00 00|................| 000006c000 00 00 00 00 00 00 001b 00 00 00 00 00 00 00|................| 000006d002 00 00 00 0e 00 00 00fc ff ff ff ff ff ff ff|................| 000006e032 00 00 00 00 00 00 0002 00 00 00 03 00 00 00|2...............| 000006f000 00 00 00 00 00 00 0038 00 00 00 00 00 00 00|........8.......| 0000070002 00 00 00 04 00 00 00fc ff ff ff ff ff ff ff|................| 0000071047 00 00 00 00 00 00 0002 00 00 00 0d 00 00 00|G...............| 00000720fc ff ff ff ff ff ff ff20 00 00 00 00 00 00 00|........ .......| 0000073002 00 00 00 02 00 00 0000 00 00 00 00 00 00 00|................| 0000074040 00 00 00 00 00 00 0002 00 00 00 02 00 00 00|@...............| 0000075021 00 00 00 00 00 00 00|!.......|


图1


使用命令ls -l SimpleSection.o,可以得到文件大小为1880字节,上面二进制内容正好也是1880个字节(0x758转换为十机制为1880)。

SimpleSection.o的整体轮廓图如下,可能读者会想为什么会得到这样一张图,随着我们深入分析每个段的内容,答案自然会揭晓。
Linux 可重定位文件 ELF结构
文章图片


图 2


我们看到0x758是所有段结束的位置,换算成十进制就是1880个字节。和我们刚才获取的文件大小一样。

下面我们来利用命令来分析ELF文件结构的每个部分:
1、ELF Header
使用命令readelf -h SimpleSection.o,得到下图。
Linux 可重定位文件 ELF结构
文章图片


图 3
ELF文件头结构及相关参数被定义在“/usr/include/elf.h”中,如下:

typedef struct { unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ Elf32_Halfe_type; /* Object file type */ Elf32_Halfe_machine; /* Architecture */ Elf32_Worde_version; /* Object file version */ Elf32_Addre_entry; /* Entry point virtual address */ Elf32_Offe_phoff; /* Program header table file offset */ Elf32_Offe_shoff; /* Section header table file offset */ Elf32_Worde_flags; /* Processor-specific flags */ Elf32_Halfe_ehsize; /* ELF header size in bytes */ Elf32_Halfe_phentsize; /* Program header table entry size */ Elf32_Halfe_phnum; /* Program header table entry count */ Elf32_Halfe_shentsize; /* Section header table entry size */ Elf32_Halfe_shnum; /* Section header table entry count */ Elf32_Halfe_shstrndx; /* Section header string table index */ } Elf32_Ehdr;

Type:ELF文件类型,本例中为REL(Relocatable File),可重定位文件。
Start of section headers,段表在文件中偏移,就是图2中Section Table的位置为392(0x188)。
Size of section headers,ELF文件头的大小为64个字节。
Number of section headers,ELF拥有多少个断,本例为13个段。见图 7。
Section header string table index,段表字符串表所在的段在段表中的下标。本例中等于10,见图 7。


2、.text
使用命令:
objdump -d SimpleSection.o,得到了下图,由于是代码段,所以二进制代表汇编代码。
Linux 可重定位文件 ELF结构
文章图片


图 4

3、.data
使用命令objdump -s SimpleSection.o,得到数据段,如下图:
Linux 可重定位文件 ELF结构
文章图片


图 5


本例中存入数据段的是

int global_init_var = 84; static int static_var = 85;

共8个字节,一个是0x00000054,十进制是84;一个是0x0000000056,十进制是85。


4、.bss
使用命令objdump -h SimpleSection.o,得到下图:
Linux 可重定位文件 ELF结构
文章图片


图 6
本例中存入数据段的是


static int static_var2;

大家会注意到int global_uninit_var; 既没有在.data段中,也没有在.bss段中。如果在前面加上static,那么则存在.bss段中。


5、.rodata
.rodata存放的只读数据。25640a00,查看ASCII表代表的就是%d\n。


6、.shstrtab(段表字符串表)
如图1,存放的是
..symtab..strtab..shstrtab..rela.text..data..bs..rodata..comment..note.GNU-stak..rela.eh_frame



7、.strtab(字符串表)
如图1,存放的是
SimpleSection.c.static_var.1594.static_var2.1595.global_init_var.global_uninit_var.func1.printf.main



8、Section Table
使用命令,readelf -S SimpleSection.o,得到下图:

Linux 可重定位文件 ELF结构
文章图片


图 7
这就解释了图1,为什么要那么画。
Offset表示段偏移,Size表示段大小。
Type,PROGBITS表示段,NOBITS表示不占空间,.RELA表示重定位段,STRTAB表示字符串表,SYMTAB表示符号表。
EntSize表示如果段中有重复的内容,则表示重复内容大小。比如下面要介绍的符号表就是重复内容组成的。
在TYPE为RELA时,Link表示该段所使用的相应符号表在段表中,本例中为11。Info表示该重定位表所作用的段在段表中的下标。.rela.text为1,.rela.eh_frame为8。


9、.symtab(符号表)
使用命令,readelf -s SimpleSection.o,得到下图:
Linux 可重定位文件 ELF结构
文章图片


图 8
Name,表示字符串在字符串表中的下标;


Ndx,SimpleSection.c为ABS,global_uninit_var为COM,表示这个变量是强引用或者弱引用,目前即不在.data段中,也不在.bss段中,等待链接时会确定。
printf为UND,表示没有定义,即引用了外部的函数。
global_init_var,NDX为3,表示在.data中,其余类似。表示符号所在的段在段表中的下标;参考图 7。


Bind GLOBAL表示可以被外部引用或者引用外部的函数和变量。
TYPE为OBJECT表示对象,FUNC表示函数,SECTION表示段,FILE表示文件,printf为NOTYPE,表示没有定义,是引用外部函数。
SIZE表示大小。
Value表示在本段中的偏移,比如static_var.1594表示在.data段中的偏移为4。 main在.data段中的偏移为21。


最后介绍个命令,nm SimpleSection.o,结果如下:
Linux 可重定位文件 ELF结构
文章图片


可以看出示所有可以被外部引用或者引用外部的函数和变量。
T表示text;D和d表示data;b表示bss,C表示Common,U表示Undef。
程序中的非静态局部变量即不在数据段也不在代码段,可能在堆栈段。


【Linux 可重定位文件 ELF结构】至此,所有段都分析完了。本文参考程序员的自我修养。

    推荐阅读