Skip to content

Commit

Permalink
Merge tag 'trace-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/rostedt/linux-trace

Pull tracing updates from Steven Rostedt:

 - Rework of the kprobe/uprobe and synthetic events to consolidate all
   the dynamic event code. This will make changes in the future easier.

 - Partial rewrite of the function graph tracing infrastructure. This
   will allow for multiple users of hooking onto functions to get the
   callback (return) of the function. This is the ground work for having
   kprobes and function graph tracer using one code base.

 - Clean up of the histogram code that will facilitate adding more
   features to the histograms in the future.

 - Addition of str_has_prefix() and a few use cases. There currently is
   a similar function strstart() that is used in a few places, but only
   returns a bool and not a length. These instances will be removed in
   the future to use str_has_prefix() instead.

 - A few other various clean ups as well.

* tag 'trace-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (57 commits)
  tracing: Use the return of str_has_prefix() to remove open coded numbers
  tracing: Have the historgram use the result of str_has_prefix() for len of prefix
  tracing: Use str_has_prefix() instead of using fixed sizes
  tracing: Use str_has_prefix() helper for histogram code
  string.h: Add str_has_prefix() helper function
  tracing: Make function ‘ftrace_exports’ static
  tracing: Simplify printf'ing in seq_print_sym
  tracing: Avoid -Wformat-nonliteral warning
  tracing: Merge seq_print_sym_short() and seq_print_sym_offset()
  tracing: Add hist trigger comments for variable-related fields
  tracing: Remove hist trigger synth_var_refs
  tracing: Use hist trigger's var_ref array to destroy var_refs
  tracing: Remove open-coding of hist trigger var_ref management
  tracing: Use var_refs[] for hist trigger reference checking
  tracing: Change strlen to sizeof for hist trigger static strings
  tracing: Remove unnecessary hist trigger struct field
  tracing: Fix ftrace_graph_get_ret_stack() to use task and not current
  seq_buf: Use size_t for len in seq_buf_puts()
  seq_buf: Make seq_buf_puts() null-terminate the buffer
  arm64: Use ftrace_graph_get_ret_stack() instead of curr_ret_stack
  ...
  • Loading branch information
torvalds committed Dec 31, 2018
2 parents f12e840 + 3d739c1 commit 495d714
Show file tree
Hide file tree
Showing 49 changed files with 2,494 additions and 1,644 deletions.
3 changes: 3 additions & 0 deletions Documentation/trace/kprobetrace.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ current_tracer. Instead of that, add probe points via
/sys/kernel/debug/tracing/kprobe_events, and enable it via
/sys/kernel/debug/tracing/events/kprobes/<EVENT>/enable.

You can also use /sys/kernel/debug/tracing/dynamic_events instead of
kprobe_events. That interface will provide unified access to other
dynamic events too.

Synopsis of kprobe_events
-------------------------
Expand Down
4 changes: 4 additions & 0 deletions Documentation/trace/uprobetracer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ current_tracer. Instead of that, add probe points via
However unlike kprobe-event tracer, the uprobe event interface expects the
user to calculate the offset of the probepoint in the object.

You can also use /sys/kernel/debug/tracing/dynamic_events instead of
uprobe_events. That interface will provide unified access to other
dynamic events too.

Synopsis of uprobe_tracer
-------------------------
::
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,

void arch_ftrace_update_code(int command)
{
command |= FTRACE_MAY_SLEEP;
ftrace_modify_all_code(command);
}

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/perf_callchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
frame.fp = regs->regs[29];
frame.pc = regs->pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = current->curr_ret_stack;
frame.graph = 0;
#endif

