跳过正文

readelf

·
Elf Debug Tool
目录
elf-debug - 这篇文章属于一个选集。
§ 3: 本文

readelf 是显示 ELF 二进制文件(可执行程序或动态库等)中各 Section 内容的重要工具。

  • 显示符号表 Sections,如 .dnysym 和 .symtab 中的符号名称和地址;
  • 显示 DWARF 格式的 Sections,如各种 .debug_xx,.eh_frame 等;
  • 显示查找 debuginfo 文件所需的 .gnu_debuglink 和 .note.gnu.build-id ;

readelf 和 objdump 相比:

  1. objdump 可以对二进制文件根据调试符号表进行反汇编,但是 readelf 不行;
  2. 两者都会使用 build-id 和 gnu debuglink 机制从 /usr/lib/debug 查找当前二进制的 debuginfo 文件,然后显示其内容;

通用选项:

  1. -W/--wide : 使输出宽度超过 80 字符。

显示 ELF header -h
#

readelf -h/--file-headers: 显示 ELF 头信息:

root@lima-ebpf-dev:~# 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:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1060
  Start of program headers:          64 (bytes into file)   # Program Headers
  Start of section headers:          14720 (bytes into file) # Section Headers
  Flags:                             0x0
  Size of this header:               64 (bytes)    # ELF Header
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         37
  Section header string table index: 36

显示 Program Header 列表 -l(Segments)
#

readelf -l/--program-headers/--segments: 显示 program headers 的内容(也称为 Segments):

Program headers tell the system how to create the process image.

  • PHDR:Points to the program header table itself.
  • INTERP:指定动态链接器路径 /lib64/ld-linux-x86-64.so.2
  • LOAD:描述加载到内存的 segments:
    • Read-only segments (code and constants)
    • Read-execute segments (code)
    • Read-write segments (data)
  • DYNAMIC:包含动态链接信息
  • NOTE
  • GNU_PROPERTY
  • GNU_EH_FRAME
  • GNU_STACK
  • GNU_RELRO

这些 Segments 是由多种 ELF Sections 合并而来(由链接脚本,linker script 控制,ld –verbose 查看默认链接脚本),在 Section to Segment mapping 中显示合并情况:

root@lima-ebpf-dev:~# readelf -l -W hello

Elf file type is DYN (Position-Independent Executable file)
Entry point 0x1060
There are 13 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0002d8 0x0002d8 R   0x8
  INTERP         0x000318 0x0000000000000318 0x0000000000000318 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000628 0x000628 R   0x1000
  LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x000185 0x000185 R E 0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x000114 0x000114 R   0x1000
  LOAD           0x002db8 0x0000000000003db8 0x0000000000003db8 0x000258 0x000260 RW  0x1000
  DYNAMIC        0x002dc8 0x0000000000003dc8 0x0000000000003dc8 0x0001f0 0x0001f0 RW  0x8
  NOTE           0x000338 0x0000000000000338 0x0000000000000338 0x000030 0x000030 R   0x8
  NOTE           0x000368 0x0000000000000368 0x0000000000000368 0x000044 0x000044 R   0x4
  GNU_PROPERTY   0x000338 0x0000000000000338 0x0000000000000338 0x000030 0x000030 R   0x8
  GNU_EH_FRAME   0x00200c 0x000000000000200c 0x000000000000200c 0x00003c 0x00003c R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x002db8 0x0000000000003db8 0x0000000000003db8 0x000248 0x000248 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .plt.got .plt.sec .text .fini
   04     .rodata .eh_frame_hdr .eh_frame
   05     .init_array .fini_array .dynamic .got .data .bss
   06     .dynamic
   07     .note.gnu.property
   08     .note.gnu.build-id .note.ABI-tag
   09     .note.gnu.property
   10     .eh_frame_hdr
   11
   12     .init_array .fini_array .dynamic .got

显示 Section Header 列表 -S
#

readelf -S/--sections/--section-headers :显示所有 Section headers 列表;

  • 使用 -W 来显示超过 80 字符的宽度;
  • 只显示当前文件,而不查找 debuginfo 文件;
