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可以代表代码,字母,数字(十进制数和十六进制数)。
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 01 00 3e 00 01 00 00 00 00 00 00 00 00 00 00 00 |..>.............|
00000020 00 00 00 00 00 00 00 00 88 01 00 00 00 00 00 00 |................|
00000030 00 00 00 00 40 00 00 00 00 00 40 00 0d 00 0a 00 |....@.....@.....|
00000040 55 48 89 e5 48 83 ec 10 89 7d fc 8b 45 fc 89 c6 |UH..H....}..E...|
00000050 bf 00 00 00 00 b8 00 00 00 00 e8 00 00 00 00 c9 |................|
00000060 c3 55 48 89 e5 48 83 ec 10 c7 45 f8 01 00 00 00 |.UH..H....E.....|
00000070 8b 15 00 00 00 00 8b 05 00 00 00 00 01 d0 03 45 |...............E|
00000080 f8 03 45 fc 89 c7 e8 00 00 00 00 8b 45 f8 c9 c3 |..E.........E...|
00000090 54 00 00 00 55 00 00 00 25 64 0a 00 00 47 43 43 |T...U...%d...GCC|
000000a0 3a 20 28 55 62 75 6e 74 75 2f 4c 69 6e 61 72 6f |: (Ubuntu/Linaro|
000000b0 20 34 2e 36 2e 33 2d 31 75 62 75 6e 74 75 35 29 | 4.6.3-1ubuntu5)|
000000c0 20 34 2e 36 2e 33 00 00 14 00 00 00 00 00 00 00 | 4.6.3..........|
000000d0 01 7a 52 00 01 78 10 01 1b 0c 07 08 90 01 00 00 |.zR..x..........|
000000e0 1c 00 00 00 1c 00 00 00 00 00 00 00 21 00 00 00 |............!...|
000000f0 00 41 0e 10 86 02 43 0d 06 5c 0c 07 08 00 00 00 |.A....C..\......|
00000100 1c 00 00 00 3c 00 00 00 00 00 00 00 2f 00 00 00 |....<......./...|
00000110 00 41 0e 10 86 02 43 0d 06 6a 0c 07 08 00 00 00 |.A....C..j......|
00000120 00 2e 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62 |..symtab..strtab|
00000130 00 2e 73 68 73 74 72 74 61 62 00 2e 72 65 6c 61 |..shstrtab..rela|
00000140 2e 74 65 78 74 00 2e 64 61 74 61 00 2e 62 73 73 |.text..data..bss|
00000150 00 2e 72 6f 64 61 74 61 00 2e 63 6f 6d 6d 65 6e |..rodata..commen|
00000160 74 00 2e 6e 6f 74 65 2e 47 4e 55 2d 73 74 61 63 |t..note.GNU-stac|
00000170 6b 00 2e 72 65 6c 61 2e 65 68 5f 66 72 61 6d 65 |k..rela.eh_frame|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001c0 00 00 00 00 00 00 00 00 20 00 00 00 01 00 00 00 |........ .......|
000001d0 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000001e0 40 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00 |@.......P.......|
000001f0 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000200 00 00 00 00 00 00 00 00 1b 00 00 00 04 00 00 00 |................|
00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000220 b0 06 00 00 00 00 00 00 78 00 00 00 00 00 00 00 |........x.......|
00000230 0b 00 00 00 01 00 00 00 08 00 00 00 00 00 00 00 |................|
00000240 18 00 00 00 00 00 00 00 26 00 00 00 01 00 00 00 |........&.......|
00000250 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000260 90 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000270 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000280 00 00 00 00 00 00 00 00 2c 00 00 00 08 00 00 00 |........,.......|
00000290 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002a0 98 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
000002b0 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
000002c0 00 00 00 00 00 00 00 00 31 00 00 00 01 00 00 00 |........1.......|
000002d0 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000002e0 98 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
000002f0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000300 00 00 00 00 00 00 00 00 39 00 00 00 01 00 00 00 |........9.......|
00000310 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0...............|
00000320 9c 00 00 00 00 00 00 00 2b 00 00 00 00 00 00 00 |........+.......|
00000330 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000340 01 00 00 00 00 00 00 00 42 00 00 00 01 00 00 00 |........B.......|
00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000360 c7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000370 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000380 00 00 00 00 00 00 00 00 57 00 00 00 01 00 00 00 |........W.......|
00000390 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003a0 c8 00 00 00 00 00 00 00 58 00 00 00 00 00 00 00 |........X.......|
000003b0 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
000003c0 00 00 00 00 00 00 00 00 52 00 00 00 04 00 00 00 |........R.......|
000003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000003e0 28 07 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |(.......0.......|
000003f0 0b 00 00 00 08 00 00 00 08 00 00 00 00 00 00 00 |................|
00000400 18 00 00 00 00 00 00 00 11 00 00 00 03 00 00 00 |................|
00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000420 20 01 00 00 00 00 00 00 61 00 00 00 00 00 00 00 | .......a.......|
00000430 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000440 00 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 |................|
00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000460 c8 04 00 00 00 00 00 00 80 01 00 00 00 00 00 00 |................|
00000470 0c 00 00 00 0b 00 00 00 08 00 00 00 00 00 00 00 |................|
00000480 18 00 00 00 00 00 00 00 09 00 00 00 03 00 00 00 |................|
00000490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000004a0 48 06 00 00 00 00 00 00 66 00 00 00 00 00 00 00 |H.......f.......|
000004b0 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000004e0 01 00 00 00 04 00 f1 ff 00 00 00 00 00 00 00 00 |................|
000004f0 00 00 00 00 00 00 00 00 00 00 00 00 03 00 01 00 |................|
00000500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000510 00 00 00 00 03 00 03 00 00 00 00 00 00 00 00 00 |................|
00000520 00 00 00 00 00 00 00 00 00 00 00 00 03 00 04 00 |................|
00000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000540 00 00 00 00 03 00 05 00 00 00 00 00 00 00 00 00 |................|
00000550 00 00 00 00 00 00 00 00 11 00 00 00 01 00 03 00 |................|
00000560 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000570 21 00 00 00 01 00 04 00 00 00 00 00 00 00 00 00 |!...............|
00000580 04 00 00 00 00 00 00 00 00 00 00 00 03 00 07 00 |................|
00000590 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000005a0 00 00 00 00 03 00 08 00 00 00 00 00 00 00 00 00 |................|
000005b0 00 00 00 00 00 00 00 00 00 00 00 00 03 00 06 00 |................|
000005c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000005d0 32 00 00 00 11 00 03 00 00 00 00 00 00 00 00 00 |2...............|
000005e0 04 00 00 00 00 00 00 00 42 00 00 00 11 00 f2 ff |........B.......|
000005f0 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................|
00000600 54 00 00 00 12 00 01 00 00 00 00 00 00 00 00 00 |T...............|
00000610 21 00 00 00 00 00 00 00 5a 00 00 00 10 00 00 00 |!.......Z.......|
00000620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000630 61 00 00 00 12 00 01 00 21 00 00 00 00 00 00 00 |a.......!.......|
00000640 2f 00 00 00 00 00 00 00 00 53 69 6d 70 6c 65 53 |/........SimpleS|
00000650 65 63 74 69 6f 6e 2e 63 00 73 74 61 74 69 63 5f |ection.c.static_|
00000660 76 61 72 2e 31 35 39 34 00 73 74 61 74 69 63 5f |var.1594.static_|
00000670 76 61 72 32 2e 31 35 39 35 00 67 6c 6f 62 61 6c |var2.1595.global|
00000680 5f 69 6e 69 74 5f 76 61 72 00 67 6c 6f 62 61 6c |_init_var.global|
00000690 5f 75 6e 69 6e 69 74 5f 76 61 72 00 66 75 6e 63 |_uninit_var.func|
000006a0 31 00 70 72 69 6e 74 66 00 6d 61 69 6e 00 00 00 |1.printf.main...|
000006b0 11 00 00 00 00 00 00 00 0a 00 00 00 05 00 00 00 |................|
000006c0 00 00 00 00 00 00 00 00 1b 00 00 00 00 00 00 00 |................|
000006d0 02 00 00 00 0e 00 00 00 fc ff ff ff ff ff ff ff |................|
000006e0 32 00 00 00 00 00 00 00 02 00 00 00 03 00 00 00 |2...............|
000006f0 00 00 00 00 00 00 00 00 38 00 00 00 00 00 00 00 |........8.......|
00000700 02 00 00 00 04 00 00 00 fc ff ff ff ff ff ff ff |................|
00000710 47 00 00 00 00 00 00 00 02 00 00 00 0d 00 00 00 |G...............|
00000720 fc ff ff ff ff ff ff ff 20 00 00 00 00 00 00 00 |........ .......|
00000730 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................|
00000740 40 00 00 00 00 00 00 00 02 00 00 00 02 00 00 00 |@...............|
00000750 21 00 00 00 00 00 00 00 |!.......|
图1
SimpleSection.o的整体轮廓图如下,可能读者会想为什么会得到这样一张图,随着我们深入分析每个段的内容,答案自然会揭晓。
图 2
我们看到0x758是所有段结束的位置,换算成十进制就是1880个字节。和我们刚才获取的文件大小一样。
下面我们来利用命令来分析ELF文件结构的每个部分:
1、ELF Header
使用命令readelf -h SimpleSection.o,得到下图。
图 3
ELF文件头结构及相关参数被定义在“/usr/include/elf.h”中,如下:
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_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,得到了下图,由于是代码段,所以二进制代表汇编代码。
图 4
3、.data
使用命令objdump -s SimpleSection.o,得到数据段,如下图:
图 5
本例中存入数据段的是
int global_init_var = 84;
static int static_var = 85;
共8个字节,一个是0x00000054,十进制是84;一个是0x0000000056,十进制是85。
4、.bss
使用命令objdump -h SimpleSection.o,得到下图:
图 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,得到下图:
图 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,得到下图:
图 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,结果如下:
可以看出示所有可以被外部引用或者引用外部的函数和变量。
T表示text;D和d表示data;b表示bss,C表示Common,U表示Undef。
程序中的非静态局部变量即不在数据段也不在代码段,可能在堆栈段。
至此,所有段都分析完了。本文参考程序员的自我修养。