ELF段介绍:
本次分析的源程序就是下面的简单程序:gcc -c SimpleSector.c
即可获得目标文件,SimpleSector.o
/*
SimpleSector.c
*/
#include <stdio.h>
int global_init_var = 84;
int global_NotInit ;
const int a=1;
const int b=3;
void func(int i)
{
printf("%d\n",i);
}
int main()
{
static int static_var = 85;
static int static_NotInit ;
static int x1 ;
static int x2;
int a =1;
int c;
c=b;
func(a+b);
return 0;
}
下面我们通过objdump -h SimpleSector.o
可以获得这个目标文件的文件头:
mgl@mgl-Inspiron-N4030:~/Work/LoaderAndLinker$ objdump -h SimpleSector.o
SimpleSector.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000050 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000008 0000000000000000 0000000000000000 00000090 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 0000000c 0000000000000000 0000000000000000 00000098 2**2
ALLOC
3 .rodata 0000000c 0000000000000000 0000000000000000 00000098 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 00000035 0000000000000000 0000000000000000 000000a4 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000d9 2**0
CONTENTS, READONLY
6 .eh_frame 00000058 0000000000000000 0000000000000000 000000e0 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
这里我们可以看出本目标文件有6个段,其中有代码段,数据段,bss段,只读数据段,注释段等等。
然后我们的任务是分析出每一段都是存储了上面简单测试函数的哪一部分?
我们使用objdump -s SimpleSector.o
命令得到上面每个段的详细数据
mgl@mgl-Inspiron-N4030:~/Work/LoaderAndLinker$ objdump -s SimpleSector.o
SimpleSector.o: file format elf64-x86-64
Contents of section .text:
0000 554889e5 4883ec10 897dfc8b 45fc89c6 UH..H....}..E...
0010 bf000000 00b80000 0000e800 00000090 ................
0020 c9c35548 89e54883 ec10c745 f8010000 ..UH..H....E....
0030 00c745fc 03000000 ba030000 008b45f8 ..E...........E.
0040 01d089c7 e8000000 00b80000 0000c9c3 ................
Contents of section .data:
0000 54000000 55000000 T...U... ------>(这里就是84 和85)
Contents of section .rodata:
0000 01000000 03000000 25640a00 ........%d.. --------->(这里就是1 3 d%)
Contents of section .comment:
0000 00474343 3a202855 62756e74 7520352e .GCC: (Ubuntu 5.
0010 342e302d 36756275 6e747531 7e31362e 4.0-6ubuntu1~16.
0020 30342e34 2920352e 342e3020 32303136 04.4) 5.4.0 2016
0030 30363039 00 0609.
Contents of section .eh_frame:
0000 14000000 00000000 017a5200 01781001 .........zR..x..
0010 1b0c0708 90010000 1c000000 1c000000 ................
0020 00000000 22000000 00410e10 8602430d ...."....A....C.
0030 065d0c07 08000000 1c000000 3c000000 .]..........<...
0040 00000000 2e000000 00410e10 8602430d .........A....C.
0050 06690c07 08000000 .i......
我们可以看出来这里.data
段包含的数据是全局变量和静态局部变量。
.rodata
段包含的是只读变量(const修饰的)和字符串变量。
.bss
段包含的是未初始化的全局变量和局部局部变量。
下面我们对simpleSector.o进行分析
使用readelf -h 得到段的头属性
mgl@mgl-Inspiron-N4030:~/Work/LoaderAndLinker$ readelf -h SimpleSector.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: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 1136 (bytes into file) --->注意这里实际上是0x470.
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 13
Section header string table index: 10
使用命令:readelf -S simpleSector.o 得到的是段属性:
mgl@mgl-Inspiron-N4030:~/Work/LoaderAndLinker$ readelf -S SimpleSector.o
There are 13 section headers, starting at offset 0x470:
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
0000000000000050 0000000000000000 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 00000390
0000000000000048 0000000000000018 I 11 1 8
[ 3] .data PROGBITS 0000000000000000 00000090
0000000000000008 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 00000098
000000000000000c 0000000000000000 WA 0 0 4
[ 5] .rodata PROGBITS 0000000000000000 00000098
000000000000000c 0000000000000000 A 0 0 4
[ 6] .comment PROGBITS 0000000000000000 000000a4
0000000000000035 0000000000000001 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 000000d9
0000000000000000 0000000000000000 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 000000e0
0000000000000058 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 000003d8
0000000000000030 0000000000000018 I 11 8 8
[10] .shstrtab STRTAB 0000000000000000 00000408
0000000000000061 0000000000000000 0 0 1
[11] .symtab SYMTAB 0000000000000000 00000138
00000000000001e0 0000000000000018 12 13 8
[12] .strtab STRTAB 0000000000000000 00000318
0000000000000078 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)
下面是书中一句话
真正了不起的程序员对自己的程序的每一个字节都了如指掌。 ——————佚名