root@lima-ebpf-dev:~# readelf -S -W hello
There are 37 section headers, starting at offset 0x3980:

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        0000000000000318 000318 00001c 00   A  0   0  1
  [ 2] .note.gnu.property NOTE            0000000000000338 000338 000030 00   A  0   0  8
  [ 3] .note.gnu.build-id NOTE            0000000000000368 000368 000024 00   A  0   0  4
  [ 4] .note.ABI-tag     NOTE            000000000000038c 00038c 000020 00   A  0   0  4
  [ 5] .gnu.hash         GNU_HASH        00000000000003b0 0003b0 000024 00   A  6   0  8
  [ 6] .dynsym           DYNSYM          00000000000003d8 0003d8 0000a8 18   A  7   1  8
  [ 7] .dynstr           STRTAB          0000000000000480 000480 00008d 00   A  0   0  1
  [ 8] .gnu.version      VERSYM          000000000000050e 00050e 00000e 02   A  6   0  2
  [ 9] .gnu.version_r    VERNEED         0000000000000520 000520 000030 00   A  7   1  8
  [10] .rela.dyn         RELA            0000000000000550 000550 0000c0 18   A  6   0  8
  [11] .rela.plt         RELA            0000000000000610 000610 000018 18  AI  6  24  8
  [12] .init             PROGBITS        0000000000001000 001000 00001b 00  AX  0   0  4
  [13] .plt              PROGBITS        0000000000001020 001020 000020 10  AX  0   0 16
  [14] .plt.got          PROGBITS        0000000000001040 001040 000010 10  AX  0   0 16
  [15] .plt.sec          PROGBITS        0000000000001050 001050 000010 10  AX  0   0 16
  [16] .text             PROGBITS        0000000000001060 001060 000117 00  AX  0   0 16
  [17] .fini             PROGBITS        0000000000001178 001178 00000d 00  AX  0   0  4
  [18] .rodata           PROGBITS        0000000000002000 002000 00000b 00   A  0   0  4
  [19] .eh_frame_hdr     PROGBITS        000000000000200c 00200c 00003c 00   A  0   0  4
  [20] .eh_frame         PROGBITS        0000000000002048 002048 0000cc 00   A  0   0  8
  [21] .init_array       INIT_ARRAY      0000000000003db8 002db8 000008 08  WA  0   0  8
  [22] .fini_array       FINI_ARRAY      0000000000003dc0 002dc0 000008 08  WA  0   0  8
  [23] .dynamic          DYNAMIC         0000000000003dc8 002dc8 0001f0 10  WA  7   0  8
  [24] .got              PROGBITS        0000000000003fb8 002fb8 000048 08  WA  0   0  8
  [25] .data             PROGBITS        0000000000004000 003000 000010 00  WA  0   0  8
  [26] .bss              NOBITS          0000000000004010 003010 000008 00  WA  0   0  1
  [27] .comment          PROGBITS        0000000000000000 003010 00002d 01  MS  0   0  1
  [28] .debug_aranges    PROGBITS        0000000000000000 00303d 000030 00      0   0  1
  [29] .debug_info       PROGBITS        0000000000000000 00306d 0000a6 00      0   0  1
  [30] .debug_abbrev     PROGBITS        0000000000000000 003113 00005e 00      0   0  1
  [31] .debug_line       PROGBITS        0000000000000000 003171 00005b 00      0   0  1
  [32] .debug_str        PROGBITS        0000000000000000 0031cc 0000df 01  MS  0   0  1
  [33] .debug_line_str   PROGBITS        0000000000000000 0032ab 00000d 01  MS  0   0  1
  [34] .symtab           SYMTAB          0000000000000000 0032b8 000378 18     35  18  8
  [35] .strtab           STRTAB          0000000000000000 003630 0001e0 00      0   0  1
  [36] .shstrtab         STRTAB          0000000000000000 003810 00016a 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), l (large), p (processor specific)
root@lima-ebpf-dev:~#

带有 S 标识的表示是字符串 Sections,如 .comment。

显示符号表 -s
#

readelf -s/--syms/--symbols: 显示符号表,包含 .dynsym 和 .symtab Sections 中内容。

.dynsym:只存储动态链接时需要的符号信息, 包含程序运行时需要解析的外部符号, 是动态链接器(dynamic linker)用来解析符号的主要来源,在运行时被动态链接器使用,不能被删除。

  • readelf --dyn-syms: 只显示 .dynsym 动态符号表中的内容;
  • 依赖的共享库符号包含版本信息,如 puts@GLIBC_2.2.5 等;

