跳过正文

目录

调试
#

在执行 C main 函数前,gcc 将自身的 crt*.o 和 glibc 链接到可执行程序中,为 C main 函数执行前后提供初始化和清理机制:

  1. _start (assembly entry point)
  2. __libc_start_main (C runtime initialization)
  3. Various initialization functions
  4. 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
  1. Core Program Components (~2.5KB) Machine code (.text) Read-only data (.rodata) Initialized data (.data) BSS section placeholder (.bss)

  2. Dynamic Linking Support (~4KB) Dynamic symbol table String tables Global offset table Procedure linkage table (We’ll explore these in Chapter 9)

  3. Runtime Support (~3KB) Exception handling frames Init/fini arrays Debug information

  4. Metadata and Headers (~1KB) ELF header Program headers Section headers

  5. 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 由以下内容组成:

  1. ELF Header:固定的 64 bytes
  2. Program Header Table: 可执行程序的 header,由多个 section 合并而成;
  3. 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
  1. Section Header Table:ELF sections 列表, 多个 section 被映射到某个 segment 中;

ELF Header 中的 Type 类型:

  1. EXEC: Executable file
  2. DYN: Shared object file (including position-independent executables, gcc -shared -fPIC 生成的 so 动态库文件)
  3. REL: Relocatable file(gcc -c 生成的 obj 文件)
  4. 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:

  1. PHDR: Points to the program header table itself.

  2. INTERP:Specifies the dynamic linker/interpreter:

    alizj@ubuntu:~$ readelf -p .interp example
    
    String dump of section '.interp':
      [     0]  /lib/ld-linux-aarch64.so.1
    
  3. LOAD: Describes segments to be loaded into memory:

    Read-only segments (code and constants) Read-execute segments (code) Read-write segments (data)

  4. 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:

  1. Code Sections
  • .text: Executable code, Read + Execute
  • .init: Initialization code, constructor
  • .fini: Finalization code, destructor
  • .plt: Procedure Linkage Table (for dynamic linking)
  1. 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
  1. Symbol and Relocation Sections
  • .symtab: Symbol table
  • .dynsym: 动态符号表
  • .strtab: String table
  • .dynstr: 字符串表
  • .rela.text: Relocations for .text
  • .rela.data: Relocations for .data
  1. 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 类型:

  1. 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

  2. Executable Files

    Contain directly executable code and data Have program headers describing how to create process image Specify interpreter for dynamic linking

  3. 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

相关文章

gdb
Gnu Tool Gdb
gdb 个人速查手册。
GCC 编译器 - 个人参考手册
Gnu Gcc Manual
gcc 编译器个人参考手册。