2011-05-02 107 views
23

所以我試圖找出哪些內核進程正在調用塊驅動程序中的某些功能。我認爲在C庫中包含backtrace()會讓它變得容易。但是我無法加載回溯。如何將C backtrace包含在內核模塊代碼中?

我複製此示例函數來顯示回溯:

http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/063/6391/6391l1.html

所有嘗試編譯有錯誤在一個地方或其他某個文件不能被發現的或功能沒有定義。

下面是最接近的。

在Makefile中,我把編譯器指令:

-rdynamic -I/usr/include 

如果我離開了第二個,-I/usr/include目錄,那麼編譯器報告它無法找到所需的頭execinfo.h。

接下來,若我想要做我抄在例子中,函數回溯代碼:

//trying to include the c backtrace capability 
#include <execinfo.h> 

void show_stackframe() { 
void *trace[16]; 
char **messages = (char **)NULL; 
int i, trace_size = 0; 

trace_size = backtrace(trace, 16); 
messages = backtrace_symbols(trace, trace_size); 
printk(KERN_ERR "[bt] Execution path:\n"); 
for (i=0; i<trace_size; ++i) 
    printk(KERN_ERR "[bt] %s\n", messages[i]); 
} 
//backtrace function 

我已經把調用這個函數以後,在塊驅動程序的功能,其中發生錯誤的第一個標誌。簡單地說:

show_stackframe(); 

所以,當我編譯它,以下錯誤:

[email protected]:~/2.6-32$ make -s 
Invoking make againt the kernel at /lib/modules/2.6.32-5-686/build 
In file included from /usr/include/features.h:346, 
     from /usr/include/execinfo.h:22, 
     from /home/linux/2.6-32/block/block26.c:49: 
/usr/include/sys/cdefs.h:287:1: warning: "__always_inline" redefined 
In file included from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc.h:86, 
     from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler.h:40, 
     from /usr/src/linux-headers-2.6.32-5-common/include/linux/stddef.h:4, 
     from /usr/src/linux-headers-2.6.32-5-common/include/linux/list.h:4, 
     from /usr/src/linux-headers-2.6.32-5-common/include/linux/module.h:9, 
     from /home/linux/2.6-32/inc/linux_ver.h:40, 
     from /home/linux/2.6-32/block/block26.c:32: 
/usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc4.h:15:1: warning: this is the location of the previous definition 
    /home/linux/2.6-32/block/block26.c:50: warning: function declaration isn’t a prototype 
WARNING: "backtrace" [/home/linux/2.6-32/ndas_block.ko] undefined! 
WARNING: "backtrace_symbols" [/home/linux/2.6-32/ndas_block.ko] undefined! 

注:block26.c是我希望能得到回溯文件。

當編譯到.ko模塊時,回溯和backtrace_symbols爲什麼仍然未定義有明顯的原因嗎?

我猜測它是因爲我使用的編譯器包括execinfo.h,它駐留在計算機上並且未加載到模塊。

這是我沒有受過教育的猜測,至少可以說。

任何人都可以提供一個幫助,以獲得加載模塊中的回溯函數嗎?

感謝您查看此調查。

我正在研究debian。當我拿出功能等,模塊編譯好,幾乎完美的作品。

從ndasusers

+2

我不太確定你是否應該在內核模塊代碼中包含這樣的庫。你有沒有嘗試過使用gdb並設置一箇中斷點? [1] [1]:http://www.xml.com/ldd/chapter/book/ch04.html#t5 – zdav 2011-05-02 22:37:13

+0

哦老鼠!我很害怕聽到這樣的事情。這看起來像你已經與我聯繫的有用章節。感謝那。 – ndasusers 2011-05-02 23:44:39

+0

與用戶空間程序不同,內核不與標準C庫(或任何其他庫)鏈接。 http://kernelnewbies.org/FAQ/LibraryFunctionsInKernel – jschmier 2011-05-03 18:21:59

回答

42

要打印堆棧內容,並回溯到內核日誌,使用dump_stack()函數你的內核模塊中。它在linux/kernel.h中的內核源代碼目錄中的include文件夾中聲明。

+1

謝謝。這是我期望用c backtrace做的事情。現在我只需要一個新帖子來幫助閱讀。 – ndasusers 2011-05-07 04:45:21

+0

顯示的值分爲兩個塊:第一個是地址顯示的堆棧的原始內容,第二個顯示每個堆棧幀像常規回溯。 – jmkeyes 2011-05-07 04:55:13

19

如果您需要保存堆棧跟蹤並以某種方式處理其元素,則可以使用save_stack_trace()dump_trace()作爲選項。這些函數分別在<linux/stacktrace.h><asm/stacktrace.h>中聲明。

它不像dump_stack()那樣容易使用,但如果您需要更多的靈活性,它們可能會有所幫助。

這裏是如何save_stack_trace()都可以使用(與適合自己需要的值替換HOW_MANY_ENTRIES_TO_STORE,16-32通常是綽綽有餘):

unsigned long stack_entries[HOW_MANY_ENTRIES_TO_STORE]; 
struct stack_trace trace = { 
    .nr_entries = 0, 
    .entries = &stack_entries[0], 

    .max_entries = HOW_MANY_ENTRIES_TO_STORE, 

    /* How many "lower entries" to skip. */ 
    .skip = 0 
}; 
save_stack_trace(&trace); 

現在stack_entries數組包含相應的呼叫地址。填充的元素數量爲nr_entries

還有一點需要指出。如果希望不輸出屬於save_stack_trace(),dump_trace()dump_stack()自身的堆棧條目(在不同的系統上,這些條目的數量可能會有所不同),如果使用save_stack_trace(),則可以應用以下技巧。您可以使用__builtin_return_address(0)作爲「錨點」條目並僅處理「不低於」的條目。

+0

對於一個偉大的職位+1。 – jmkeyes 2011-05-06 02:51:14

+0

謝謝你的幫助。我沒有使用這個技巧,但我可以。stack_dump顯示了我所想象的全部內容。 – ndasusers 2011-05-07 04:48:21

+0

我能夠使用此方法查找地址,但這些地址似乎與'System.map'中的任何地址都不匹配。那麼,我怎樣才能把這樣一個地址變成一個函數名? – 2018-02-27 12:07:01

0

我知道這個問題是關於Linux,但因爲它是「回溯內核」的第一個結果,這裏有幾個解決方案:


的DragonFly BSD

這是一個從/sys/sys/systm.hprint_backtrace(int count)。它在 /sys/kern/kern_debug.c和/或/sys/platform/pc64/x86_64/db_trace.c中實施。可以通過搜索在/sys/kern/kern_shutdown.c中執行的panic來找到,並且如果DDB被定義並且trace_on_panic被設置,則這兩個都是默認值,並且調用print_backtrace(6)


FreeBSD的

這是一個從/sys/sys/kdb.hkdb_backtrace(void)。同樣,當trace_on_panic爲真時,通過查看panic實現的調用很容易找到。


OpenBSD的

去了panic路線,這似乎是db_stack_dump(), implemented in /sys/ddb/db_output.c。唯一的標題提及是/sys/ddb/db_output.h