Saturday, 1 February 2014

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. 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:
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 isnt 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
Answers:-
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 (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 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() or dump_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.

0 comments:

Post a Comment

Twitter Delicious Facebook Digg Stumbleupon Favorites More