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

发布于 2024-11-04 16:11:59 字数 2656 浏览 0 评论 0原文

所以我试图找出哪些内核进程正在调用块驱动程序中的某些函数。我认为在 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();

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

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 和 backtrace_symbols 编译到 .ko 模块中时仍然未定义,是否有明显的原因?

我猜测是因为我使用编译器 include execinfo.h ,它驻留在计算机上并且没有加载到模块中。

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

任何人都可以提供帮助来在模块中加载回溯函数吗?

感谢您查看此询问。

我正在 debian 上工作。当我取出该函数等时,该模块可以正常编译并且几乎可以完美运行。

来自 ndasusers

So I am trying to find out what kernel processes are calling some functions in a block driver. I thought including backtrace() in the C library would make it easy. But I am having trouble to load the backtrace.

I copied this example function to show the backtrace:

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:

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

Next, in the code where I want to do the backtrace I have copied the function from the example:

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

Is there an obvious reason why the backtrace and backtrace_symbols remain undefined when it is compiled into the .ko modules?

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.

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. When I take out the function and such, the module compiles fine and almost works perfectly.

From ndasusers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

油饼 2024-11-11 16:11:59

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

To print the stack contents and a backtrace to the kernel log, use the dump_stack() function in your kernel module. It's declared in linux/kernel.h in the include folder in the kernel source directory.

神仙妹妹 2024-11-11 16:11:59

如果您需要保存堆栈跟踪并以某种方式处理其元素,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< /code> 数组包含适当的调用地址。填充的元素数量为nr_entries

还有一点需要指出。如果不希望输出属于 save_stack_trace()dump_trace()dump_stack() 本身实现的堆栈条目(在不同的系统上,此类条目的数量可能会有所不同),如果您使用save_stack_trace(),则可以应用以下技巧。您可以使用 __builtin_return_address(0) 作为“锚”条目,并仅处理“不低于”该条目的条目。

If you need to save the stack trace and process its elements somehow, save_stack_trace() or dump_trace() might be also an option. These functions are declared in <linux/stacktrace.h> and <asm/stacktrace.h>, respectively.

It is not as easy to use these as dump_stack() but if you need more flexibility, they may be helpful.

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):

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. The number of elements filled is 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(). You can use __builtin_return_address(0) as an "anchor" entry and process only the entries "not lower" than that.

调妓 2024-11-11 16:11:59

dump_stack() 函数可用于打印堆栈,因此可用于回溯。使用它时要小心,不要将它放在重复的路径中,例如循环或数据包接收函数,它会填充您的 dmesg 缓冲区,并可能导致嵌入式设备崩溃(内存和 CPU 较少)。

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

dump_stack() is function can be used to print your stack and thus can be used to backtrack . 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).

This function is declared in linux/kernel.h .

沩ん囻菔务 2024-11-11 16:11:59

我知道这个问题是关于 Linux 的,但由于它是“backtrace kernel”的第一个结果,这里还有一些解决方案:


DragonFly BSD

It's print_backtrace(int count) from /sys/sys/systm.h。它的实施于
/sys/kern/kern_debug.c 和/或 /sys/platform/pc64/ x86_64/db_trace.c。搜索panic即可找到,其实现在/sys/kern/kern_shutdown.c,如果定义了 DDB 并且 则调用 print_backtrace(6)已设置trace_on_panic,这都是默认值。


FreeBSD

它是来自 /sys/ 的 kdb_backtrace(void) sys/kdb.h。同样,通过查看 panictrace_on_panic 为 true 时调用实现。


OpenBSD

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

I know this question is about Linux, but since it's the first result for "backtrace kernel", here's a few more solutions:


DragonFly BSD

It's print_backtrace(int count) from /sys/sys/systm.h. It's implemented in
/sys/kern/kern_debug.c and/or /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.


FreeBSD

It's kdb_backtrace(void) from /sys/sys/kdb.h. Likewise, it's easy to find by looking into what the panic implementation calls when trace_on_panic is true.


OpenBSD

Going the panic route, it appears to be db_stack_dump(), implemented in /sys/ddb/db_output.c. The only header mention is /sys/ddb/db_output.h.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文