最近項目上遇到一個關于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