前言
这里我们来探讨一下 elf 文件的执行流程
当然 这也是我很久以前 就想了解的东西了
不过 苦于 缺少各种调试环境, 呵呵 所以 一直搁置于此
调试环境 至关重要
这里主要是走一下 elf 的执行流程, fork, exec, libc_start_main, main
测试用例
root@ubuntu:~/ClionWorkStations/HelloWorld# cat Test01Sum.c
#include "stdio.h"
int main(int argc, char** argv) {
int x = 2;
int y = 3;
int z = x + y;
printf(" x + y = %d\n ", z);
}
readelf 查看 elf 的文件信息
root@ubuntu:~/ClionWorkStations/HelloWorld# readelf -a Test01Sum
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400480
Start of program headers: 64 (bytes into file)
Start of section headers: 8496 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 38
Section header string table index: 35
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 0000000000400238 00000238
0000000000000040 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400278 00000278
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400298 00000298
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 00000000004002c0 000002c0
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002e0 000002e0
0000000000000060 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400340 00000340
000000000000006a 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 00000000004003aa 000003aa
0000000000000008 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 00000000004003b8 000003b8
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 00000000004003d8 000003d8
0000000000000018 0000000000000018 A 5 0 8
[10] .rela.plt RELA 00000000004003f0 000003f0
0000000000000030 0000000000000018 AI 5 24 8
[11] .init PROGBITS 0000000000400420 00000420
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000400440 00000440
0000000000000030 0000000000000010 AX 0 0 16
[13] .plt.got PROGBITS 0000000000400470 00000470
0000000000000008 0000000000000000 AX 0 0 8
[14] .text PROGBITS 0000000000400480 00000480
00000000000001b2 0000000000000000 AX 0 0 16
[15] .fini PROGBITS 0000000000400634 00000634
0000000000000009 0000000000000000 AX 0 0 4
[16] .rodata PROGBITS 0000000000400640 00000640
0000000000000012 0000000000000000 A 0 0 4
[17] .eh_frame_hdr PROGBITS 0000000000400654 00000654
0000000000000034 0000000000000000 A 0 0 4
[18] .eh_frame PROGBITS 0000000000400688 00000688
00000000000000f4 0000000000000000 A 0 0 8
[19] .init_array INIT_ARRAY 0000000000600e00 00000e00
0000000000000008 0000000000000000 WA 0 0 8
[20] .fini_array FINI_ARRAY 0000000000600e08 00000e08
0000000000000008 0000000000000000 WA 0 0 8
[21] .jcr PROGBITS 0000000000600e10 00000e10
0000000000000008 0000000000000000 WA 0 0 8
[22] .dynamic DYNAMIC 0000000000600e18 00000e18
00000000000001e0 0000000000000010 WA 6 0 8
[23] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[24] .got.plt PROGBITS 0000000000601000 00001000
0000000000000028 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000601028 00001028
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000601038 00001038
0000000000000008 0000000000000000 WA 0 0 1
[27] .comment PROGBITS 0000000000000000 00001038
0000000000000035 0000000000000001 MS 0 0 1
[28] .debug_aranges PROGBITS 0000000000000000 0000106d
0000000000000030 0000000000000000 0 0 1
[29] .debug_info PROGBITS 0000000000000000 0000109d
000000000000016a 0000000000000000 0 0 1
[30] .debug_abbrev PROGBITS 0000000000000000 00001207
000000000000010d 0000000000000000 0 0 1
[31] .debug_line PROGBITS 0000000000000000 00001314
0000000000000097 0000000000000000 0 0 1
[32] .debug_str PROGBITS 0000000000000000 000013ab
000000000000016d 0000000000000001 MS 0 0 1
[33] .debug_loc PROGBITS 0000000000000000 00001518
000000000000011b 0000000000000000 0 0 1
[34] .debug_ranges PROGBITS 0000000000000000 00001633
0000000000000060 0000000000000000 0 0 1
[35] .shstrtab STRTAB 0000000000000000 00001fc5
0000000000000165 0000000000000000 0 0 1
[36] .symtab SYMTAB 0000000000000000 00001698
0000000000000708 0000000000000018 37 55 8
[37] .strtab STRTAB 0000000000000000 00001da0
0000000000000225 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)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x0000000000000040 0x0000000000000040 R 1
[Requesting program interpreter: /root/Desktop/linux/glibc-2.23/install/lib/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000077c 0x000000000000077c R E 200000
LOAD 0x0000000000000e00 0x0000000000600e00 0x0000000000600e00
0x0000000000000238 0x0000000000000240 RW 200000
DYNAMIC 0x0000000000000e18 0x0000000000600e18 0x0000000000600e18
0x00000000000001e0 0x00000000000001e0 RW 8
NOTE 0x0000000000000278 0x0000000000400278 0x0000000000400278
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x0000000000000654 0x0000000000400654 0x0000000000400654
0x0000000000000034 0x0000000000000034 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000000e00 0x0000000000600e00 0x0000000000600e00
0x0000000000000200 0x0000000000000200 R 1
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 .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
Dynamic section at offset 0xe18 contains 25 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/root/Desktop/linux/glibc-2.23/install/lib]
0x000000000000000c (INIT) 0x400420
0x000000000000000d (FINI) 0x400634
0x0000000000000019 (INIT_ARRAY) 0x600e00
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x600e08
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x4002c0
0x0000000000000005 (STRTAB) 0x400340
0x0000000000000006 (SYMTAB) 0x4002e0
0x000000000000000a (STRSZ) 106 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x601000
0x0000000000000002 (PLTRELSZ) 48 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x4003f0
0x0000000000000007 (RELA) 0x4003d8
0x0000000000000008 (RELASZ) 24 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x4003b8
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x4003aa
0x0000000000000000 (NULL) 0x0
Relocation section '.rela.dyn' at offset 0x3d8 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600ff8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
Relocation section '.rela.plt' at offset 0x3f0 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000601018 000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
000000601020 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.dynsym' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Symbol table '.symtab' contains 75 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400238 0 SECTION LOCAL DEFAULT 1
2: 0000000000400278 0 SECTION LOCAL DEFAULT 2
3: 0000000000400298 0 SECTION LOCAL DEFAULT 3
4: 00000000004002c0 0 SECTION LOCAL DEFAULT 4
5: 00000000004002e0 0 SECTION LOCAL DEFAULT 5
6: 0000000000400340 0 SECTION LOCAL DEFAULT 6
7: 00000000004003aa 0 SECTION LOCAL DEFAULT 7
8: 00000000004003b8 0 SECTION LOCAL DEFAULT 8
9: 00000000004003d8 0 SECTION LOCAL DEFAULT 9
10: 00000000004003f0 0 SECTION LOCAL DEFAULT 10
11: 0000000000400420 0 SECTION LOCAL DEFAULT 11
12: 0000000000400440 0 SECTION LOCAL DEFAULT 12
13: 0000000000400470 0 SECTION LOCAL DEFAULT 13
14: 0000000000400480 0 SECTION LOCAL DEFAULT 14
15: 0000000000400634 0 SECTION LOCAL DEFAULT 15
16: 0000000000400640 0 SECTION LOCAL DEFAULT 16
17: 0000000000400654 0 SECTION LOCAL DEFAULT 17
18: 0000000000400688 0 SECTION LOCAL DEFAULT 18
19: 0000000000600e00 0 SECTION LOCAL DEFAULT 19
20: 0000000000600e08 0 SECTION LOCAL DEFAULT 20
21: 0000000000600e10 0 SECTION LOCAL DEFAULT 21
22: 0000000000600e18 0 SECTION LOCAL DEFAULT 22
23: 0000000000600ff8 0 SECTION LOCAL DEFAULT 23
24: 0000000000601000 0 SECTION LOCAL DEFAULT 24
25: 0000000000601028 0 SECTION LOCAL DEFAULT 25
26: 0000000000601038 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 FILE LOCAL DEFAULT ABS crtstuff.c
36: 0000000000600e10 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__
37: 00000000004004b0 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones
38: 00000000004004f0 0 FUNC LOCAL DEFAULT 14 register_tm_clones
39: 0000000000400530 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux
40: 0000000000601038 1 OBJECT LOCAL DEFAULT 26 completed.7594
41: 0000000000600e08 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fin
42: 0000000000400550 0 FUNC LOCAL DEFAULT 14 frame_dummy
43: 0000000000600e00 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_
44: 0000000000000000 0 FILE LOCAL DEFAULT ABS elf-init.c
45: 0000000000000000 0 FILE LOCAL DEFAULT ABS Test01Sum.c
46: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
47: 0000000000400778 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__
48: 0000000000600e10 0 OBJECT LOCAL DEFAULT 21 __JCR_END__
49: 0000000000000000 0 FILE LOCAL DEFAULT ABS
50: 0000000000600e08 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
51: 0000000000600e18 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC
52: 0000000000600e00 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
53: 0000000000400654 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR
54: 0000000000601000 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_
55: 0000000000400630 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
56: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
57: 0000000000601028 0 NOTYPE WEAK DEFAULT 25 data_start
58: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 _edata
59: 0000000000400634 0 FUNC GLOBAL DEFAULT 15 _fini
60: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.2.5
61: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
62: 0000000000601028 0 NOTYPE GLOBAL DEFAULT 25 __data_start
63: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
64: 0000000000601030 0 OBJECT GLOBAL HIDDEN 25 __dso_handle
65: 0000000000400640 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used
66: 00000000004005c0 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init
67: 0000000000601040 0 NOTYPE GLOBAL DEFAULT 26 _end
68: 0000000000400480 42 FUNC GLOBAL DEFAULT 14 _start
69: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 26 __bss_start
70: 0000000000400576 67 FUNC GLOBAL DEFAULT 14 main
71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
72: 0000000000601038 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__
73: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
74: 0000000000400420 0 FUNC GLOBAL DEFAULT 11 _init
Version symbols section '.gnu.version' contains 4 entries:
Addr: 00000000004003aa Offset: 0x0003aa Link: 5 (.dynsym)
000: 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*)
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x00000000004003b8 Offset: 0x0003b8 Link: 6 (.dynstr)
000000: Version: 1 File: libc.so.6 Cnt: 1
0x0010: Name: GLIBC_2.2.5 Flags: none Version: 2
Displaying notes found at file offset 0x00000278 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 2.6.32
Displaying notes found at file offset 0x00000298 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 40a7a5576d0c3e9280e8fd00051f817befc922c6
linux 层面的 elf 的执行
在这一个层面主要是包含两个部分, fork + exec
1. fork 当前进程
2. 然后更新 子进程的执行文件为待执行 elf
3. 然后 之后执行 elf 的相关业务
执行 "./Test01Sum"
首先是 fork, 可以看到执行 Test01Sum 的进程是 275
然后是 exec 更新子进程待执行的 elf
这里可以看到待执行文件为 "./Test01Sum"
然后 核心业务处理是在 binfmt_elf. load_elf_binary
主要包含了读取 elfHeader, programHeaders, 加载 interpreter, 加载 interpreter 的 elfHeader, programHeaders, mmap LOAD 的 segment, 更新 bss, data, code 的相关偏移, 初始化执行程序的栈帧, 更新子进程的入口, 子进程开始处理业务
这里的 elf_entry, 如果是静态链接, 则为 elf 的 entry_point, 否则为 interpreter 的 entry_point
glibc 的 libc_start_main
我们看一下 elf 的 entry_point 的代码
主要是构造了 libc_start_main 的参数, 传入了诸如 main, init, fini, argc, argv 等等相关参数
main, 就是用户代码的 main 编译好了之后生成的代码
在 libc_start_main 中调用了 main
main 的代码地址为 0x400576, 对应于 elf 中的 main
然后 这时候我们的 main 才开始跑起来
main 的执行
然后就是 用户代码中的 main 的代码的执行了
上面的这部分代码段时属于 LOAD 的 segment 的一部分, 被完全 mmap 进来, 因此是一样的
当然 以上仅仅是一个 大体的脉络
实际上有很多有意思的细节, 在其中
完
Copyright © 2022 日本世界杯_林高远世界杯 - edenyn.com All Rights Reserved.