是的,您絕對可以象徵內核恐慌痕跡,但要追溯性地執行此操作,您需要來自恐慌日誌的更多信息而不僅僅是原始堆棧跟蹤。正如你所說,地址只對加載地址有意義。
蘋果關於該主題的官方文檔TN2063已有點過時。它給出的例子來自Darwin 9,即OS X 10.5,並且自那時以來,隨着Kernel ASLR和kext UUID的引入,事情發生了一些變化。我會盡力給你一個非常快速的最新指南。
1.簡單的方法
如果你的恐慌是可重複的,最容易做的事情是讓內核symbolicate它。使用內核啓動參數keepsyms=1
意味着內核不會丟棄存儲在內核和kext圖像中的任何符號,並且在恐慌的情況下將查找堆棧跟蹤中的返回指針。
只需將keepsyms=1
添加到/Library/Preferences/SystemConfiguration/com.apple.Boot.plist
的內核標誌設置或boot-args
NVRAM變量中即可。重新啓動以及任何後續恐慌將自動進行符號化。您可以通過c++filt
命令行實用程序運行損壞的C++符號以獲取正確的C++函數簽名。例如,
$ echo __ZN32IOPCIMessagedInterruptController17registerInterruptEP9IOServiceiPvPFvS2_S2_S2_iES2_ | c++filt
IOPCIMessagedInterruptController::registerInterrupt(IOService*, int, void*, void (*)(void*, void*, void*, int), void*)
2.手工方式
如果你有一個unsymbolicated,神祕恐慌你似乎無法重現,最簡單的方式是沒有太大的幫助。
緊跟在堆棧跟蹤之後,在panic日誌中查找以「backtrace:內核擴展:」開頭的部分。這將列出恐慌中涉及的任何kext,包括它們的加載地址,版本和UUID。地址以範圍給出;起始地址位於->
的左側,並在@
之後。最後的地址在箭頭的右側。有了這些信息,您應該能夠識別堆棧跟蹤中列出的每個代碼地址(右側的十六進制數字)所在的kext。
除了其中的一些將不匹配任何kext。除了在某些奇怪的情況下,這些將來自內核本身。內核映像(內核或mach_kernel)加載地址會進一步向下,它會顯示「內核文本基址:」
一旦您知道要查找哪個可執行映像,atos
命令將讓您用符號表示每個地址。
例如,假設我們有這樣的線在恐慌:
…
0xffffff8098c1bba0 : 0xffffff7f80c343f2
…
而且我們還發現:
Kernel Extensions in backtrace:
com.apple.iokit.IOPCIFamily(2.9)[BDA92C3B-AD86-33E5-A7F1-1603465350A7]@0xffffff7f80c1a000->0xffffff7f80c4dfff
注意0xffffff7f80c343f2大於(或等於)0xffffff7f80c1a000和小於(或等於)0xffffff7f80c4dfff,所以有問題的代碼在IOPCIFamily中。
這使我下面的命令(及其輸出):
$ atos -o /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Extensions/IOPCIFamily.kext/IOPCIFamily -l 0xffffff7f80c1a000 0xffffff7f80c343f2
IOPCIMessagedInterruptController::registerInterrupt(IOService*, int, void*, void (*)(void*, void*, void*, int), void*) (in IOPCIFamily) (IOPCIMessagedInterruptController.cpp:85)
-o
指定的可執行文件。這通常位於.kext包的Contents/MacOS /子目錄中,但某些Apple的kexts直接位於.kext目錄中。對於內核本身的功能,提供內核映像,例如/Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Kernels/kernel
。
-l
參數指定加載地址。即開始/文本庫。
最後,只需列出您要在該文件中符號化的所有地址。在這種情況下,只有一個,但可以列出多個。您也可以從標準輸入讀取它們(如果沒有在命令行中列出)。
有了這個,你應該能夠解碼你的整個痕跡。
上的UUID
記下您會發現,在跟蹤每一個KEXT,以及內核本身,都一個UUID上市。這對於確保您使用正確的符號版本很方便。這是來自Mach-O二進制文件中LC_UUID加載器命令的UUID。您可以檢查UUID的使用KEXT:
$ otool -l /Library/Developer/KDKs/KDK_10.10.5_14F27.kdk/System/Library/Extensions/IOPCIFamily.kext/IOPCIFamily | grep uuid
uuid BDA92C3B-AD86-33E5-A7F1-1603465350A7
要確認所使用的內核擴展爲symbolication確實匹配一個在恐慌。當您遇到奇怪的版本問題時,或者您在kext緩存中遇到問題時,這非常棒。
非常感謝,我已經設法使用簡單的方法,在恐慌已知的先驗,如果我得到意想不到的恐慌,我絕對會嘗試手動的方式。再次感謝 ! – Zohar81
感謝您的信息!我可以問你在哪裏學習了這個更新的程序嗎?是否有一些我可以檢查的新文件? – ravron
@ravron我不認爲任何地方都有公共的規範文檔。這幾乎是我在過去6-7年的Mac內核編程中所揀選的內容,因爲他們已經逐步對每個操作系統版本進行了一次或兩次更改。我應該把它作爲博客文章更詳細地寫下來;我在我們的內部wiki上編寫了比上述內容更詳細的文檔,並且可以將其轉換爲博客文章......蘋果最新的公開kext文檔可能是WWDC 2013會話707. https:// developer。 apple.com/videos/play/wwdc2013/707/ – pmdj