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/bl开发者_StackOverflowock/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
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.
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.
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
.
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
.
精彩评论