简体   繁体   English

如何在 kernel 模块代码中包含 C 回溯?

[英]How to include C backtrace in a kernel module code?

So I am trying to find out what kernel processes are calling some functions in a block driver.所以我试图找出 kernel 进程正在调用块驱动程序中的某些函数。 I thought including backtrace() in the C library would make it easy.我认为在 C 库中包含 backtrace() 会很容易。 But I am having trouble to load the backtrace.但是我无法加载回溯。

I copied this example function to show the backtrace:我复制了这个例子 function 来显示回溯:

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

All attempts to compile have error in one place or another that a file cannot be found or that the functions are not defined.所有的编译尝试在某个地方或另一个地方都有错误,即找不到文件或未定义函数。

Here is what comes closest.这是最接近的。

In the Makefile I put the compiler directives:在 Makefile 我放了编译器指令:

 -rdynamic -I/usr/include 

If I leave out the second one, -I/usr/include, then the compiler reports it cannot find the required header execinfo.h.如果我忽略了第二个,-I/usr/include,那么编译器会报告它找不到所需的 header execinfo.h。

Next, in the code where I want to do the backtrace I have copied the function from the example:接下来,在我想要执行回溯的代码中,我从示例中复制了 function:

//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

I have put the call to this function later on, in a block driver function where the first sign of the error happens.稍后,我在块驱动程序 function 中调用了这个 function,其中出现了错误的第一个迹象。 Simply:简单地:

show_stackframe();

So when I compile it, the following errors:所以当我编译它时,出现以下错误:

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!

Note: block26.c is the file I am hoping to get the backtrace from.注意:block26.c 是我希望从中获取回溯的文件。

Is there an obvious reason why the backtrace and backtrace_symbols remain undefined when it is compiled into the.ko modules?当 backtrace 和 backtrace_symbols 被编译到 .ko 模块中时,是否有明显的原因保持未定义?

I am guessing it because I use the compiler include execinfo.h which is residing on the computer and not being loaded to the module.我猜是因为我使用了编译器 include execinfo.h,它驻留在计算机上并且没有加载到模块中。

It is my uneducated guess to say the least.至少可以说,这是我没有受过教育的猜测。

Can anyone offer a help to get the backtrace functions loading up in the module?任何人都可以提供帮助以在模块中加载回溯功能吗?

Thanks for looking at this inquiry.感谢您查看此查询。

I am working on debian.我正在研究 debian。 When I take out the function and such, the module compiles fine and almost works perfectly.当我取出 function 等时,该模块编译良好,几乎可以完美运行。

From ndasusers来自 ndasusers

To print the stack contents and a backtrace to the kernel log, use the dump_stack() function in your kernel module.要打印堆栈内容和 kernel 日志的回溯,请在 kernel 模块中使用dump_stack() function。 It's declared in linux/kernel.h in the include folder in the kernel source directory.它在 kernel 源目录的 include 文件夹中的linux/kernel.h中声明。

If you need to save the stack trace and process its elements somehow, save_stack_trace() or dump_trace() might be also an option.如果您需要保存堆栈跟踪并以某种方式处理其元素, save_stack_trace()dump_trace()可能也是一种选择。 These functions are declared in <linux/stacktrace.h> and <asm/stacktrace.h> , respectively.这些函数分别在<linux/stacktrace.h><asm/stacktrace.h>中声明。

It is not as easy to use these as dump_stack() but if you need more flexibility, they may be helpful.使用它们不像dump_stack()那样容易,但如果您需要更大的灵活性,它们可能会有所帮助。

Here is how save_stack_trace() can be used (replace HOW_MANY_ENTRIES_TO_STORE with the value that suits your needs, 16-32 is usually more than enough):以下是如何使用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);

Now stack_entries array contains the appropriate call addresses.现在stack_entries数组包含适当的调用地址。 The number of elements filled is nr_entries .填充的元素数量为nr_entries

One more thing to point out.还有一件事要指出。 If it is desirable not to output the stack entries that belong to the implementation of save_stack_trace() , dump_trace() or dump_stack() themselves (on different systems, the number of such entries may vary), the following trick can be applied if you use save_stack_trace() .如果不希望 output 属于save_stack_trace()dump_trace()dump_stack()实现的堆栈条目本身(在不同的系统上,此类条目的数量可能会有所不同),如果您可以应用以下技巧使用save_stack_trace() You can use __builtin_return_address(0) as an "anchor" entry and process only the entries "not lower" than that.您可以使用__builtin_return_address(0)作为“锚”条目并仅处理“不低于”的条目。

I know this question is about Linux, but since it's the first result for "backtrace kernel", here's a few more solutions:我知道这个问题是关于 Linux,但由于它是“回溯内核”的第一个结果,这里还有一些解决方案:


DragonFly BSD蜻蜓 BSD

It's print_backtrace(int count) from /sys/sys/systm.h .它是来自/sys/sys/systm.hprint_backtrace(int count) It's implemented in /sys/kern/kern_debug.c and/or /sys/platform/pc64/x86_64/db_trace.c .它在/sys/kern/kern_debug.c和/或/sys/platform/pc64/x86_64/db_trace.c中实现。 It can be found by searching for panic , which is implemented in /sys/kern/kern_shutdown.c , and calls print_backtrace(6) if DDB is defined and trace_on_panic is set, which are both defaults.可以通过搜索panic找到,它在 /sys/kern/kern_shutdown.c 中实现,如果定义了DDB并设置了/sys/kern/kern_shutdown.c ,则调用trace_on_panic print_backtrace(6) ,这两个都是默认值。


FreeBSD自由BSD

It's kdb_backtrace(void) from /sys/sys/kdb.h .它是来自/sys/sys/kdb.hkdb_backtrace(void) Likewise, it's easy to find by looking into what the panic implementation calls when trace_on_panic is true.同样,当trace_on_panic为真时,通过查看panic实现调用的内容很容易找到。


OpenBSD OpenBSD

Going the panic route, it appears to be db_stack_dump() , implemented in /sys/ddb/db_output.c .panic路线,它似乎是db_stack_dump() ,在/sys/ddb/db_output.c中实现 The only header mention is /sys/ddb/db_output.h .唯一提到的 header 是/sys/ddb/db_output.h

dump_stack() is function can be used to print your stack and thus can be used to backtrack. dump_stack()是 function 可用于打印您的堆栈,因此可用于回溯。 while using it be carefull that don't put it in repetitive path like loops or packet receive function it can fill your dmesg buffer can cause crash in embedded device (having less memory and cpu).使用它时要小心,不要将它放在重复的路径中,如循环或数据包接收 function 它可以填充您的 dmesg 缓冲区可能导致嵌入式设备崩溃(具有较少的 memory 和 cpu)。

This function is declared in linux/kernel.h .这个 function 在linux/kernel.h中声明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM