调试 #
在执行 C main 函数前,gcc 将自身的 crt*.o 和 glibc 链接到可执行程序中,为 C main 函数执行前后提供初始化和清理机制:
- _start (assembly entry point)
- __libc_start_main (C runtime initialization)
- Various initialization functions
- Finally, your main()
通过 GNU __attribute__
属性宏,可以为指定运行 main 前后的 constructor 和 destructor:
// lifecycle.c
#include <stdio.h>
__attribute__((constructor))
void before_main() {
printf("Constructor: Running before main\n");
}
__attribute__((destructor))
void after_main() {
printf("Destructor: Running after main\n");
}
int main() {
printf("Main: Now executing\n");
return 0;
}
运行这个程序,可以看到执行顺序:
$ ./lifecycle
Constructor: Running before main
Main: Now executing
Destructor: Running after main
C 程序的真正执行入口是 _start 地址,它是 gligc 的汇编代码提供的,在没有正确设置时,gdb 提示:Download failed: Invalid argument. Continuing without source file ./elf/../sysdeps/aarch64/dl-start.S.
alizj@ubuntu:/Users/alizj/docs/lang/c$ gcc -ggdb -O0 -o start ./start-main.c
alizj@ubuntu:/Users/alizj/docs/lang/c$ gdb ./start
(gdb) break _start
Download failed: Invalid argument. Continuing without source file ./elf/../sysdeps/aarch64/dl-start.S.
Breakpoint 2 at 0xaaaaaaaa0680 (2 locations)
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /Users/alizj/docs/lang/c/start
Download failed: Invalid argument. Continuing without source file ./elf/../sysdeps/aarch64/dl-start.S.
Download failed: Invalid argument. Continuing without source file ./elf/../sysdeps/aarch64/dl-start.S.
Breakpoint 2.2, _start () at ../sysdeps/aarch64/dl-start.S:22
warning: 22 ../sysdeps/aarch64/dl-start.S: No such file or directory
(gdb) bt
#0 _start () at ../sysdeps/aarch64/dl-start.S:22
#1 0x0000000000000000 in ?? ()
解决办法:先下载 glibc 源码,并通过 gdb dir 命令添加源码搜索目录。
alizj@ubuntu:/usr/src/glibc$ sudo apt install glibc-source
alizj@ubuntu:/Users/alizj/docs/lang/c$ cd /usr/src/glibc/
alizj@ubuntu:/usr/src/glibc$ ls
debian glibc-2.39.tar.xz
alizj@ubuntu:/Users/alizj/docs/lang/c$ tar -tvf /usr/src/glibc/glibc-2.39.tar.xz |grep dl-start.S
-rw-r--r-- 0/0 1626 2024-01-31 08:34 glibc-2.39/sysdeps/aarch64/dl-start.S
-rw-r--r-- 0/0 2433 2024-01-31 08:34 glibc-2.39/sysdeps/or1k/dl-start.S
-rw-r--r-- 0/0 3618 2024-01-31 08:34 glibc-2.39/sysdeps/powerpc/powerpc32/dl-start.S
alizj@ubuntu:/usr/src/glibc$ sudo tar -xvf glibc-2.39.tar.xz
alizj@ubuntu:/Users/alizj/docs/lang/c$ gcc -ggdb -O0 -o start ./start-main.c
alizj@ubuntu:/Users/alizj/docs/lang/c$ gdb ./start
...
# 从 start ELF 中读取符号表
Reading symbols from ./start...
# 为 main 函数设置断点,main 函数地址为 0x7a0
(gdb) break main
Breakpoint 1 at 0x7a0: file ./start-main.c, line 16.
(gdb) list main
10 struct Point {
11 int x;
12 int y;
13 } point_global = {10, 20};
14
15 int main() {
16 printf("simple_global: %d\n", simple_global);
17 printf("array_global[2]: %d\n", array_global[2]);
18 printf("string_global: %s\n", string_global);
19 printf("point_global: (%d,%d)\n", point_global.x, point_global.y);
(gdb) run
Starting program: /Users/alizj/docs/lang/c/start
...
Breakpoint 1, main () at ./start-main.c:16
16 printf("simple_global: %d\n", simple_global);
# main 函数本地变量
(gdb) info locals
No locals.
# 传给 main 函数的参数
(gdb) info args
No arguments.
# 打印全局变量,它们已经在执行 main 函数前被初始化
(gdb) print simple_global
$1 = 42
(gdb) print array_global
$2 = {1, 2, 3, 4, 5}
(gdb) print string_global
$3 = 0xaaaaaaaa0848 "Hello, World!"
alizj@ubuntu:/Users/alizj/docs/lang/c$ gdb ./start
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
...
Reading symbols from ./start...
# 添加 glibc 源码搜索路径
(gdb) dir /usr/src/glibc/glibc-2.39
Source directories searched: /usr/src/glibc/glibc-2.39:$cdir:$cwd
(gdb) break _start
Breakpoint 1 at 0x680
(gdb) run
Starting program: /Users/alizj/docs/lang/c/start
...
Breakpoint 1.2, _start () at ../sysdeps/aarch64/dl-start.S:22
22 ENTRY (_start)
(gdb) continue
Continuing.
Breakpoint 1.1, 0x0000aaaaaaaa0680 in _start ()
(gdb) list
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20 #include <sysdep.h>
21
22 ENTRY (_start)
23 /* Create an initial frame with 0 LR and FP */
24 cfi_undefined (x30)
25 mov x29, #0
26 mov x30, #0
(gdb) list
27
28 mov x0, sp
29 PTR_ARG (0)
30 bl _dl_start
31 /* Returns user entry point in x0. */
32 mov PTR_REG (21), PTR_REG (0)
33 .globl _dl_start_user
34 .type _dl_start_user, %function
35 _dl_start_user:
36 /* Get argc. */
(gdb) break __libc_start_main
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
breakpoint already hit 2 times
1.1 y 0x0000aaaaaaaa0680 <_start>
1.2 y 0x0000fffff7fd8a40 in _start at ../sysdeps/aarch64/dl-start.S:22
2 breakpoint keep y 0x0000aaaaaaaa07a0 in main at ./start-main.c:16
3 breakpoint keep y 0x0000fffff7e18500 in __libc_start_main_impl at ../csu/libc-start.c:311
(gdb) continue
Continuing.
Breakpoint 3, __libc_start_main_impl (main=0xaaaaaaaa0798 <main>, argc=1, argv=0xfffffffff2c8, init=0x0, fini=0x0,
rtld_fini=0xfffff7fc2740 <_dl_fini>, stack_end=0xfffffffff2c0) at ../csu/libc-start.c:311
311 if (__glibc_likely (rtld_fini != NULL))
(gdb) info functions __do_global_*
All functions matching regular expression "__do_global_*":
Non-debugging symbols:
0x0000aaaaaaaa0740 __do_global_dtors_aux
ELF 文件大小 #
参考:https://github.com/mohitmishra786/underTheHoodOfExecutables/blob/main/src/Ch-1-The-Mystery-Of-Executable-Size/Why-is-my-Hello-World-so-Big.md
测试程序:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
编译后大小:
alizj@ubuntu:~$ gcc -o hello hello.c
alizj@ubuntu:~$ ls -l hello
-rwxr-xr-x 1 alizj alizj 70312 Feb 2 22:03 hello
查看 ELF Header:
alizj@ubuntu:~$ readelf -h hello
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: DYN (Position-Independent Executable file)
Machine: AArch64
Version: 0x1
Entry point address: 0x640
Start of program headers: 64 (bytes into file)
Start of section headers: 68520 (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: 28
Section header string table index: 27
检查 Sections:
alizj@ubuntu:~$ objdump -w -h hello
hello: file format elf64-littleaarch64
Sections:
Idx Name Size VMA LMA File off Algn Flags
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 0000001c 0000000000000298 0000000000000298 00000298 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 000000f0 00000000000002b8 00000000000002b8 000002b8 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 00000092 00000000000003a8 00000000000003a8 000003a8 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version 00000014 000000000000043a 000000000000043a 0000043a 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version_r 00000030 0000000000000450 0000000000000450 00000450 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rela.dyn 000000c0 0000000000000480 0000000000000480 00000480 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.plt 00000078 0000000000000540 0000000000000540 00000540 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .init 00000018 00000000000005b8 00000000000005b8 000005b8 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .plt 00000070 00000000000005d0 00000000000005d0 000005d0 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .text 00000138 0000000000000640 0000000000000640 00000640 2**6 CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .fini 00000014 0000000000000778 0000000000000778 00000778 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 00000016 0000000000000790 0000000000000790 00000790 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame_hdr 0000003c 00000000000007a8 00000000000007a8 000007a8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame 000000b4 00000000000007e8 00000000000007e8 000007e8 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .init_array 00000008 000000000001fd90 000000000001fd90 0000fd90 2**3 CONTENTS, ALLOC, LOAD, DATA
18 .fini_array 00000008 000000000001fd98 000000000001fd98 0000fd98 2**3 CONTENTS, ALLOC, LOAD, DATA
19 .dynamic 000001f0 000000000001fda0 000000000001fda0 0000fda0 2**3 CONTENTS, ALLOC, LOAD, DATA
20 .got 00000070 000000000001ff90 000000000001ff90 0000ff90 2**3 CONTENTS, ALLOC, LOAD, DATA
21 .data 00000010 0000000000020000 0000000000020000 00010000 2**3 CONTENTS, ALLOC, LOAD, DATA
22 .bss 00000008 0000000000020010 0000000000020010 00010010 2**0 ALLOC
23 .comment 0000002b 0000000000000000 0000000000000000 00010010 2**0 CONTENTS, READONLY
反汇编 .text 段中的 main 函数:
alizj@ubuntu:~$ objdump -w -d hello | grep -A10 '<main>:'
0000000000000758 <main>:
758: a9bf7bfd stp x29, x30, [sp, #-16]!
75c: 910003fd mov x29, sp
760: 90000000 adrp x0, 0 <__abi_tag-0x278>
764: 911e6000 add x0, x0, #0x798
768: 97ffffb2 bl 630 <puts@plt>
76c: 52800000 mov w0, #0x0 // #0
770: a8c17bfd ldp x29, x30, [sp], #16
774: d65f03c0 ret
Disassembly of section .fini:
查看 .rodata 段内容:
alizj@ubuntu:~$ objdump -w -s -j .rodata hello
hello: file format elf64-littleaarch64
Contents of section .rodata:
0790 01000200 00000000 48656c6c 6f2c2057 ........Hello, W
07a0 6f726c64 2100 orld!.
查看 .interp 段内容:
alizj@ubuntu:~$ readelf -p .interp hello
String dump of section '.interp':
[ 0] /lib/ld-linux-aarch64.so.1
查看符号表中的内容:
readelf -s/--syms/--symbols
: 显示符号表,包含 .dynsym 和 .symtab Sections 中内容。
.dynsym
:只存储动态链接时需要的符号信息, 包含程序运行时需要解析的外部符号, 是动态链接器(dynamic linker)用来解析符号的主要来源,在运行时被动态链接器使用,不能被删除。
readelf --dyn-syms
: 只显示 .dynsym 动态符号表中的内容,包含依赖的共享库符号包含版本信息,如 puts@GLIBC_2.2.5 等;
.symtab
: 包含所有符号,包括调试信息,主要用于调试,可以从 ELF 中删除。
alizj@ubuntu:~$ readelf -s hello | grep FUNC
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (2)
5: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (3)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort@GLIBC_2.17 (3)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.17 (3)
33: 0000000000000674 20 FUNC LOCAL DEFAULT 13 call_weak_fn
41: 0000000000000690 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
42: 00000000000006c0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
44: 0000000000000700 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
48: 0000000000000750 0 FUNC LOCAL DEFAULT 13 frame_dummy
65: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_mai[...]
69: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@G[...]
72: 0000000000000778 0 FUNC GLOBAL HIDDEN 14 _fini
77: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort@GLIBC_2.17
79: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.17
81: 0000000000000640 52 FUNC GLOBAL DEFAULT 13 _start
84: 0000000000000758 32 FUNC GLOBAL DEFAULT 13 main
87: 00000000000005b8 0 FUNC GLOBAL HIDDEN 11 _init
C Runtime 支持,包括初始化和结束段,如:.init, .init_array, .fini, .fini_array
alizj@ubuntu:~$ readelf -d hello | grep INIT
0x000000000000000c (INIT) 0x5b8
0x0000000000000019 (INIT_ARRAY) 0x1fd90
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
异常处理和栈展开支持:
alizj@ubuntu:~$ readelf -w hello | grep -A10 ".eh_frame"
Contents of the .eh_frame section:
00000000 0000000000000010 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 4
Data alignment factor: -8
Return address column: 30
Augmentation data: 1b
DW_CFA_def_cfa: r31 (sp) ofs 0
ELF 文件大小统计:
alizj@ubuntu:~$ size --format=GNU hello
text data bss total filename
468 1791 8 2267 hello
alizj@ubuntu:~$ size -A hello
hello :
section size addr
.interp 27 568
.note.gnu.build-id 36 596
.note.ABI-tag 32 632
.gnu.hash 28 664
.dynsym 240 696
.dynstr 146 936
.gnu.version 20 1082
.gnu.version_r 48 1104
.rela.dyn 192 1152
.rela.plt 120 1344
.init 24 1464
.plt 112 1488
.text 312 1600
.fini 20 1912
.rodata 22 1936
.eh_frame_hdr 60 1960
.eh_frame 180 2024
.init_array 8 130448
.fini_array 8 130456
.dynamic 496 130464
.got 112 130960
.data 16 131072
.bss 8 131088
.comment 43 0
Total 2310
-
Core Program Components (~2.5KB) Machine code (.text) Read-only data (.rodata) Initialized data (.data) BSS section placeholder (.bss)
-
Dynamic Linking Support (~4KB) Dynamic symbol table String tables Global offset table Procedure linkage table (We’ll explore these in Chapter 9)
-
Runtime Support (~3KB) Exception handling frames Init/fini arrays Debug information
-
Metadata and Headers (~1KB) ELF header Program headers Section headers
-
Alignment Padding (~6KB) Required for performance and loading efficiency
ELF 文件大小优化:
# -Os 文件大小优化,strip 符号表
alizj@ubuntu:~$ gcc -Os -o hello_small hello.c
alizj@ubuntu:~$ ls -l hello_small
-rwxr-xr-x 1 alizj alizj 70288 Feb 2 22:09 hello_small
alizj@ubuntu:~$ strip hello_small
alizj@ubuntu:~$ ls -l hello_small
-rwxr-xr-x 1 alizj alizj 67496 Feb 2 22:09 hello_small
# 静态链接
alizj@ubuntu:~$ gcc -static -o hello_static hello.c
alizj@ubuntu:~$ ls -l hello_static
-rwxr-xr-x 1 alizj alizj 639760 Feb 2 22:09 hello_static
# 删除非必需的段
alizj@ubuntu:~$ gcc -Os -fdata-sections -ffunction-sections -Wl,--gc-sections -o hello_opt hello.c
alizj@ubuntu:~$ ls -l hello_opt
-rwxr-xr-x 1 alizj alizj 70160 Feb 2 22:10 hello_opt
alizj@ubuntu:~$ strip hello_opt
alizj@ubuntu:~$ ls -l hello_opt
-rwxr-xr-x 1 alizj alizj 67488 Feb 2 22:10 hello_opt
ELF 格式解析 #
参考:https://github.com/mohitmishra786/underTheHoodOfExecutables/blob/main/src/Ch-2-The-Executable-And-Linkable-Format/Demystifying-the-Executable-Format.md
Executable and Linkable Format (ELF)
示例程序:
// example.c
#include <stdio.h>
const char message[] = "Hello from ELF!";
int initialized_var = 42;
int uninitialized_var;
void print_message() {
printf("%s\n", message);
}
int main() {
uninitialized_var = initialized_var;
print_message();
return 0;
}
编译:
alizj@ubuntu:~$ gcc -g -o example example
alizj@ubuntu:~$ file example
example: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=36418d0f7c00e132d3b2016a3df7764a43d27bc3, for GNU/Linux 3.7.0, with debug_info, not stripped
ELF 由以下内容组成:
- ELF Header:固定的 64 bytes
- Program Header Table: 可执行程序的 header,由多个 section 合并而成;
- Various Sections
- ELF Header Information:
- The type of architecture it’s designed to run on (e.g., x86-64).
- Entry point: The address within the code segment where execution should begin.
- Section information: The layout and sizes of the various segments within the file.
- Code Segment: .text
- Data Segments: .data/.bss/.rodata
- Symbol Table
- Relocation Information
- Debugging Information
- Section Header Table:ELF sections 列表, 多个 section 被映射到某个 segment 中;
ELF Header 中的 Type 类型:
- EXEC: Executable file
- DYN: Shared object file (including position-independent executables, gcc -shared -fPIC 生成的 so 动态库文件)
- REL: Relocatable file(gcc -c 生成的 obj 文件)
- CORE: Core dump file
Entry point address: 0x1060
The memory address where program execution begins. This typically points to the _start
function, not main
Program Header 用于执行,而 Section Header 用于链接。
+——————-+ | ELF Header | +——————-+ | Program Headers | +——————-+ | | | Sections | | (.text, etc) | | | +——————-+ | Section Headers | +——————-+
查看 Program Headers,它们用于在执行程序是被加载到内存中:
alizj@ubuntu:~$ readelf -l -W example
Elf file type is DYN (Position-Independent Executable file)
Entry point 0x640
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0008f4 0x0008f4 R E 0x10000
LOAD 0x00fd90 0x000000000001fd90 0x000000000001fd90 0x000284 0x000290 RW 0x10000
DYNAMIC 0x00fda0 0x000000000001fda0 0x000000000001fda0 0x0001f0 0x0001f0 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x000044 0x000044 R 0x4
GNU_EH_FRAME 0x0007d8 0x00000000000007d8 0x00000000000007d8 0x000044 0x000044 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fd90 0x000000000001fd90 0x000000000001fd90 0x000270 0x000270 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
Program Header types:
-
PHDR: Points to the program header table itself.
-
INTERP:Specifies the dynamic linker/interpreter:
alizj@ubuntu:~$ readelf -p .interp example String dump of section '.interp': [ 0] /lib/ld-linux-aarch64.so.1
-
LOAD: Describes segments to be loaded into memory:
Read-only segments (code and constants) Read-execute segments (code) Read-write segments (data)
-
DYNAMIC:Contains dynamic linking information:
alizj@ubuntu:~$ readelf -d example Dynamic section at offset 0xfda0 contains 27 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x5b8 0x000000000000000d (FINI) 0x7a8 0x0000000000000019 (INIT_ARRAY) 0x1fd90 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x1fd98 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000006ffffef5 (GNU_HASH) 0x298 0x0000000000000005 (STRTAB) 0x3a8 0x0000000000000006 (SYMTAB) 0x2b8 0x000000000000000a (STRSZ) 146 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000015 (DEBUG) 0x0 0x0000000000000003 (PLTGOT) 0x1ff90 0x0000000000000002 (PLTRELSZ) 120 (bytes) 0x0000000000000014 (PLTREL) RELA 0x0000000000000017 (JMPREL) 0x540 0x0000000000000007 (RELA) 0x480 0x0000000000000008 (RELASZ) 192 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000000000001e (FLAGS) BIND_NOW 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE 0x000000006ffffffe (VERNEED) 0x450 0x000000006fffffff (VERNEEDNUM) 1 0x000000006ffffff0 (VERSYM) 0x43a 0x000000006ffffff9 (RELACOUNT) 4 0x0000000000000000 (NULL) 0x0
Sections: 保存链接器生成的程序的各部分内容:
alizj@ubuntu:~$ readelf -W -S example
There are 34 section headers, starting at offset 0x11050:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 0000000000000238 000238 00001b 00 A 0 0 1
[ 2] .note.gnu.build-id NOTE 0000000000000254 000254 000024 00 A 0 0 4
[ 3] .note.ABI-tag NOTE 0000000000000278 000278 000020 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000000298 000298 00001c 00 A 5 0 8
[ 5] .dynsym DYNSYM 00000000000002b8 0002b8 0000f0 18 A 6 3 8
[ 6] .dynstr STRTAB 00000000000003a8 0003a8 000092 00 A 0 0 1
[ 7] .gnu.version VERSYM 000000000000043a 00043a 000014 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000000450 000450 000030 00 A 6 1 8
[ 9] .rela.dyn RELA 0000000000000480 000480 0000c0 18 A 5 0 8
[10] .rela.plt RELA 0000000000000540 000540 000078 18 AI 5 21 8
[11] .init PROGBITS 00000000000005b8 0005b8 000018 00 AX 0 0 4
[12] .plt PROGBITS 00000000000005d0 0005d0 000070 00 AX 0 0 16
[13] .text PROGBITS 0000000000000640 000640 000168 00 AX 0 0 64
[14] .fini PROGBITS 00000000000007a8 0007a8 000014 00 AX 0 0 4
[15] .rodata PROGBITS 00000000000007c0 0007c0 000018 00 A 0 0 8
[16] .eh_frame_hdr PROGBITS 00000000000007d8 0007d8 000044 00 A 0 0 4
[17] .eh_frame PROGBITS 0000000000000820 000820 0000d4 00 A 0 0 8
[18] .init_array INIT_ARRAY 000000000001fd90 00fd90 000008 08 WA 0 0 8
[19] .fini_array FINI_ARRAY 000000000001fd98 00fd98 000008 08 WA 0 0 8
[20] .dynamic DYNAMIC 000000000001fda0 00fda0 0001f0 10 WA 6 0 8
[21] .got PROGBITS 000000000001ff90 00ff90 000070 08 WA 0 0 8
[22] .data PROGBITS 0000000000020000 010000 000014 00 WA 0 0 8
[23] .bss NOBITS 0000000000020014 010014 00000c 00 WA 0 0 4
[24] .comment PROGBITS 0000000000000000 010014 00002b 01 MS 0 0 1
[25] .debug_aranges PROGBITS 0000000000000000 01003f 000030 00 0 0 1
[26] .debug_info PROGBITS 0000000000000000 01006f 0000ff 00 0 0 1
[27] .debug_abbrev PROGBITS 0000000000000000 01016e 000087 00 0 0 1
[28] .debug_line PROGBITS 0000000000000000 0101f5 00005e 00 0 0 1
[29] .debug_str PROGBITS 0000000000000000 010253 0000e7 01 MS 0 0 1
[30] .debug_line_str PROGBITS 0000000000000000 01033a 000016 01 MS 0 0 1
[31] .symtab SYMTAB 0000000000000000 010350 000960 18 32 73 8
[32] .strtab STRTAB 0000000000000000 010cb0 00024f 00 0 0 1
[33] .shstrtab STRTAB 0000000000000000 010eff 00014a 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), p (processor specific)
重要的 Sections:
- Code Sections
- .text: Executable code, Read + Execute
- .init: Initialization code, constructor
- .fini: Finalization code, destructor
- .plt: Procedure Linkage Table (for dynamic linking)
- Data Sections
- .data: Initialized Global Variables, Read + Write
- .rodata: Read-only data, Constants and String Literals
- .bss: Uninitialized Variables, Read + Write,不占用 ELF 二进制文件空间,但是在装载时分配内存,初始化为 0。
- .got: Global Offset Table
- Symbol and Relocation Sections
- .symtab: Symbol table
- .dynsym: 动态符号表
- .strtab: String table
- .dynstr: 字符串表
- .rela.text: Relocations for .text
- .rela.data: Relocations for .data
- Debugging
- .debug_XX 用于调试。
- .eh_frame 用于异常处理和调试时的函数调用栈展开;
.plt 和 .got 用于支持动态链接。
.text 保存代码
alizj@ubuntu:~$ objdump -d -j .text example
example: file format elf64-littleaarch64
Disassembly of section .text:
0000000000000640 <_start>:
640: d503201f nop
644: d280001d mov x29, #0x0 // #0
648: d280001e mov x30, #0x0 // #0
64c: aa0003e5 mov x5, x0
650: f94003e1 ldr x1, [sp]
654: 910023e2 add x2, sp, #0x8
658: 910003e6 mov x6, sp
65c: f00000e0 adrp x0, 1f000 <__FRAME_END__+0x1e710>
660: f947f800 ldr x0, [x0, #4080]
664: d2800003 mov x3, #0x0 // #0
668: d2800004 mov x4, #0x0 // #0
66c: 97ffffe1 bl 5f0 <__libc_start_main@plt>
670: 97ffffec bl 620 <abort@plt>
0000000000000674 <call_weak_fn>:
674: f00000e0 adrp x0, 1f000 <__FRAME_END__+0x1e710>
678: f947f400 ldr x0, [x0, #4072]
67c: b4000040 cbz x0, 684 <call_weak_fn+0x10>
680: 17ffffe4 b 610 <__gmon_start__@plt>
684: d65f03c0 ret
688: d503201f nop
68c: d503201f nop
0000000000000690 <deregister_tm_clones>:
690: 90000100 adrp x0, 20000 <__data_start>
694: 91006000 add x0, x0, #0x18
698: 90000101 adrp x1, 20000 <__data_start>
69c: 91006021 add x1, x1, #0x18
6a0: eb00003f cmp x1, x0
6a4: 540000c0 b.eq 6bc <deregister_tm_clones+0x2c> // b.none
6a8: f00000e1 adrp x1, 1f000 <__FRAME_END__+0x1e710>
6ac: f947ec21 ldr x1, [x1, #4056]
6b0: b4000061 cbz x1, 6bc <deregister_tm_clones+0x2c>
6b4: aa0103f0 mov x16, x1
6b8: d61f0200 br x16
6bc: d65f03c0 ret
00000000000006c0 <register_tm_clones>:
6c0: 90000100 adrp x0, 20000 <__data_start>
6c4: 91006000 add x0, x0, #0x18
6c8: 90000101 adrp x1, 20000 <__data_start>
6cc: 91006021 add x1, x1, #0x18
6d0: cb000021 sub x1, x1, x0
6d4: d37ffc22 lsr x2, x1, #63
6d8: 8b810c41 add x1, x2, x1, asr #3
6dc: 9341fc21 asr x1, x1, #1
6e0: b40000c1 cbz x1, 6f8 <register_tm_clones+0x38>
6e4: f00000e2 adrp x2, 1f000 <__FRAME_END__+0x1e710>
6e8: f947fc42 ldr x2, [x2, #4088]
6ec: b4000062 cbz x2, 6f8 <register_tm_clones+0x38>
6f0: aa0203f0 mov x16, x2
6f4: d61f0200 br x16
6f8: d65f03c0 ret
6fc: d503201f nop
0000000000000700 <__do_global_dtors_aux>:
700: d503233f paciasp
704: a9be7bfd stp x29, x30, [sp, #-32]!
708: 910003fd mov x29, sp
70c: f9000bf3 str x19, [sp, #16]
710: 90000113 adrp x19, 20000 <__data_start>
714: 39405260 ldrb w0, [x19, #20]
718: 37000140 tbnz w0, #0, 740 <__do_global_dtors_aux+0x40>
71c: f00000e0 adrp x0, 1f000 <__FRAME_END__+0x1e710>
720: f947f000 ldr x0, [x0, #4064]
724: b4000080 cbz x0, 734 <__do_global_dtors_aux+0x34>
728: 90000100 adrp x0, 20000 <__data_start>
72c: f9400400 ldr x0, [x0, #8]
730: 97ffffb4 bl 600 <__cxa_finalize@plt>
734: 97ffffd7 bl 690 <deregister_tm_clones>
738: 52800020 mov w0, #0x1 // #1
73c: 39005260 strb w0, [x19, #20]
740: f9400bf3 ldr x19, [sp, #16]
744: a8c27bfd ldp x29, x30, [sp], #32
748: d50323bf autiasp
74c: d65f03c0 ret
0000000000000750 <frame_dummy>:
750: d503245f bti c
754: 17ffffdb b 6c0 <register_tm_clones>
0000000000000758 <print_message>:
758: a9bf7bfd stp x29, x30, [sp, #-16]!
75c: 910003fd mov x29, sp
760: 90000000 adrp x0, 0 <__abi_tag-0x278>
764: 911f2000 add x0, x0, #0x7c8
768: 97ffffb2 bl 630 <puts@plt>
76c: d503201f nop
770: a8c17bfd ldp x29, x30, [sp], #16
774: d65f03c0 ret
0000000000000778 <main>:
778: a9bf7bfd stp x29, x30, [sp, #-16]!
77c: 910003fd mov x29, sp
780: 90000100 adrp x0, 20000 <__data_start>
784: 91004000 add x0, x0, #0x10
788: b9400001 ldr w1, [x0]
78c: 90000100 adrp x0, 20000 <__data_start>
790: 91006000 add x0, x0, #0x18
794: b9000001 str w1, [x0]
798: 97fffff0 bl 758 <print_message>
79c: 52800000 mov w0, #0x0 // #0
7a0: a8c17bfd ldp x29, x30, [sp], #16
7a4: d65f03c0 ret
.rodata 保存只读数据
alizj@ubuntu:~$ objdump -s -j .rodata example
example: file format elf64-littleaarch64
Contents of section .rodata:
07c0 01000200 00000000 48656c6c 6f206672 ........Hello fr
07d0 6f6d2045 4c462100 om ELF!.
.data 保存已初始化数据
alizj@ubuntu:~$ objdump -s -j .data example
example: file format elf64-littleaarch64
Contents of section .data:
20000 00000000 00000000 08000200 00000000 ................
20010 2a000000 *...
符号表将程序中名称映射为地址:
alizj@ubuntu:~$ readelf -s example
Symbol table '.dynsym' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000000005b8 0 SECTION LOCAL DEFAULT 11 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 22 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (2)
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
5: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (3)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort@GLIBC_2.17 (3)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.17 (3)
9: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
Symbol table '.symtab' contains 100 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000238 0 SECTION LOCAL DEFAULT 1 .interp
2: 0000000000000254 0 SECTION LOCAL DEFAULT 2 .note.gnu.build-id
3: 0000000000000278 0 SECTION LOCAL DEFAULT 3 .note.ABI-tag
4: 0000000000000298 0 SECTION LOCAL DEFAULT 4 .gnu.hash
5: 00000000000002b8 0 SECTION LOCAL DEFAULT 5 .dynsym
6: 00000000000003a8 0 SECTION LOCAL DEFAULT 6 .dynstr
7: 000000000000043a 0 SECTION LOCAL DEFAULT 7 .gnu.version
8: 0000000000000450 0 SECTION LOCAL DEFAULT 8 .gnu.version_r
9: 0000000000000480 0 SECTION LOCAL DEFAULT 9 .rela.dyn
10: 0000000000000540 0 SECTION LOCAL DEFAULT 10 .rela.plt
11: 00000000000005b8 0 SECTION LOCAL DEFAULT 11 .init
12: 00000000000005d0 0 SECTION LOCAL DEFAULT 12 .plt
13: 0000000000000640 0 SECTION LOCAL DEFAULT 13 .text
14: 00000000000007a8 0 SECTION LOCAL DEFAULT 14 .fini
15: 00000000000007c0 0 SECTION LOCAL DEFAULT 15 .rodata
16: 00000000000007d8 0 SECTION LOCAL DEFAULT 16 .eh_frame_hdr
17: 0000000000000820 0 SECTION LOCAL DEFAULT 17 .eh_frame
18: 000000000001fd90 0 SECTION LOCAL DEFAULT 18 .init_array
19: 000000000001fd98 0 SECTION LOCAL DEFAULT 19 .fini_array
20: 000000000001fda0 0 SECTION LOCAL DEFAULT 20 .dynamic
21: 000000000001ff90 0 SECTION LOCAL DEFAULT 21 .got
22: 0000000000020000 0 SECTION LOCAL DEFAULT 22 .data
23: 0000000000020014 0 SECTION LOCAL DEFAULT 23 .bss
24: 0000000000000000 0 SECTION LOCAL DEFAULT 24 .comment
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25 .debug_aranges
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26 .debug_info
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 .debug_abbrev
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28 .debug_line
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29 .debug_str
30: 0000000000000000 0 SECTION LOCAL DEFAULT 30 .debug_line_str
31: 0000000000000000 0 FILE LOCAL DEFAULT ABS Scrt1.o
32: 0000000000000278 0 NOTYPE LOCAL DEFAULT 3 $d
33: 0000000000000278 32 OBJECT LOCAL DEFAULT 3 __abi_tag
34: 0000000000000640 0 NOTYPE LOCAL DEFAULT 13 $x
35: 0000000000000834 0 NOTYPE LOCAL DEFAULT 17 $d
36: 00000000000007c0 0 NOTYPE LOCAL DEFAULT 15 $d
37: 0000000000000000 0 FILE LOCAL DEFAULT ABS crti.o
38: 0000000000000674 0 NOTYPE LOCAL DEFAULT 13 $x
39: 0000000000000674 20 FUNC LOCAL DEFAULT 13 call_weak_fn
40: 00000000000005b8 0 NOTYPE LOCAL DEFAULT 11 $x
41: 00000000000007a8 0 NOTYPE LOCAL DEFAULT 14 $x
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtn.o
43: 00000000000005c8 0 NOTYPE LOCAL DEFAULT 11 $x
44: 00000000000007b4 0 NOTYPE LOCAL DEFAULT 14 $x
45: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
46: 0000000000000690 0 NOTYPE LOCAL DEFAULT 13 $x
47: 0000000000000690 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
48: 00000000000006c0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
49: 0000000000020008 0 NOTYPE LOCAL DEFAULT 22 $d
50: 0000000000000700 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
51: 0000000000020014 1 OBJECT LOCAL DEFAULT 23 completed.0
52: 000000000001fd98 0 NOTYPE LOCAL DEFAULT 19 $d
53: 000000000001fd98 0 OBJECT LOCAL DEFAULT 19 __do_global_dtor[...]
54: 0000000000000750 0 FUNC LOCAL DEFAULT 13 frame_dummy
55: 000000000001fd90 0 NOTYPE LOCAL DEFAULT 18 $d
56: 000000000001fd90 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_in[...]
57: 0000000000000848 0 NOTYPE LOCAL DEFAULT 17 $d
58: 0000000000020014 0 NOTYPE LOCAL DEFAULT 23 $d
59: 0000000000000000 0 FILE LOCAL DEFAULT ABS example.c
60: 00000000000007c8 0 NOTYPE LOCAL DEFAULT 15 $d
61: 0000000000020010 0 NOTYPE LOCAL DEFAULT 22 $d
62: 0000000000020018 0 NOTYPE LOCAL DEFAULT 23 $d
63: 0000000000000758 0 NOTYPE LOCAL DEFAULT 13 $x
64: 00000000000008b0 0 NOTYPE LOCAL DEFAULT 17 $d
65: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
66: 00000000000008f0 0 NOTYPE LOCAL DEFAULT 17 $d
67: 00000000000008f0 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
68: 0000000000000000 0 FILE LOCAL DEFAULT ABS
69: 000000000001fda0 0 OBJECT LOCAL DEFAULT ABS _DYNAMIC
70: 00000000000007d8 0 NOTYPE LOCAL DEFAULT 16 __GNU_EH_FRAME_HDR
71: 000000000001ffd0 0 OBJECT LOCAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
72: 00000000000005d0 0 NOTYPE LOCAL DEFAULT 12 $x
73: 00000000000007c8 16 OBJECT GLOBAL DEFAULT 15 message
74: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_mai[...]
75: 0000000000020018 4 OBJECT GLOBAL DEFAULT 23 uninitialized_var
76: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
77: 0000000000020000 0 NOTYPE WEAK DEFAULT 22 data_start
78: 0000000000020014 0 NOTYPE GLOBAL DEFAULT 23 __bss_start__
79: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@G[...]
80: 0000000000020020 0 NOTYPE GLOBAL DEFAULT 23 _bss_end__
81: 0000000000020014 0 NOTYPE GLOBAL DEFAULT 22 _edata
82: 00000000000007a8 0 FUNC GLOBAL HIDDEN 14 _fini
83: 0000000000020020 0 NOTYPE GLOBAL DEFAULT 23 __bss_end__
84: 0000000000000758 32 FUNC GLOBAL DEFAULT 13 print_message
85: 0000000000020000 0 NOTYPE GLOBAL DEFAULT 22 __data_start
86: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
87: 0000000000020008 0 OBJECT GLOBAL HIDDEN 22 __dso_handle
88: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort@GLIBC_2.17
89: 00000000000007c0 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
90: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.17
91: 0000000000020020 0 NOTYPE GLOBAL DEFAULT 23 _end
92: 0000000000000640 52 FUNC GLOBAL DEFAULT 13 _start
93: 0000000000020020 0 NOTYPE GLOBAL DEFAULT 23 __end__
94: 0000000000020014 0 NOTYPE GLOBAL DEFAULT 23 __bss_start
95: 0000000000000778 48 FUNC GLOBAL DEFAULT 13 main
96: 0000000000020018 0 OBJECT GLOBAL HIDDEN 22 __TMC_END__
97: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMC[...]
98: 0000000000020010 4 OBJECT GLOBAL DEFAULT 22 initialized_var
99: 00000000000005b8 0 FUNC GLOBAL HIDDEN 11 _init
创建不同类型 ELF 文件:
# 1. Relocatable Object File
alizj@ubuntu:~$ gcc -c -o example.o example.c
alizj@ubuntu:~$ file example.o
example.o: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), not stripped
# 2. Shared Library
alizj@ubuntu:~$ gcc -shared -fPIC -o libexample.so example.c
alizj@ubuntu:~$ file libexample.so
libexample.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=07353ae994fa16f85b38d58cc175aaf45277cf2e, not stripped
# 3. 可执行程序(静态)
alizj@ubuntu:~$ gcc -static -o example_static example.c
alizj@ubuntu:~$ file example_static
example_static: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=413dd17f0e0686db49f09cba0ffa9d1d4dd48f82, for GNU/Linux 3.7.0, not stripped
ELF 类型:
-
Relocatable Files (.o)
Contain code and data suitable for linking Have relocations that specify how to modify section contents Include symbol table for external references
-
Executable Files
Contain directly executable code and data Have program headers describing how to create process image Specify interpreter for dynamic linking
-
Shared Objects (.so)
Can be linked at runtime Position-independent code Can be shared by multiple processes
ELF 文件操作:
Adding Sections
$ objcopy –add-section .mydata=myfile.txt example example_modified
Extracting Sections
$ objcopy -O binary –only-section=.text example text.bin
strip: 删除 ELF 中符号表和调试符号表
strip --strip-debug example
gdb 调试:
alizj@ubuntu:~$ gdb example
...
Reading symbols from example...
(gdb) info files
Symbols from "/home/alizj/example".
Local exec file:
`/home/alizj/example', file type elf64-littleaarch64.
Entry point: 0x640
0x0000000000000238 - 0x0000000000000253 is .interp
0x0000000000000254 - 0x0000000000000278 is .note.gnu.build-id
0x0000000000000278 - 0x0000000000000298 is .note.ABI-tag
0x0000000000000298 - 0x00000000000002b4 is .gnu.hash
0x00000000000002b8 - 0x00000000000003a8 is .dynsym
0x00000000000003a8 - 0x000000000000043a is .dynstr
0x000000000000043a - 0x000000000000044e is .gnu.version
--Type <RET> for more, q to quit, c to continue without paging--
0x0000000000000450 - 0x0000000000000480 is .gnu.version_r
0x0000000000000480 - 0x0000000000000540 is .rela.dyn
0x0000000000000540 - 0x00000000000005b8 is .rela.plt
0x00000000000005b8 - 0x00000000000005d0 is .init
0x00000000000005d0 - 0x0000000000000640 is .plt
0x0000000000000640 - 0x00000000000007a8 is .text
0x00000000000007a8 - 0x00000000000007bc is .fini
0x00000000000007c0 - 0x00000000000007d8 is .rodata
0x00000000000007d8 - 0x000000000000081c is .eh_frame_hdr
0x0000000000000820 - 0x00000000000008f4 is .eh_frame
0x000000000001fd90 - 0x000000000001fd98 is .init_array
0x000000000001fd98 - 0x000000000001fda0 is .fini_array
0x000000000001fda0 - 0x000000000001ff90 is .dynamic
0x000000000001ff90 - 0x0000000000020000 is .got
0x0000000000020000 - 0x0000000000020014 is .data
0x0000000000020014 - 0x0000000000020020 is .bss
nm:ELF 打印符号表中符号名称和地址:
alizj@ubuntu:~$ nm example
0000000000000278 r __abi_tag
U abort@GLIBC_2.17
0000000000020020 B __bss_end__
0000000000020020 B _bss_end__
0000000000020014 B __bss_start
0000000000020014 B __bss_start__
0000000000000674 t call_weak_fn
0000000000020014 b completed.0
w __cxa_finalize@GLIBC_2.17
0000000000020000 D __data_start
0000000000020000 W data_start
0000000000000690 t deregister_tm_clones
0000000000000700 t __do_global_dtors_aux
000000000001fd98 d __do_global_dtors_aux_fini_array_entry
0000000000020008 D __dso_handle
000000000001fda0 a _DYNAMIC
0000000000020014 D _edata
0000000000020020 B __end__
0000000000020020 B _end
00000000000007a8 T _fini
0000000000000750 t frame_dummy
000000000001fd90 d __frame_dummy_init_array_entry
00000000000008f0 r __FRAME_END__
000000000001ffd0 a _GLOBAL_OFFSET_TABLE_
w __gmon_start__
00000000000007d8 r __GNU_EH_FRAME_HDR
00000000000005b8 T _init
0000000000020010 D initialized_var
00000000000007c0 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __libc_start_main@GLIBC_2.34
0000000000000778 T main
00000000000007c8 R message
0000000000000758 T print_message
U puts@GLIBC_2.17
00000000000006c0 t register_tm_clones
0000000000000640 T _start
0000000000020018 D __TMC_END__
0000000000020018 B uninitialized_var
strings: 打印 ELF 中字符串:
alizj@ubuntu:~$ strings example
/lib/ld-linux-aarch64.so.1
puts
__libc_start_main
__cxa_finalize
abort
libc.so.6
GLIBC_2.17
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
`R@9@
Hello from ELF!
GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
long unsigned int
short unsigned int
short int
uninitialized_var
unsigned char
long int
GNU C17 13.3.0 -mlittle-endian -mabi=lp64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection
main
print_message
/home/alizj
example.c
Scrt1.o
__abi_tag
crti.o
call_weak_fn
crtn.o
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.0
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
example.c
__FRAME_END__
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_start_main@GLIBC_2.34
uninitialized_var
_ITM_deregisterTMCloneTable
__bss_start__
__cxa_finalize@GLIBC_2.17
_edata
_fini
__bss_end__
print_message
__data_start
__gmon_start__
__dso_handle
abort@GLIBC_2.17
_IO_stdin_used
puts@GLIBC_2.17
_end
__end__
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
_init
.symtab
.strtab
.shstrtab
.interp
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.data
.bss
.comment
.debug_aranges
.debug_info
.debug_abbrev
.debug_line
.debug_str
.debug_line_str
理解 ELF Sections #
参考:https://github.com/mohitmishra786/underTheHoodOfExecutables/blob/main/src/Ch-3-Sections-Organizing-Code-And-Data/Understanding-ELF-Sections.md