如何在内核模块代码中包含C backtrace?

nda*_*ers 24 c kernel backtrace linux-device-driver

所以我试图找出哪些内核进程正在调用块驱动程序中的某些函数.我认为在C库中包含backtrace()可以让它变得简单.但是我无法加载回溯.

我复制了这个示例函数来显示回溯:

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

所有编译尝试都在一个地方或另一个地方发生错误,导致无法找到文件或未定义函数.

这是最接近的.

在Makefile中我放了编译器指令:

 -rdynamic -I/usr/include 
Run Code Online (Sandbox Code Playgroud)

如果我省略第二个,-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
Run Code Online (Sandbox Code Playgroud)

我稍后在块驱动程序函数中调用此函数,其中发生错误的第一个符号.只是:

show_stackframe();
Run Code Online (Sandbox Code Playgroud)

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

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!
Run Code Online (Sandbox Code Playgroud)

注意:block26.c是我希望从中获取回溯的文件.

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

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

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

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

感谢您查看此查询.

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

来自ndasusers

jmk*_*yes 48

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


Eug*_*ene 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);
Run Code Online (Sandbox Code Playgroud)

现在stack_entries数组包含适当的调用地址.填充的元素数量是nr_entries.

还有一点需要指出.如果希望不输出属于实现的堆栈条目save_stack_trace(),dump_trace()或者dump_stack()它们自己(在不同的系统上,这些条目的数量可能不同),如果使用,可以应用以下技巧save_stack_trace().您可以使用__builtin_return_address(0)"锚点"条目并仅处理"不低于"的条目.