.symtab: 包含所有符号,包括调试信息,主要用于调试,可以从 ELF 中删除。

只显示当前 ELF 文件中的符号表信息,而不查找 debuginfo 文件;

root@lima-ebpf-dev:~# readelf -s hello

Symbol table '.dynsym' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _[...]@GLIBC_2.34 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (3)
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
     6: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5 (3)

Symbol table '.symtab' contains 37 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS Scrt1.o
     2: 000000000000038c    32 OBJECT  LOCAL  DEFAULT    4 __abi_tag
     3: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
     4: 0000000000001090     0 FUNC    LOCAL  DEFAULT   16 deregister_tm_clones
     5: 00000000000010c0     0 FUNC    LOCAL  DEFAULT   16 register_tm_clones
     6: 0000000000001100     0 FUNC    LOCAL  DEFAULT   16 __do_global_dtors_aux
     7: 0000000000004010     1 OBJECT  LOCAL  DEFAULT   26 completed.0
     8: 0000000000003dc0     0 OBJECT  LOCAL  DEFAULT   22 __do_global_dtor[...]
     9: 0000000000001140     0 FUNC    LOCAL  DEFAULT   16 frame_dummy
    10: 0000000000003db8     0 OBJECT  LOCAL  DEFAULT   21 __frame_dummy_in[...]
    11: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c
    12: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    13: 0000000000002110     0 OBJECT  LOCAL  DEFAULT   20 __FRAME_END__
    14: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS
    15: 0000000000003dc8     0 OBJECT  LOCAL  DEFAULT   23 _DYNAMIC
    16: 000000000000200c     0 NOTYPE  LOCAL  DEFAULT   19 __GNU_EH_FRAME_HDR
    17: 0000000000003fb8     0 OBJECT  LOCAL  DEFAULT   24 _GLOBAL_OFFSET_TABLE_
    18: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_mai[...]
    19: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
    20: 0000000000004000     0 NOTYPE  WEAK   DEFAULT   25 data_start
    21: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5
    22: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   25 _edata
    23: 0000000000001178     0 FUNC    GLOBAL HIDDEN    17 _fini
    24: 0000000000001149    26 FUNC    GLOBAL DEFAULT   16 hello
    25: 0000000000004000     0 NOTYPE  GLOBAL DEFAULT   25 __data_start
    26: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    27: 0000000000004008     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle
    28: 0000000000002000     4 OBJECT  GLOBAL DEFAULT   18 _IO_stdin_used
    29: 0000000000004018     0 NOTYPE  GLOBAL DEFAULT   26 _end
    30: 0000000000001060    38 FUNC    GLOBAL DEFAULT   16 _start
    31: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
    32: 0000000000001163    20 FUNC    GLOBAL DEFAULT   16 main
    33: 0000000000004010     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__
    34: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
    35: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@G[...]
    36: 0000000000001000     0 FUNC    GLOBAL HIDDEN    12 _init
root@lima-ebpf-dev:~#

显示 note sections -n
#

readelf -n: 显示 core notes Section,即以 .note 开头的 section:

  • .note.gnu.property
  • .note.gnu.build-id: 用于查找 debug file 的 build-id;
  • .note.ABI-tag
root@lima-ebpf-dev:~# readelf -n hello

Displaying notes found in: .note.gnu.property
  Owner                Data size        Description
  GNU                  0x00000020       NT_GNU_PROPERTY_TYPE_0
      Properties: x86 feature: IBT, SHSTK
        x86 ISA needed: x86-64-baseline

Displaying notes found in: .note.gnu.build-id
  Owner                Data size        Description
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 7e31292c839740f24092f371f1e85cd9ad74a79b

Displaying notes found in: .note.ABI-tag
  Owner                Data size        Description
  GNU                  0x00000010       NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 3.2.0
root@lima-ebpf-dev:~#

显示重定位 sections -r
#

readefl -r/--relocs:显示重定位 sections,如 .rela.dyn, .rela.plt:

root@lima-ebpf-dev:~# readelf -r hello

