剥离二进制文件后的调试部分

Posted

技术标签:

【中文标题】剥离二进制文件后的调试部分【英文标题】:Debug sections after binary is stripped 【发布时间】:2016-03-25 22:49:11 【问题描述】:

我在 linux 上构建了我的应用程序(c/c++)并使用“strip”命令将其剥离。 我认为如果不提供任何选项,它将从原始二进制文件中删除所有调试信息。 我使用以下内容进行了剥离:

strip my_app -o $odir/my_app_stripped  (where $odir is preconfigured location)

但是,当我执行以下操作时:

objdump -h my_app_stripped

它给了我以下输出:

my_app_stripped: file format elf32-i386
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
 0 .interp       0000002c  00048154  00048154  00000154  2**0
                 CONTENTS, ALLOC, LOAD, READONLY, DATA
 1 .note.ABI-tag 00000020  00048180  00048180  00000180  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
 2 .hash         00067dcc  000481a0  000481a0  000001a0  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
 3 .dynsym       0011f6e0  000aff6c  000aff6c  00067f6c  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
 4 .dynstr       00488e4c  001cf64c  001cf64c  0018764c  2**0
              CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version  00023edc  00658498  00658498  00610498  2**1
              CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000290  0067c374  0067c374  00634374  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.dyn      00006860  0067c604  0067c604  00634604  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt      00003768  00682e64  00682e64  0063ae64  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init         00000017  006865cc  006865cc  0063e5cc  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt          00006ee0  006865e4  006865e4  0063e5e4  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text         01120918  0068d4d0  0068d4d0  006454d0  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
12 BINK          00018d20  017addf0  017addf0  01765df0  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
13 BINK32        00001350  017c6b10  017c6b10  0177eb10  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
14 BINK16        00001008  017c7e60  017c7e60  0177fe60  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
15 BINKP8        000008fb  017c8e70  017c8e70  01780e70  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
16 BINKY16       000008e1  017c9770  017c9770  01781770  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
17 BINKY12       000001b0  017ca060  017ca060  01782060  2**4
              CONTENTS, ALLOC, LOAD, READONLY, CODE
18 .fini         0000001a  017ca210  017ca210  01782210  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE
19 .rodata       00164204  017ca240  017ca240  01782240  2**6
              CONTENTS, ALLOC, LOAD, READONLY, DATA
20 .debug$S      000010f8  0192e444  0192e444  018e6444  2**0
              CONTENTS, ALLOC, LOAD, READONLY, DATA
21 BINKCONST     00004e40  0192f540  0192f540  018e7540  2**6
              CONTENTS, ALLOC, LOAD, READONLY, DATA
22 .debug$F      00000250  01934380  01934380  018ec380  2**0
              CONTENTS, ALLOC, LOAD, READONLY, DATA
23 .rdata        00000080  019345d0  019345d0  018ec5d0  2**4
              CONTENTS, ALLOC, LOAD, READONLY, DATA
24 .eh_frame_hdr 0004765c  01934650  01934650  018ec650  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
25 .eh_frame     00128fec  0197bcac  0197bcac  01933cac  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
26 .gcc_except_table 000aaaf1  01aa4c98  01aa4c98  01a5cc98  2**2
              CONTENTS, ALLOC, LOAD, READONLY, DATA
27 .tbss         00000004  01b5078c  01b5078c  01b0778c  2**2
              ALLOC, THREAD_LOCAL
28 .ctors        000004f4  01b5078c  01b5078c  01b0778c  2**2
              CONTENTS, ALLOC, LOAD, DATA
29 .dtors        000004d0  01b50c80  01b50c80  01b07c80  2**2
              CONTENTS, ALLOC, LOAD, DATA
30 .jcr          00000004  01b51150  01b51150  01b08150  2**2
              CONTENTS, ALLOC, LOAD, DATA
31 .data.rel.ro  00012160  01b51160  01b51160  01b08160  2**5
              CONTENTS, ALLOC, LOAD, DATA
32 .dynamic      00000240  01b632c0  01b632c0  01b1a2c0  2**2
              CONTENTS, ALLOC, LOAD, DATA
