这一章主要讲述目标文件有哪几个部分组成以及介绍组成部分。
ELF格式文件有文件头和各个段组成。
1.文件头:描述了文件的文件属性,包括文件是否可执行,是静态链接还是动态链接及入口地址、目标硬件,目标操作系统等信息,还包括一个段表。可以从段表中得到每个段的所有信息
2.段(Section):sections 是在ELF文件里头,用以装载内容数据的最小容器。在ELF文件里面,每一个 sections 内都装载了性质属性都一样的内容。例如
1) .text section 里装载了可执行代码;
2) .data section 里面装载了被初始化的数据;
3) .bss section 里面装载了未被初始化的数据;
4) 以 .rec 打头的 sections 里面装载了重定位条目;
5) .symtab 或者 .dynsym section 里面装载了符号信息;
6) .strtab 或者 .dynstr section 里面装载了字符串信息;
7) 其他还有为满足不同目的所设置的section,比方满足调试的目的、满足动态链接与加载的目的等等。
为什么要把代码段和数据段分开呢,好处有以下两点
1.可以分开设置属性。指令区域设置为可读可执行,数据区域设置成可读写。这样可以防止指令被篡改。
2.提高缓存命中率,加快程序运行。现代cpu一般都有数据缓存和指令缓存。分开存放可以提高缓存命中率
3.节约内存。系统中运行多个程序的副本,可以共用其中的指令数据和只读数据等,只需要再多用些内存存放数据区域
可以使用objdump -h打印elf文件的各个段的基本信息打印出来。
aston@ubuntu:/home/file/x264$ objdump -h x264
x264: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000400238 0000000000400238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 0000000000400254 0000000000400254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 0000000000400274 0000000000400274 00000274 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 00000e1c 0000000000400298 0000000000400298 00000298 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 00003c00 00000000004010b8 00000000004010b8 000010b8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 000039ab 0000000000404cb8 0000000000404cb8 00004cb8 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version 00000500 0000000000408664 0000000000408664 00008664 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version_r 00000160 0000000000408b68 0000000000408b68 00008b68 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rela.dyn 000000c0 0000000000408cc8 0000000000408cc8 00008cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.plt 00000b70 0000000000408d88 0000000000408d88 00008d88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .init 0000001a 00000000004098f8 00000000004098f8 000098f8 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .plt 000007b0 0000000000409920 0000000000409920 00009920 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt.got 00000010 000000000040a0d0 000000000040a0d0 0000a0d0 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00187b52 000000000040a0e0 000000000040a0e0 0000a0e0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000009 0000000000591c34 0000000000591c34 00191c34 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 000264cb 0000000000591c40 0000000000591c40 00191c40 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 0000297c 00000000005b810c 00000000005b810c 001b810c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 00014cfc 00000000005baa88 00000000005baa88 001baa88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 00000000007cfa28 00000000007cfa28 001cfa28 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 00000000007cfa30 00000000007cfa30 001cfa30 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .jcr 00000008 00000000007cfa38 00000000007cfa38 001cfa38 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .data.rel.ro 00001330 00000000007cfa40 00000000007cfa40 001cfa40 2**5
CONTENTS, ALLOC, LOAD, DATA
22 .dynamic 00000240 00000000007d0d70 00000000007d0d70 001d0d70 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .got 00000040 00000000007d0fb0 00000000007d0fb0 001d0fb0 2**3
CONTENTS, ALLOC, LOAD, DATA
24 .got.plt 000003e8 00000000007d1000 00000000007d1000 001d1000 2**3
CONTENTS, ALLOC, LOAD, DATA
25 .data 000019f0 00000000007d1400 00000000007d1400 001d1400 2**5
CONTENTS, ALLOC, LOAD, DATA
26 .bss 000f9140 00000000007d2e00 00000000007d2e00 001d2df0 2**6
ALLOC
27 .comment 0000002d 0000000000000000 0000000000000000 001d2df0 2**0
CONTENTS, READONLY
如果想要看各个段大小可以用size命令
aston@ubuntu:/home/file/x264$ size x264
text data bss dec hex filename
1897775 13216 1020224 2931215 2cba0f x264
3.3.1 代码段
可以使用objdump中的-s参数将所有段的内容按16进制打印出来。-d参数可以将所有包含指令的段反汇编。
3.3.2 数据段和只读数据段
.data段保存的是已经初始化的全局静态变量和局部静态变量
3.3.3 bss段
bss段存放的是未初始化的全局变量和局部静态变量。.bss
不占据实际的磁盘空间,只在段表中记录大小,在符号表中记录符号。当文件加载运行时,才分配空间以及初始化。有个疑问,我把符号表strip掉了,为什么程序执行的时候依然知道bss中每个变量的大小?
3.4 其他段
可以使用objcopy把一个二进制文件导入到代码中供其使用