2012-10-28 107 views

回答

27

'?'意味着關於這個堆棧條目的信息可能不可靠。

堆棧輸出機制(請參閱dump_trace() function的實現)無法證明它找到的地址是調用堆棧中的有效返回地址。

'?'本身由printk_stack_address()輸出。

堆棧條目可能有效或不可用。有時候可以簡單地跳過它。 調查相關模塊的反彙編以查看在ClearFunctionName+0x88(或者在x86上緊接該位置之前)調用哪個函數可能會有所幫助。

關於可靠性

在x86上,當dump_stack()被調用時,實際檢查中堆疊arch/x86/kernel/dumpstack.c定義print_context_stack()的功能。看看它的代碼,我會試着在下面解釋它。

我假設您的Linux系統中沒有DWARF2堆棧解除設備(如果不是OpenSUSE或SLES,很可能不是)。在這種情況下,print_context_stack()似乎執行以下操作。

它從保證堆棧位置的地址的地址(代碼中的「堆棧」變量)開始。它實際上是dump_stack()中局部變量的地址。

函數重複遞增該地址(while (valid_stack_ptr ...) { ... stack++})並檢查它指向的內容是否也可以是內核代碼中的地址(if (__kernel_text_address(addr)) ...)。通過這種方式,當這些函數被調用時,它會嘗試查找函數的棧上返回地址。

當然,並不是每個看起來像返回地址的無符號長整型值實際上都是返回地址。所以該函數試圖檢查它。如果在內核的代碼中使用幀指針(如果CONFIG_FRAME_POINTER被設置,則使用%ebp /%rbp寄存器),它們可以用於遍歷函數的堆棧幀。函數的返回地址位於幀指針的正上方(即在%ebp/%rbp + sizeof(unsigned long)處)。 print_context_stack完全檢查。

如果存在「堆棧」指向的值爲返回地址的堆棧幀,則該值被視爲可靠的堆棧條目。 ops->address將與reliable == 1一起被調用,它最終將調用printk_stack_address()並將該值作爲可靠的調用堆棧條目輸出。否則地址將被視爲不可靠。不管怎樣,它都會輸出,但是會顯示'?'前綴。 [注意]如果幀指針信息不可用(例如默認情況下它是在Debian 6中),則由於這個原因,所有調用堆棧條目都將被標記爲不可靠。

具有DWARF2展開支持(並且設置了CONFIG_STACK_UNWIND)的系統是另一回事。

+0

偉大的答案 - 它錯過了一件事情,使其完成(我有點困惑拱門代碼中的間接程度) - 什麼使條目不可靠? – qdot

+0

我編輯了我的答案。希望我的解釋不是太混亂。 – Eugene

+0

到達那裏:)你的回答實際上證實了我對它的工作原理的一些懷疑 - 爲了給出一些背景信息,我試圖更新一個像驅動程序這樣的二進制blob +包裝器 - 所以內核實際上是我自己的版本..我弄糊塗,想要一些解釋的原因是,顯然在局部變量blob存儲函數指針內的一些函數,拋出整個系統一點點。請完成你的'另一個故事' - 特別是當主內核是DWARF2時它是如何工作的,但是模塊的某些部分不是。 – qdot