walk_stackframe(current, &frame, callchain_trace, entry);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ unsigned long get_wchan(struct task_struct *p)
frame.fp = thread_saved_fp(p);
frame.pc = thread_saved_pc(p);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = p->curr_ret_stack;
frame.graph = 0;
#endif
do {
if (unwind_frame(p, &frame))
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/return_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void *return_address(unsigned int level)
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.pc = (unsigned long)return_address; /* dummy */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = current->curr_ret_stack;
frame.graph = 0;
#endif

walk_stackframe(current, &frame, save_return_addr, &data);
Expand Down
15 changes: 7 additions & 8 deletions arch/arm64/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,17 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if (tsk->ret_stack &&
(frame->pc == (unsigned long)return_to_handler)) {
if (WARN_ON_ONCE(frame->graph == -1))
return -EINVAL;
if (frame->graph < -1)
frame->graph += FTRACE_NOTRACE_DEPTH;

struct ftrace_ret_stack *ret_stack;
/*
* This is a case where function graph tracer has
* modified a return address (LR) in a stack frame
* to hook a function return.
* So replace it to an original value.
*/
frame->pc = tsk->ret_stack[frame->graph--].ret;
ret_stack = ftrace_graph_get_ret_stack(tsk, frame->graph++);
if (WARN_ON_ONCE(!ret_stack))
return -EINVAL;
frame->pc = ret_stack->ret;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */

Expand Down Expand Up @@ -137,7 +136,7 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
frame.fp = regs->regs[29];
frame.pc = regs->pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = current->curr_ret_stack;
frame.graph = 0;
#endif

walk_stackframe(current, &frame, save_trace, &data);
Expand Down Expand Up @@ -168,7 +167,7 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
frame.pc = (unsigned long)__save_stack_trace;
}
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = tsk->curr_ret_stack;
frame.graph = 0;
#endif

walk_stackframe(tsk, &frame, save_trace, &data);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ unsigned long profile_pc(struct pt_regs *regs)
frame.fp = regs->regs[29];
frame.pc = regs->pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = current->curr_ret_stack;
frame.graph = 0;
#endif
do {
int ret = unwind_frame(NULL, &frame);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
frame.pc = thread_saved_pc(tsk);
}
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = tsk->curr_ret_stack;
frame.graph = 0;
#endif

skip = !!regs;
Expand Down
13 changes: 9 additions & 4 deletions arch/powerpc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -2061,9 +2061,10 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
int count = 0;
int firstframe = 1;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
int curr_frame = current->curr_ret_stack;
struct ftrace_ret_stack *ret_stack;
extern void return_to_handler(void);
unsigned long rth = (unsigned long)return_to_handler;
int curr_frame = 0;
#endif

sp = (unsigned long) stack;
Expand All @@ -2089,9 +2090,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if ((ip == rth) && curr_frame >= 0) {
pr_cont(" (%pS)",
(void *)current->ret_stack[curr_frame].ret);
curr_frame--;
ret_stack = ftrace_graph_get_ret_stack(current,
curr_frame++);
if (ret_stack)
pr_cont(" (%pS)",
(void *)ret_stack->ret);
else
curr_frame = -1;
}
#endif
if (firstframe)
Expand Down
11 changes: 7 additions & 4 deletions arch/sh/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,20 @@ print_ftrace_graph_addr(unsigned long addr, void *data,
struct thread_info *tinfo, int *graph)
{
struct task_struct *task = tinfo->task;
struct ftrace_ret_stack *ret_stack;
unsigned long ret_addr;
int index = task->curr_ret_stack;

if (addr != (unsigned long)return_to_handler)
return;

if (!task->ret_stack || index < *graph)
if (!task->ret_stack)
return;

index -= *graph;
ret_addr = task->ret_stack[index].ret;
ret_stack = ftrace_graph_get_ret_stack(task, *graph);
if (!ret_stack)
return;

ret_addr = ret_stack->ret;

ops->address(data, ret_addr, 1);

Expand Down
9 changes: 5 additions & 4 deletions arch/sh/kernel/dwarf.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,17 +605,18 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
* expected to find the real return address.
*/
if (pc == (unsigned long)&return_to_handler) {
int index = current->curr_ret_stack;
struct ftrace_ret_stack *ret_stack;

ret_stack = ftrace_graph_get_ret_stack(current, 0);
if (ret_stack)
pc = ret_stack->ret;
/*
* We currently have no way of tracking how many
* return_to_handler()'s we've seen. If there is more
* than one patched return address on our stack,
* complain loudly.
*/
WARN_ON(index > 0);

pc = current->ret_stack[index].ret;
WARN_ON(ftrace_graph_get_ret_stack(current, 1);
}
#endif

Expand Down
8 changes: 5 additions & 3 deletions arch/sparc/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1767,9 +1767,11 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
perf_callchain_store(entry, pc);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if ((pc + 8UL) == (unsigned long) &return_to_handler) {
int index = current->curr_ret_stack;
if (current->ret_stack && index >= graph) {
pc = current->ret_stack[index - graph].ret;
struct ftrace_ret_stack *ret_stack;
ret_stack = ftrace_graph_get_ret_stack(current,
graph);
if (ret_stack) {
pc = ret_stack->ret;
perf_callchain_store(entry, pc);
graph++;
}
Expand Down
8 changes: 5 additions & 3 deletions arch/sparc/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ static void __save_stack_trace(struct thread_info *tp,
trace->entries[trace->nr_entries++] = pc;
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if ((pc + 8UL) == (unsigned long) &return_to_handler) {
int index = t->curr_ret_stack;
if (t->ret_stack && index >= graph) {
pc = t->ret_stack[index - graph].ret;
struct ftrace_ret_stack *ret_stack;
ret_stack = ftrace_graph_get_ret_stack(t,
graph);
if (ret_stack) {
pc = ret_stack->ret;
if (trace->nr_entries <
trace->max_entries)
trace->entries[trace->nr_entries++] = pc;
Expand Down
7 changes: 4 additions & 3 deletions arch/sparc/kernel/traps_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -2502,9 +2502,10 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
printk(" [%016lx] %pS\n", pc, (void *) pc);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if ((pc + 8UL) == (unsigned long) &return_to_handler) {
int index = tsk->curr_ret_stack;
if (tsk->ret_stack && index >= graph) {
pc = tsk->ret_stack[index - graph].ret;
struct ftrace_ret_stack *ret_stack;
ret_stack = ftrace_graph_get_ret_stack(tsk, graph);
if (ret_stack) {
pc = ret_stack->ret;
printk(" [%016lx] %pS\n", pc, (void *) pc);
graph++;
}
Expand Down
41 changes: 22 additions & 19 deletions arch/x86/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,18 +733,20 @@ union ftrace_op_code_union {
} __attribute__((packed));
};

#define RET_SIZE 1

static unsigned long
create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
{
unsigned const char *jmp;
unsigned long start_offset;
unsigned long end_offset;
unsigned long op_offset;
unsigned long offset;
unsigned long size;
unsigned long ip;
unsigned long retq;
unsigned long *ptr;
void *trampoline;
void *ip;
/* 48 8b 15 <offset> is movq <offset>(%rip), %rdx */
unsigned const char op_ref[] = { 0x48, 0x8b, 0x15 };
union ftrace_op_code_union op_ptr;
Expand All @@ -764,27 +766,27 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)

/*
* Allocate enough size to store the ftrace_caller code,
* the jmp to ftrace_epilogue, as well as the address of
* the ftrace_ops this trampoline is used for.
* the iret , as well as the address of the ftrace_ops this
* trampoline is used for.
*/
trampoline = alloc_tramp(size + MCOUNT_INSN_SIZE + sizeof(void *));
trampoline = alloc_tramp(size + RET_SIZE + sizeof(void *));
if (!trampoline)
return 0;

*tramp_size = size + MCOUNT_INSN_SIZE + sizeof(void *);
*tramp_size = size + RET_SIZE + sizeof(void *);

/* Copy ftrace_caller onto the trampoline memory */
ret = probe_kernel_read(trampoline, (void *)start_offset, size);
if (WARN_ON(ret < 0)) {
tramp_free(trampoline, *tramp_size);
return 0;
}
if (WARN_ON(ret < 0))
goto fail;

ip = (unsigned long)trampoline + size;
ip = trampoline + size;

/* The trampoline ends with a jmp to ftrace_epilogue */
jmp = ftrace_jmp_replace(ip, (unsigned long)ftrace_epilogue);
memcpy(trampoline + size, jmp, MCOUNT_INSN_SIZE);
/* The trampoline ends with ret(q) */
retq = (unsigned long)ftrace_stub;
ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
if (WARN_ON(ret < 0))
goto fail;

/*
* The address of the ftrace_ops that is used for this trampoline
Expand All @@ -794,17 +796,15 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
* the global function_trace_op variable.
*/

ptr = (unsigned long *)(trampoline + size + MCOUNT_INSN_SIZE);
ptr = (unsigned long *)(trampoline + size + RET_SIZE);
*ptr = (unsigned long)ops;

op_offset -= start_offset;
memcpy(&op_ptr, trampoline + op_offset, OP_REF_SIZE);

/* Are we pointing to the reference? */
if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0)) {
tramp_free(trampoline, *tramp_size);
return 0;
}
if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0))
goto fail;

/* Load the contents of ptr into the callback parameter */
offset = (unsigned long)ptr;
Expand All @@ -819,6 +819,9 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;

return (unsigned long)trampoline;
fail:
tramp_free(trampoline, *tramp_size);
return 0;
}

static unsigned long calc_trampoline_call_offset(bool save_regs)
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/kernel/ftrace_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,6 @@ GLOBAL(ftrace_call)
restore_mcount_regs

/*
* The copied trampoline must call ftrace_epilogue as it
* still may need to call the function graph tracer.
*
* The code up to this label is copied into trampolines so
* think twice before adding any new code or changing the
* layout here.
Expand All @@ -185,7 +182,10 @@ GLOBAL(ftrace_graph_call)
jmp ftrace_stub
#endif

/* This is weak to keep gas from relaxing the jumps */
/*
* This is weak to keep gas from relaxing the jumps.
* It is also used to copy the retq for trampolines.
*/
WEAK(ftrace_stub)
retq
ENDPROC(ftrace_caller)
Expand Down
Loading

0 comments on commit 495d714

Please sign in to comment.