如何在内核模块代码中包含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  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(); 

所以当我编译它时,会出现以下错误:

 user@slinux:~/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是我希望从中获取回溯的文件。

回溯和backtrace_symbols在编译成.ko模块时是否仍然未定义?

我猜它是因为我使用编译器包括execinfo.h,它驻留在计算机上而不是加载到模块。

至少可以说,这是我没有受过教育的猜测。

任何人都可以提供帮助,以便在模块中加载回溯function吗?

感谢您查看此查询。

我正在研究debian。 当我取出这样的function时,模块编译得很好并且几乎完美地工作。

来自ndasusers

要将堆栈内容和回溯打印到内核日志,请在内核模块中使用dump_stack()函数。 它在linux/kernel.h中的内核源目录的include文件夹中声明。

如果需要以某种方式保存堆栈跟踪并处理其元素,则save_stack_trace()dump_trace()也可能是一个选项。 这些函数分别在

使用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)作为“锚点”条目,并仅处理“不低于”的条目。

我知道这个问题是关于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并且设置了/sys/kern/kern_shutdown.c ,则调用print_backtrace(6) ,这两者都是默认值。


FreeBSD的

它是kdb_backtrace(void)kdb_backtrace(void) 。 同样,通过查看trace_on_panic为true时panic实现调用的内容很容易找到。


OpenBSD系统

panic路线,似乎是db_stack_dump() ,在/sys/ddb/db_output.c实现 。 唯一提到的标题是/sys/ddb/db_output.h

dump_stack()函数可用于打印堆栈,因此可用于回溯。 使用它时要小心,不要把它放在像循环或数据包接收function这样的重复路径中,它可以填满你的dmesg缓冲区,可能导致嵌入式设备崩溃(内存和cpu较少)。

该函数在linux/kernel.h声明。