剥离 ELF 二进制文件,但保留 gdb 回溯的符号/源文件位置信息

问题描述 投票:0回答:1

我想剥离使用调试信息编译的 ELF 二进制文件,并仅保留在 GDB 回溯中提供符号/源代码位置输出所需的最少信息。

这将是二进制后处理,从

-g
“降级”到
-g1

考虑这个示例 C++ 源文件 hello.cpp:

#include <iostream>
#include <cstring>

static void *invalid_mem = (void *)1;

static void crash() {
  memset((char *)invalid_mem, 1, 100);
}

int main() {
  std::cout << "Hello World!" << std::endl;
  crash();
  return 0;
}

我用调试信息编译它,运行生成的

hello
二进制文件以获取核心文件并使用 GDB 打印回溯:

$ g++ -g hello.cpp -o hello
$ ./hello
Hello World!
Segmentation fault (core dumped)
$ gdb --quiet -ex bt -ex quit hello core
Reading symbols from hello...
[New LWP 479]
Core was generated by `./hello'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f16330982e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#0  0x00007f16330982e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#1  0x00000000004011a3 in crash () at hello.cpp:7
#2  0x00000000004011cb in main () at hello.cpp:12

如果我从

hello
二进制文件中删除调试信息,我会丢失 GDB 中的源文件位置输出,但不会丢失符号,因为
.symtab
部分未删除:

$ cp hello hello.full
$ objcopy --strip-debug hello.full hello
$ gdb --quiet -ex bt -ex quit hello core
Reading symbols from hello...
(No debugging symbols found in hello)
[New LWP 512]
Core was generated by `./hello'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fc20289f2e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#0  0x00007fc20289f2e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#1  0x00000000004011a3 in crash() ()
#2  0x00000000004011cb in main ()

根据 DWARF 4 标准规范(DWARF4 (pdf)),

.debug_line
部分似乎是我需要保留的部分,但似乎还不够:

$ objcopy --strip-debug --keep-section .debug_line hello.full hello
$ diff --color -Naur <(readelf -S hello.full | grep -oP '\.\K.[^ ]+') <(readelf -S hello | grep -oP '\.\K.[^ ]+')
--- /dev/fd/63  2024-04-29 12:23:49.023699848 +0200
+++ /dev/fd/62  2024-04-29 12:23:49.027699860 +0200
@@ -24,11 +24,7 @@
 bss
 comment
 gnu.build.a[...]
-debug_aranges
-debug_info
-debug_abbrev
 debug_line
-debug_str
 symtab
 strtab
 shstrtab
$ gdb --quiet -ex bt -ex quit hello core
Reading symbols from hello...
(No debugging symbols found in hello)
[New LWP 572]
Core was generated by `./hello'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f182a0462e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#0  0x00007f182a0462e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#1  0x00000000004011a3 in crash() ()
#2  0x00000000004011cb in main ()

我尝试添加/删除单独的

.debug_*
部分,但它们似乎与
.debug_info
相关联,如果删除此部分,则任何操作都不会起作用。

如果这可以与 GDB 的 MiniDebugInfo 一起使用,能够完全剥离 ELF 二进制文件,并且仍然在 GDB 回溯中获取符号和源文件位置输出,那就更好了:

# Adding .gnu_debugdata section in binary for minidebuginfo  (see link)
$ gdb --quiet -ex bt -ex quit hello core
Reading symbols from hello...
Reading symbols from .gnu_debugdata for hello...
(No debugging symbols found in .gnu_debugdata for hello)
[New LWP 599]
Core was generated by `./hello'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f1de1f2d2e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#0  0x00007f1de1f2d2e0 in __memset_avx2_unaligned_erms () from /lib64/libc.so.6
#1  0x00000000004011a3 in crash() ()
#2  0x00000000004011cb in main ()

我知道我可以使用

-g1
而不是
-g
,但我需要完整的调试信息 (
-g
),这些信息将被剥离并远程存储,同时在二进制文件中保留最少的本地调试信息 (
-g1
)。

有谁知道这是否可以实现?

c++ c linux debugging gdb
1个回答
0
投票

根据 obj-copy 的手册页,照常编译和链接后,您应该 - 假设您的输出(可执行)文件名为 hello

— :

objcopy --only-keep-debug hello hello.dbg
这将创建一个文件

hello.dbg

,其中包含将被
--strip-debug
删除的所有内容。
然后

objcopy --strip-debug hello
这将删除调试信息。
最后:

objcopy --add-gnu-debuglink=hello.dbg hello
正如它所建议的,这将添加一个指向我们在第一步中创建的调试信息文件

hello.dbg

的链接。
或者,(然后将
hello.cpp
 编译为 
hello
 精灵):

cp hello hello.full
创建 

hello

 的副本,名为 
hello.full

objcopy --strip-debug hello objcopy --add-gnu-debuglink=hello.full hello
完整的可执行文件的工作方式与您使用

--only-keep-debug

创建的调试文件一样...(但如果您有它,它会更酷,我认为)。

© www.soinside.com 2019 - 2024. All rights reserved.