33 .got          00002e6c  01b63500  01b63500  01b1a500  2**2
              CONTENTS, ALLOC, LOAD, DATA
34 .data         000481a8  01b66380  01b66380  01b1d380  2**5
              CONTENTS, ALLOC, LOAD, DATA
35 .got.plt      00001bc0  01bae528  01bae528  01b65528  2**2
              CONTENTS, ALLOC, LOAD, DATA
36 BINKDATA      00002de0  01bb0100  01bb0100  01b67100  2**5
              CONTENTS, ALLOC, LOAD, DATA
37 .bss          0046f8e8  01bb2ee0  01bb2ee0  01b69ee0  2**5
              ALLOC
38 BINKBSS       000067a0  020227e0  020227e0  01b69ee0  2**5
              ALLOC
39 .comment      00002d95  00000000  00000000  01b69ee0  2**0
              CONTENTS, READONLY
40 .drectve      0000005d  00000000  00000000  01b6cc75  2**0
              CONTENTS, READONLY

那么,如果调试被全部删除,那么“.debug$S”和“.debug$F”是什么部分?

【问题讨论】:

【参考方案1】:

尽管它们的名称这些部分不是调试部分,至少根据它们的标志不是。您会注意到它们具有相同的标志CONTENTS, ALLOC, LOAD, READONLY, DATA,与可执行文件中的许多其他部分(如.rodata)相同。这些标志表示该部分旨在加载到内存中并用作数据。 strip 命令无法知道这些部分是否不必要。丢弃.rodata 部分会破坏您的程序,导致它在每次运行时崩溃。 strip 命令不知道丢弃 .debug$F.debug$S 部分不会做同样的事情。

请注意,您通常不会在 ELF 可执行文件中找到名为 .debug$Fdebug$S 的部分。通常在 ELF 文件中使用的 DWARF 调试信息存储在名称以 .debug_ 而不是 .debug$ 开头的部分中。他们还设置了DEBUGGING 标志(但没有设置LOAD 标志),因此strip 知道他们正在调试部分并且应该并且可以删除它。具有这些名称的部分通常只能在 Microsoft 编译器生成的 PECOFF 文件中看到。它们包含 Microsoft 专有格式的调试信息。

如果您可以确定这些部分不包含有用的信息并且想要删除它们,您应该在链接之前将它们从目标文件中删除。由于它们已加载到内存中,因此在链接后完全删除它们可能为时已晚。您可以使用objcopy -R ".debug$*" foo.o foo-stripped.o 之类的命令,然后使用foo-stripped.o 而不是foo.o 链接。

您可能还想从可执行文件中删除.comment.directve 部分,因为这些部分可能不是必需的。特别是.directve 是另一个您通常不会在 ELF 文件中看到的 PECOFF 部分。

【讨论】:

感谢您的回答。但是,当您说“.debug$S/F”和“.directive”是由微软创建的 PECOFF 格式部分时,我不明白。但我在 linux 上工作并使用 gcc/g++,那么这些是如何创建的呢? @Monku GCC/G++ 永远不会在任何平台上创建 .debug$ 部分,除非你明确告诉它创建一个这样的部分并准确告诉它要放入什么(例如 @987654342 @)。它仅在 Windows PECOFF 目标上创建 .directive 部分。因此,要么您链接到由 Microsoft 编译器创建的目标文件,要么您的代码在某处明确告诉 GCC 创建这些部分。创建地图文件可以帮助您确定哪个。将 -Wl,-Map=my_app.map 传递给用于创建可执行文件的 GCC 命令。

以上是关于剥离二进制文件后的调试部分的主要内容,如果未能解决你的问题,请参考以下文章

仅去除带有通配符排除的二进制文件的函数名称

如何确定是不是在 Mac OS X 上剥离了二进制文件?

如何彻底剥离可执行文件

将“复制期间剥离调试符号”设置为 NO 后经常出现内存警告

Visual Studio 调试 - 将数组转储到文件

VC调试器高级应用----高级断点篇