Relocation section '.rela.dyn' at offset 0x550 contains 8 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003db8  000000000008 R_X86_64_RELATIVE                    1140
000000003dc0  000000000008 R_X86_64_RELATIVE                    1100
000000004008  000000000008 R_X86_64_RELATIVE                    4008
000000003fd8  000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000003fe0  000200000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0
000000003fe8  000400000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff0  000500000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0
000000003ff8  000600000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0

Relocation section '.rela.plt' at offset 0x610 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003fd0  000300000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
root@lima-ebpf-dev:~#

显示符号版本 -V
#

readelf -V/--version-info 显示如下 gnu version,用于动态库的版本化支持:

  • .gnu.version
  • .gnu.version_r:可执行程序 ELF 依赖的动态库版本;
  • .gnu.version_d:动态库 EFL 文件提供的符号版本列表;

在执行程序时,使用 .gnu.version_r 中的最大版本与动态库的 .gnu.version_d 中的版本比较,如果 version_d 的不支持该版本,则加载阶段的动态链接失败。

# 动态库的 '.gnu.version_d' 包含它支持的版本列表
alizj@ubuntu:~$ readelf -V /usr/lib/aarch64-linux-gnu/libc.so.6
...
Version definition section '.gnu.version_d' contains 22 entries:
 Addr: 0x00000000000208f8  Offset: 0x000208f8  Link: 5 (.dynstr)
  000000: Rev: 1  Flags: BASE  Index: 1  Cnt: 1  Name: libc.so.6
  0x001c: Rev: 1  Flags: none  Index: 2  Cnt: 1  Name: GLIBC_2.17
  0x0038: Rev: 1  Flags: none  Index: 3  Cnt: 2  Name: GLIBC_2.18
  0x0054: Parent 1: GLIBC_2.17
  0x005c: Rev: 1  Flags: none  Index: 4  Cnt: 2  Name: GLIBC_2.22
  0x0078: Parent 1: GLIBC_2.18
  0x0080: Rev: 1  Flags: none  Index: 5  Cnt: 2  Name: GLIBC_2.23
  0x009c: Parent 1: GLIBC_2.22
  0x00a4: Rev: 1  Flags: none  Index: 6  Cnt: 2  Name: GLIBC_2.24
  0x00c0: Parent 1: GLIBC_2.23
  0x00c8: Rev: 1  Flags: none  Index: 7  Cnt: 2  Name: GLIBC_2.25
  0x00e4: Parent 1: GLIBC_2.24
  0x00ec: Rev: 1  Flags: none  Index: 8  Cnt: 2  Name: GLIBC_2.26
...

# 可执行程序的 '.gnu.version_r' 包含它依赖的动态库版本
root@lima-ebpf-dev:~# readelf -V hello

Version symbols section '.gnu.version' contains 72 entries:
 Addr: 0x0000000000000cb8  Offset: 0x00000cb8  Link: 5 (.dynsym)
  000:   0 (*local*)       0 (*local*)       0 (*local*)       2 (GLIBC_2.17)
  004:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    3 (GLIBC_2.34)
  008:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    1 (*global*)      2 (GLIBC_2.17)
  00c:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  010:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  014:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  018:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  01c:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    4 (GLIBC_2.27)    2 (GLIBC_2.17)
  020:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  024:   1 (*global*)      5 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  028:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  02c:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  030:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)
  034:   2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)    2 (GLIBC_2.17)

Version needs section '.gnu.version_r' contains 2 entries:
 Addr: 0x0000000000000d48  Offset: 0x00000d48  Link: 6 (.dynstr)
  000000: Version: 1  File: ld-linux-aarch64.so.1  Cnt: 1
  0x0010:   Name: GLIBC_2.17  Flags: none  Version: 5
  0x0020: Version: 1  File: libc.so.6  Cnt: 4
  0x0030:   Name: GLIBC_2.33  Flags: none  Version: 6
  0x0040:   Name: GLIBC_2.27  Flags: none  Version: 4
  0x0050:   Name: GLIBC_2.34  Flags: none  Version: 3
  0x0060:   Name: GLIBC_2.17  Flags: none  Version: 2

显示指定 Sections 内容 -x,-p
#

  • readelf -x/--hex-dump=<number|name>: 使用 16 进制打印指定 Sections 的内容;
  • readelf -p/--string-dump=<number|name>: 使用文本打印指定 Sections 的内容;
  • readelf -S 来显示所有 sections number 和 name,同时有 S 标志的表示是字符串 Section;
