ftrace/x86/extable: Add is_ftrace_trampoline() function
Stack traces that happen from function tracing check if the address on the stack is a __kernel_text_address(). That is, is the address kernel code. This calls core_kernel_text() which returns true if the address is part of the builtin kernel code. It also calls is_module_text_address() which returns true if the address belongs to module code. But what is missing is ftrace dynamically allocated trampolines. These trampolines are allocated for individual ftrace_ops that call the ftrace_ops callback functions directly. But if they do a stack trace, the code checking the stack wont detect them as they are neither core kernel code nor module address space. Adding another field to ftrace_ops that also stores the size of the trampoline assigned to it we can create a new function called is_ftrace_trampoline() that returns true if the address is a dynamically allocate ftrace trampoline. Note, it ignores trampolines that are not dynamically allocated as they will return true with the core_kernel_text() function. Link: http://lkml.kernel.org/r/20141119034829.497125839@goodmis.org Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:

committed by
Steven Rostedt

parent
9960efeb80
commit
aec0be2d6e
@@ -1117,6 +1117,43 @@ static struct ftrace_ops global_ops = {
|
||||
FTRACE_OPS_FL_INITIALIZED,
|
||||
};
|
||||
|
||||
/*
|
||||
* This is used by __kernel_text_address() to return true if the
|
||||
* the address is on a dynamically allocated trampoline that would
|
||||
* not return true for either core_kernel_text() or
|
||||
* is_module_text_address().
|
||||
*/
|
||||
bool is_ftrace_trampoline(unsigned long addr)
|
||||
{
|
||||
struct ftrace_ops *op;
|
||||
bool ret = false;
|
||||
|
||||
/*
|
||||
* Some of the ops may be dynamically allocated,
|
||||
* they are freed after a synchronize_sched().
|
||||
*/
|
||||
preempt_disable_notrace();
|
||||
|
||||
do_for_each_ftrace_op(op, ftrace_ops_list) {
|
||||
/*
|
||||
* This is to check for dynamically allocated trampolines.
|
||||
* Trampolines that are in kernel text will have
|
||||
* core_kernel_text() return true.
|
||||
*/
|
||||
if (op->trampoline && op->trampoline_size)
|
||||
if (addr >= op->trampoline &&
|
||||
addr < op->trampoline + op->trampoline_size) {
|
||||
ret = true;
|
||||
goto out;
|
||||
}
|
||||
} while_for_each_ftrace_op(op);
|
||||
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ftrace_page {
|
||||
struct ftrace_page *next;
|
||||
struct dyn_ftrace *records;
|
||||
@@ -5373,6 +5410,7 @@ static struct ftrace_ops graph_ops = {
|
||||
FTRACE_OPS_FL_STUB,
|
||||
#ifdef FTRACE_GRAPH_TRAMP_ADDR
|
||||
.trampoline = FTRACE_GRAPH_TRAMP_ADDR,
|
||||
/* trampoline_size is only needed for dynamically allocated tramps */
|
||||
#endif
|
||||
ASSIGN_OPS_HASH(graph_ops, &global_ops.local_hash)
|
||||
};
|
||||
|
Reference in New Issue
Block a user