1 ELF目标文件格式
- 目标文件:编译器编译后生成的文件,目标指的是目标平台(例如:x86/x64平台、arm64平台等),这决定了编译器使用的机器指令集。
- 目标文件与目标平台是二进制兼容的(即目标文件已经是适应某一种CPU架构体系上的二进制指令),例如一个64位的x64平台上编译出来的目标文件是无法链接成arm64平台上的可执行文件。
- 最古老的目标文件格式是a.out,后来陆续发展成为COFF格式、PE格式、ELF格式等;
- ELF(Executable and Linkable Format):可执行的和可链接的格式,是一个目标文件格式的标准。它用于存储Linux程序。
2 ELF文件的3种类型(可执行文件格式中3种不同类型的目标文件)
- 可重定位文件:一般是中间文件,还需要继续处理。由编译器和汇编器创建,一个源文件会生成一个可重定位文件。文件中保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件、静态库文件或共享目标文件。
- 可执行文件:一般由多个可重定位文件结合而成,是完成了所有重定位和符号解析工作的文件,文件中保存着一个用来执行的程序。
- 共享目标文件:即共享库,是可以被可执行文件或其他库文件使用的目标文件。
3 ELF文件的作用
- ELF文件参与程序的链接和程序的执行,可以从如下两个方面来看待ELF文件的作用:
- 如果用于编译和链接(可重定位目标文件),则编译器和链接器会把ELF文件看成节的集合,所有节由节头表描述,段头表可选;
- 如果用于加载执行(可执行文件),则加载器会把ELF文件看成段头表描述的段的集合,一个段可能包含多个节,节头表可选;
4 从源文件hello.c------>可执行文件hello的详细过程
- 预处理:gcc -E hello.c -o hello.i,主要是删除所有的注释、删除所有的#define,展开所有的宏定义、处理所有的条件预编译命令、处理#include预编译命令、添加行号及文件名标识
- 编译:gcc -S hello.i -o hello.s,主要是检查代码的规范性、是否有语法错误,检查无误后,gcc把代码翻译成汇编代码,不会进一步翻译成机器代码
- 汇编:gcc -c hello.s -o hello.o------目标文件(hello.o是可重定位目标文件),汇编后生成的xxx.o文件已经是ELF格式的文件了,目标文件至少含有3个section,分别是.text(用于存放程序执行代码的一块内存区域)、.data(用于存放程序中已经初始化的全局变量的一块内存区域)、.bss(用于存放程序中未初始化的全局变量的一块内存区域)
- 查看目标文件的节头表信息(section table header):readelf -S hello.o
- Type列是PROGBITS表示该节存储的是代码;
- 由于当前汇编生成的是可重定位目标文件还不是可执行文件,所以没有设置其对应的虚拟地址。在下一步链接完成后,该部分会变成将在代码段在内存中的虚拟地址,故当前Address列全部是0;
- 代码段中Flags列的含义,A表示需要加载到内存中,X表示对应内存需要可执行;
- 查看目标文件的节头表信息(section table header):readelf -S hello.o
[cdl@h3c temp]$ readelf -S hello.o
There are 13 section headers, starting at offset 0x138:
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
0000000000000015 0000000000000000 AX 0 0 4
[ 2] .rela.text RELA 0000000000000000 00000598
0000000000000030 0000000000000018 11 1 8
[ 3] .data PROGBITS 0000000000000000 00000058
0000000000000000 0000000000000000 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 00000058
0000000000000000 0000000000000000 WA 0 0 4
[ 5] .rodata PROGBITS 0000000000000000 00000058
000000000000000c 0000000000000000 A 0 0 1
[ 6] .comment PROGBITS 0000000000000000 00000064
000000000000002e 0000000000000001 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 00000092
0000000000000000 0000000000000000 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 00000098
0000000000000038 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 000005c8
0000000000000018 0000000000000018 11 8 8
[10] .shstrtab STRTAB 0000000000000000 000000d0
0000000000000061 0000000000000000 0 0 1
[11] .symtab SYMTAB 0000000000000000 00000478
0000000000000108 0000000000000018 12 9 8
[12] .strtab STRTAB 0000000000000000 00000580
0000000000000013 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
- 链接:gcc hello.o -o hello-------可执行文件hello,链接环节是将各种代码和数据部分收集起来并组合成一个单一文件的过程,这个文件可以被加载到内存中并执行。换句话说,链接就是把多个文件拼接到一起,本质上是section的拼接。
- 对比链接前目标文件的节头表信息,可以发现可执行文件的节头表中节多了,多出来的节是从外部库中添加过来的,编译器进行了整合,并安排了地址布局。同时,代码段.text的Address列不再是全为0,已经有值了。
[cdl@h3c temp]$ readelf -S hello
There are 39 section headers, starting at offset 0x11c8:
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-i NOTE 000000000040023c 0000023c
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400260 00000260
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400280 00000280
0000000000000060 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 00000000004002e0 000002e0
000000000000003d 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 000000000040031e 0000031e
0000000000000008 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400328 00000328
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400348 00000348
0000000000000018 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000400360 00000360
0000000000000030 0000000000000018 A 5 12 8
[11] .init PROGBITS 0000000000400390 00000390
0000000000000018 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 00000000004003a8 000003a8
0000000000000030 0000000000000010 AX 0 0 4
[13] .text PROGBITS 00000000004003e0 000003e0
00000000000001d8 0000000000000000 AX 0 0 16
[14] .fini PROGBITS 00000000004005b8 000005b8
000000000000000e 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 00000000004005c8 000005c8
000000000000001c 0000000000000000 A 0 0 8
[16] .eh_frame_hdr PROGBITS 00000000004005e4 000005e4
0000000000000024 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000400608 00000608
000000000000007c 0000000000000000 A 0 0 8
[18] .ctors PROGBITS 0000000000600688 00000688
0000000000000010 0000000000000000 WA 0 0 8
[19] .dtors PROGBITS 0000000000600698 00000698
0000000000000010 0000000000000000 WA 0 0 8
[20] .jcr PROGBITS 00000000006006a8 000006a8
0000000000000008 0000000000000000 WA 0 0 8
[21] .dynamic DYNAMIC 00000000006006b0 000006b0
0000000000000190 0000000000000010 WA 6 0 8
[22] .got PROGBITS 0000000000600840 00000840
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 0000000000600848 00000848
0000000000000028 0000000000000008 WA 0 0 8
[24] .data PROGBITS 0000000000600870 00000870
0000000000000004 0000000000000000 WA 0 0 4
[25] .bss NOBITS 0000000000600878 00000874
0000000000000010 0000000000000000 WA 0 0 8
[26] .comment PROGBITS 0000000000000000 00000874
000000000000002d 0000000000000001 MS 0 0 1
[27] .debug_aranges PROGBITS 0000000000000000 000008b0
0000000000000060 0000000000000000 0 0 16
[28] .debug_pubnames PROGBITS 0000000000000000 00000910
000000000000005f 0000000000000000 0 0 1
[29] .debug_info PROGBITS 0000000000000000 0000096f
000000000000023b 0000000000000000 0 0 1
[30] .debug_abbrev PROGBITS 0000000000000000 00000baa
000000000000012a 0000000000000000 0 0 1
[31] .debug_line PROGBITS 0000000000000000 00000cd4
0000000000000120 0000000000000000 0 0 1
[32] .debug_str PROGBITS 0000000000000000 00000df4
0000000000000100 0000000000000001 MS 0 0 1
[33] .debug_loc PROGBITS 0000000000000000 00000ef4
00000000000000d9 0000000000000000 0 0 1
[34] .debug_pubtypes PROGBITS 0000000000000000 00000fcd
000000000000002f 0000000000000000 0 0 1
[35] .debug_ranges PROGBITS 0000000000000000 00000ffc
0000000000000050 0000000000000000 0 0 1
[36] .shstrtab STRTAB 0000000000000000 0000104c
0000000000000177 0000000000000000 0 0 1
[37] .symtab SYMTAB 0000000000000000 00001b88
0000000000000738 0000000000000018 38 59 8
[38] .strtab STRTAB 0000000000000000 000022c0
000000000000020e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
- 查看段头表(program headers table):readelf -l hello.o,链接后得到的可执行文件多了段头表。可执行文件的执行,本质上是操作系统按照段头表的排列,将可执行文件按照排列好的布局加载到内存中,再跳转到其中的代码段进行执行。
[cdl@h3c temp]$ readelf -l hello
Elf file type is EXEC (Executable file)
Entry point 0x4003e0
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
0x0000000000000684 0x0000000000000684 R E 200000
LOAD 0x0000000000000688 0x0000000000600688 0x0000000000600688
0x00000000000001ec 0x0000000000000200 RW 200000
DYNAMIC 0x00000000000006b0 0x00000000006006b0 0x00000000006006b0
0x0000000000000190 0x0000000000000190 RW 8
NOTE 0x000000000000021c 0x000000000040021c 0x000000000040021c
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x00000000000005e4 0x00000000004005e4 0x00000000004005e4
0x0000000000000024 0x0000000000000024 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 .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
5 链接与库
- 链接过程详细上来说分为两个步骤:符号解析和重定位;根据链接的时间点不同,可以分成静态链接和动态链接;
- 如下以hello.c文件为例说明符号解析和重定位过程
- 符号解析:由于hello.c文件中只有两个符号main和printf,由于main的实现就在hello.c文件中,而printf的实现显然不在hello.c中,因此,hello.c编译为hello.o后,main这个符号就是有定义的,printf这个符号就是无定义的。注意:这里讨论的符号有无定义是指函数对应的机器指令地址是否在当前文件中。编译器需要到其他共享库中找到printf这个符号的定义(机器指令片段),找到后把该片机器指令与hello.o拼接到一起,生成可执行文件hello。这样,hello中符号printf就有了明确的地址。
- 重定位:在拼接所有的目标文件同时,编译器会确定各个函数加载到内存中的运行地址,然后反过来去修改所有调用该函数的机器指令,使得该指令能跳转到正确的内存地址,这个过程即重定位。
-
符号:符号包含全局变量和全局函数,链接器上下文中的3种不同符号如下:
- 由模块定义并能被其他模块引用的全局符号。全局链接器符号对应非静态的C函数和被定义为不带C static属性的全局变量;
- 由其他模块定义并被模块引用的全局符号。这些符号称为外部符号,对应定义在其他模块中的C函数和变量;
- 只被模块定义和引用的本地符号。
- 符号表:一种供编译器用于保存有关源程序构造的各种信息的数据结构。这些信息在编译器分析阶段被逐步收集并保存在符号表中,它们在综合阶段用于生成目标代码。符号表的作用是查找未知函数在其他库文件中的代码段的具体位置。以hello为例,其调用的printf是外部库提供的函数。在链接前,编译器需要把类似printf这类的符号都记录下来,存储在符号表中。
- 链接前,查看符号表:readelf -s hello.o或objdump -t hello.o
[cdl@h3c temp]$ readelf -s hello.o
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 7
7: 0000000000000000 0 SECTION LOCAL DEFAULT 8
8: 0000000000000000 0 SECTION LOCAL DEFAULT 6
9: 0000000000000000 21 FUNC GLOBAL DEFAULT 1 main
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
- 链接后,查看符号表:readelf -s hello或objdump -t hello
[cdl@h3c temp]$ readelf -s hello
Symbol table '.dynsym' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
Symbol table '.symtab' contains 77 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400200 0 SECTION LOCAL DEFAULT 1
2: 000000000040021c 0 SECTION LOCAL DEFAULT 2
3: 000000000040023c 0 SECTION LOCAL DEFAULT 3
4: 0000000000400260 0 SECTION LOCAL DEFAULT 4
5: 0000000000400280 0 SECTION LOCAL DEFAULT 5
6: 00000000004002e0 0 SECTION LOCAL DEFAULT 6
7: 000000000040031e 0 SECTION LOCAL DEFAULT 7
8: 0000000000400328 0 SECTION LOCAL DEFAULT 8
9: 0000000000400348 0 SECTION LOCAL DEFAULT 9
10: 0000000000400360 0 SECTION LOCAL DEFAULT 10
11: 0000000000400390 0 SECTION LOCAL DEFAULT 11
12: 00000000004003a8 0 SECTION LOCAL DEFAULT 12
13: 00000000004003e0 0 SECTION LOCAL DEFAULT 13
14: 00000000004005b8 0 SECTION LOCAL DEFAULT 14
15: 00000000004005c8 0 SECTION LOCAL DEFAULT 15
16: 00000000004005e4 0 SECTION LOCAL DEFAULT 16
17: 0000000000400608 0 SECTION LOCAL DEFAULT 17
18: 0000000000600688 0 SECTION LOCAL DEFAULT 18
19: 0000000000600698 0 SECTION LOCAL DEFAULT 19
20: 00000000006006a8 0 SECTION LOCAL DEFAULT 20
21: 00000000006006b0 0 SECTION LOCAL DEFAULT 21
22: 0000000000600840 0 SECTION LOCAL DEFAULT 22
23: 0000000000600848 0 SECTION LOCAL DEFAULT 23
24: 0000000000600870 0 SECTION LOCAL DEFAULT 24
25: 0000000000600878 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30
31: 0000000000000000 0 SECTION LOCAL DEFAULT 31
32: 0000000000000000 0 SECTION LOCAL DEFAULT 32
33: 0000000000000000 0 SECTION LOCAL DEFAULT 33
34: 0000000000000000 0 SECTION LOCAL DEFAULT 34
35: 0000000000000000 0 SECTION LOCAL DEFAULT 35
36: 0000000000000000 0 FILE LOCAL DEFAULT ABS init.c
37: 0000000000000000 0 FILE LOCAL DEFAULT ABS initfini.c
38: 000000000040040c 0 FUNC LOCAL DEFAULT 13 call_gmon_start
39: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
40: 0000000000600688 0 OBJECT LOCAL DEFAULT 18 __CTOR_LIST__
41: 0000000000600698 0 OBJECT LOCAL DEFAULT 19 __DTOR_LIST__
42: 00000000006006a8 0 OBJECT LOCAL DEFAULT 20 __JCR_LIST__
43: 0000000000400430 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
44: 0000000000600878 1 OBJECT LOCAL DEFAULT 25 completed.6364
45: 0000000000600880 8 OBJECT LOCAL DEFAULT 25 dtor_idx.6366
46: 00000000004004a0 0 FUNC LOCAL DEFAULT 13 frame_dummy
47: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
48: 0000000000600690 0 OBJECT LOCAL DEFAULT 18 __CTOR_END__
49: 0000000000400680 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
50: 00000000006006a8 0 OBJECT LOCAL DEFAULT 20 __JCR_END__
51: 0000000000400580 0 FUNC LOCAL DEFAULT 13 __do_global_ctors_aux
52: 0000000000000000 0 FILE LOCAL DEFAULT ABS initfini.c
53: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c
54: 0000000000000000 0 FILE LOCAL DEFAULT ABS elf-init.c
55: 0000000000600848 0 OBJECT LOCAL DEFAULT 23 _GLOBAL_OFFSET_TABLE_
56: 0000000000600684 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
57: 0000000000600684 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
58: 00000000006006b0 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
59: 0000000000600870 0 NOTYPE WEAK DEFAULT 24 data_start
60: 00000000004004e0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
61: 00000000004003e0 0 FUNC GLOBAL DEFAULT 13 _start
62: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
64: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
65: 00000000004005b8 0 FUNC GLOBAL DEFAULT 14 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
67: 00000000004005c8 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
68: 0000000000600870 0 NOTYPE GLOBAL DEFAULT 24 __data_start
69: 00000000004005d0 0 OBJECT GLOBAL HIDDEN 15 __dso_handle
70: 00000000006006a0 0 OBJECT GLOBAL HIDDEN 19 __DTOR_END__
71: 00000000004004f0 137 FUNC GLOBAL DEFAULT 13 __libc_csu_init
72: 0000000000600874 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
73: 0000000000600888 0 NOTYPE GLOBAL DEFAULT ABS _end
74: 0000000000600874 0 NOTYPE GLOBAL DEFAULT ABS _edata
75: 00000000004004c4 21 FUNC GLOBAL DEFAULT 13 main
76: 0000000000400390 0 FUNC GLOBAL DEFAULT 11 _init
-
对比上述链接前后main函数的符号表,我们可以关注Value和Ndx列。Value在链接前是0,在链接后是4004c4。对于符号main来说,Value就是内存地址。在链接前可执行文件各部分没有分配内存地址,所以Value的值是0。Ndx是符号main对应的节区编号,链接前是1,链接后是13,这是因为链接后加入了外部库的节区。由于main函数本身就在hello.o文件中,所以类型是FUNC,大小21也是已知的。puts(printf)是调用外部的函数,也就是外部符号。
-
重定位:把程序的逻辑地址空间转化成内存中实际的物理地址空间,即在装入时对目标程序中指令和数据的修改过程。它实现了多道程序在内存中同时运行的基础。重定位具体分为两步:
- 重定位节和符号定义
- 重定位节中的符号引用
-
可重定位表中的每一条记录对应一个需要重定位的符号。汇编器将为可重定位文件中每个包含需要重定位符号的段都建立一个重定位表,可重定位表的查看方法:readelf -r hello.o
[cdl@h3c temp]$ readelf -r hello.o
Relocation section '.rela.text' at offset 0x598 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000005 00050000000a R_X86_64_32 0000000000000000 .rodata + 0
00000000000a 000a00000002 R_X86_64_PC32 0000000000000000 puts - 4
Relocation section '.rela.eh_frame' at offset 0x5c8 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0
- 上面显示了hello.o的可重定位表信息,仅关注puts。其描述的是代码段的第0xa字节处有一个地址,需要被替换成符号puts将来的内存地址。通过反汇编hello.o,找到"9: e8 00 00 00 00"机器代码,即代码的第9字节,e8就是call指令,链接后"00 00 00 00"(第10~第13字节)就会被替换成puts链接后的地址。
[cdl@h3c temp]$ objdump -d hello.o
hello.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov $0x0,%edi
9: e8 00 00 00 00 callq e <main+0xe>
e: b8 00 00 00 00 mov $0x0,%eax
13: c9 leaveq
14: c3 retq
6 ELF常用命令
- man elf:查看其详细的格式定义
- readelf:用于显示一个或多个elf格式的目标文件
- -a:等价于-h -l -S -s -r -d -V -A -I
- -h:显示elf文件开始的文件头信息
- -S:显示节头信息
- -l:显示段头信息
- -s:显示符号表信息
- -r:显示可重定位段的信息
- objdump:显示二进制文件信息,用于查看目标文件或者可执行的目标文件构成的gcc工具
- -f:显示目标文件中每个文件的整个头部摘要信息
- -h:显示目标文件各个节的头部摘要信息
- -r:显示文件的重定位入口
- -d:以反汇编的格式显示
网友评论