root@lima-ebpf-dev:~# readelf -S hello |grep comm
  [27] .comment          PROGBITS         0000000000000000  00003010

root@lima-ebpf-dev:~# readelf -p .comment hello

String dump of section '.comment':
  [     0]  GCC: (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0

显示 DWARF 内容 -w
#

readelf -w 打印二进制的 DWARF 内容,即各种以 .debug_XX 开头的 Section 内容:

  • .eh_frame: C/C++ 等函数栈帧展开和异常处理;

如果二进制被 strip,则本身不再包含调试符号表,这时 readelf 会根据 .gnu_debuglink Sections 中的 debug 文件名(需要单独添加该 Section),或根据 .note.gnu.build-id 在 /usr/lib/debug 下查找单独的 debug file。

root@lima-ebpf-dev:~# readelf -w hello
Contents of the .eh_frame section:

00000000 0000000000000014 00000000 CIE
  Version:               1
  Augmentation:          "zR"
  Code alignment factor: 1
  Data alignment factor: -8
  Return address column: 16
  Augmentation data:     1b
  DW_CFA_def_cfa: r7 (rsp) ofs 8
  DW_CFA_offset: r16 (rip) at cfa-8
  DW_CFA_nop
  DW_CFA_nop

00000018 0000000000000014 0000001c FDE cie=00000000 pc=0000000000001060..0000000000001086
  DW_CFA_advance_loc: 4 to 0000000000001064
  DW_CFA_undefined: r16 (rip)
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop
  DW_CFA_nop
...
Contents of the .debug_line_str section:

  0x00000000 74657374 2e63002f 726f6f74 00       test.c./root.

root@lima-ebpf-dev:~#

可以使用 -wX--debug-dump=YY 选项来指定打印 DWARF debug sections 的范围和类型:

  • X/=YY,例如 -wa 等效为 –debug-dump abbrev
  • -w –debug-dump[a/=abbrev, A/=addr, r/=aranges, c/=cu_index, L/=decodedline, f/=frames, F/=frames-interp, g/=gdb_index, i/=info, o/=loc, m/=macro, p/=pubnames, t/=pubtypes, R/=Ranges, l/=rawline, s/=str, O/=str-offsets, u/=trace_abbrev, T/=trace_aranges, U/=trace_info]

例子:

root@lima-ebpf-dev:~# readelf --debug-dump=abbrev hello |head -6
Contents of the .debug_abbrev section (loaded from hello):

  Number TAG (0x0)
   1      DW_TAG_base_type    [no children]
    DW_AT_byte_size    DW_FORM_data1
    DW_AT_encoding     DW_FORM_data1
root@lima-ebpf-dev:~# readelf -wa hello |head -6
Contents of the .debug_abbrev section (loaded from hello):

  Number TAG (0x0)
   1      DW_TAG_base_type    [no children]
    DW_AT_byte_size    DW_FORM_data1
    DW_AT_encoding     DW_FORM_data1
root@lima-ebpf-dev:~#

显示所有内容 -a、-e
#

readelf -e/--headers:等效为 -h -l -S ,显示 ELF/Program/Section Headers 的内容。

readelf -a/--all : 等效为 -h -l -S -s -r -d -V -A -I,显示 ELF 文件除 DWARF 外的所有内容。

ELF 操作
#

Relocatable Object File

$ gcc -c -o example.o example.c
$ file example.o
example.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

Shared Library

$ gcc -shared -fPIC -o libexample.so example.c
$ file libexample.so
libexample.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)

Static Executable

$ gcc -static -o example_static example.c
$ file example_static
example_static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux)

保存在指定 section:__attribute__((section(".mysection"))) int special_var = 42;

参考
#

  1. https://github.com/mohitmishra786/underTheHoodOfExecutables
elf-debug - 这篇文章属于一个选集。
§ 3: 本文

相关文章

objdump
·
Elf Debug Tool
objdump 是 ELF 文件查看和反汇编工具。
ELF 符号表和 DWARF 调试符号表
·
Elf Debuginfo Dwarf
介绍 Linux ELF 二进制文件的符号表和调试符号表(.debug_XX)生成、管理机制。
向 ELF 二进制添加元数据信息
·
Elf
介绍向 ELF 文件中添加自定义数据的方法。