最近项目上遇到一个关于Debug Symbol
泄露方面的问题:使用nm
命令可以显示二进制目标文件的符号表,造成信息泄露:
nm -a TargetBinary
-a:每个符号前显示文件名;
-d:显示动态符号
-g:仅显示外部符号
-r:反序显示符号表
TargetBinary:目标文件,即二进制目标文件,通常是库文件和可执行文件
利用之前的一个小项目来做测试:
这个项目包含一些简单的
swift
文件,使用nm
命令后,可以看到类名方法等信息的确暴露了出来,并且有相应的地址信息:可见在XCode默认配置下,代码信息的确遭到了暴露,打开XCode的项目配置文件,我们看看哪些设置会影响到符号的暴露:
这里有三个最主要的跟符号相关的信息:
"Deployment Postprocessing" 默认为NO
"Strip Linked Product" 默认为YES
"Strip Style" 默认为All Symbols
让我们打开Deployment Postprocessing
看看结果有什么不同:
可以看到,类、方法、地址等信息都被隐藏了,只留下了一些系统类库的类信息:
"Deployment Postprocessing" 事实上是一个总开关
只有这个打开的情况下,下面两个设置才有用。
"Strip Linked Product" 设定是否需要剥离符号信息
只有这个打开的情况下,下面的设置才有用
"Strip Style" 设定剥离方式
- All Symbols
- Non-global Symbols
- Debug Symbols
在同样的设置界面,我还还看到一个同样用于Strip
的设置:
"Strip Debug Symbols During Copy"
这个设置看起来也说得是剥离调试符号
但是偏偏加了一个"Copy",所以这个不是直接应用于项目的目标文件
而是对于
"binary files which are copied during the build
(e.g., in a Copy Bundle Resources or Copy Files build phase)
to be stripped of debugging symbols"
我们可以看到,Debug Symbols
是被剥离的主要对象,我们有几个地方来控制它的产生:
"Generate Debug Symbols" 是用来控制是否在编译时产生调试符号
"Debug Information Level" 是用来设定调试符号的细节级别
- "Compiler default" 默认所有的
- "Line tables only" 仅包含函数名、文件名、行号,不包括其他数据比如局部变量、函数参数等
与Debug Symbols
对应的,就是我们在程序崩溃时用来解析符号表的dSYM
文件:
通过
Debug Information Format
来选择是否在编译时同步生成dSYM
文件。
问题
在实际应用上面的设置时,遇到了一个奇怪的问题,就是当打开Strip Style
为All Symbols
时,编译在最后的Strip
阶段出错:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip:
symbols referenced by indirect symbol table entries that can't be stripped in: ***
通过最下面的两篇引用文章,可以知道其实是对于library
,我们是不可以将所有的符号都去掉的,这样,我们最高能去掉的级别是Non-global Symbols
。而我们的实际应用,是建立在一个SDK的类库基础上的,所以不能将符号剥离的级别调到最高。
总结
Setting | Debug | Release | Distribution | Comments |
---|---|---|---|---|
Generate Debug Symbols | Yes | No | No | 发布时不生成调试符号,减小体积 |
Debug Information Level | Compiler default | Compiler default | Compiler default | 默认调试设置 |
Debug Information Format | DWARF | DWARF | DWARF | 默认不生成dSYM文件,需要时再打开 |
Deployment Postprocessing | No | Yes | Yes | 发布时需要去除符号,减小体积,增加安全性 |
Strip Linked Product | Yes | Yes | Yes | 默认设置 |
Strip Style | All Symbols | Non-global Symbols | Non-global Symbols | 对于类库,仅打开非全局符号,其他默认全打开 |
Strip Debug Symbols During Copy | Yes | Yes | Yes | 默认移除调试符号 |
这份配置表是针对公司产品的,可以看到,为了减少符号暴露,我们相应的dSYM
都没有生成,这也就意味着,一旦发布的程序崩溃,我们无法对Crash Log
进行任何解析。另一方面,去除了这些符号,也相应减小了我们APP的体积(约为10%)。
引用
How to strip Cocoa Touch frameworks
Xcode中和symbols有关的几个设置
后记
"Strip Debug Symbols During Copy"默认被设为 "NO": Skipping Copy Phase Strip