如何在内核模块代码中包含 C 回溯?
所以我试图找出哪些内核进程正在调用块驱动程序中的某些函数。我认为在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
要将堆栈内容和回溯打印到内核日志,请使用内核模块中的
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 inlinux/kernel.h
in the include folder in the kernel source directory.如果您需要保存堆栈跟踪并以某种方式处理其元素,
save_stack_trace()
或dump_trace()
也可能是一个选项。这些函数分别在
和
中声明。使用它们不像
dump_stack()
那么容易,但如果您需要更大的灵活性,它们可能会有所帮助。以下是
save_stack_trace()
的使用方法(将HOW_MANY_ENTRIES_TO_STORE
替换为适合您需要的值,16-32 通常就足够了):现在
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()
ordump_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 (replaceHOW_MANY_ENTRIES_TO_STORE
with the value that suits your needs, 16-32 is usually more than enough):Now
stack_entries
array contains the appropriate call addresses. The number of elements filled isnr_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()
ordump_stack()
themselves (on different systems, the number of such entries may vary), the following trick can be applied if you usesave_stack_trace()
. You can use__builtin_return_address(0)
as an "anchor" entry and process only the entries "not lower" than that.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
.我知道这个问题是关于 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.hpanic
当trace_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 forpanic
, which is implemented in/sys/kern/kern_shutdown.c
, and callsprint_backtrace(6)
ifDDB
is defined andtrace_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 thepanic
implementation calls whentrace_on_panic
is true.OpenBSD
Going the
panic
route, it appears to bedb_stack_dump()
, implemented in/sys/ddb/db_output.c
. The only header mention is/sys/ddb/db_output.h
.