2016-02-11 220 views
2

我正在調試導致我的Mac上的內核轉儲的驅動程序。這表明長回溯構成了一系列的地址的:OS X內核恐慌診斷。如何翻譯回溯地址

panic(cpu 6 caller 0xffffff8004dc9986): trying to interlock destroyed mutex 
(0xffffff8049deedb0) 
Backtrace (CPU 6), Frame : Return Address 
0xffffff93b1c8bb50 : 0xffffff8004ce5307 
0xffffff93b1c8bbd0 : 0xffffff8004dc9986 
0xffffff93b1c8bbe0 : 0xffffff8004d099eb 
0xffffff93b1c8bc20 : 0xffffff7f85604899 
0xffffff93b1c8bc50 : 0xffffff800519776b 
0xffffff93b1c8bc90 : 0xffffff80051f336c 
0xffffff93b1c8be00 : 0xffffff8005205fb3 
0xffffff93b1c8bef0 : 0xffffff80052028a6 
0xffffff93b1c8bf60 : 0xffffff800522afd1 
0xffffff93b1c8bfb0 : 0xffffff8004df4b16 

我認爲由於計算機進行重新啓動,地址翻譯是沒用的,因爲現在的內存映射均可以啓動迭代後不同。

是否有任何選項可以將相關方法與回顧中的每個地址進行匹配,或提前設置適當的配置? 謝謝

回答

6

是的,您絕對可以象徵內核恐慌痕跡,但要追溯性地執行此操作,您需要來自恐慌日誌的更多信息而不僅僅是原始堆棧跟蹤。正如你所說,地址只對加載地址有意義。

蘋果關於該主題的官方文檔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緩存中遇到問題時,這非常棒。

+0

非常感謝,我已經設法使用簡單的方法,在恐慌已知的先驗,如果我得到意想不到的恐慌,我絕對會嘗試手動的方式。再次感謝 ! – Zohar81

+0

感謝您的信息!我可以問你在哪裏學習了這個更新的程序嗎?是否有一些我可以檢查的新文件? – ravron

+0

@ravron我不認爲任何地方都有公共的規範文檔。這幾乎是我在過去6-7年的Mac內核編程中所揀選的內容,因爲他們已經逐步對每個操作系統版本進行了一次或兩次更改。我應該把它作爲博客文章更詳細地寫下來;我在我們的內部wiki上編寫了比上述內容更詳細的文檔,並且可以將其轉換爲博客文章......蘋果最新的公開kext文檔可能是WWDC 2013會話707. https:// developer。 apple.com/videos/play/wwdc2013/707/ – pmdj