Skip to content

Commit 334e551

Browse files
committed
tracing/probes: Add fprobe events for tracing function entry and exit.
Add fprobe events for tracing function entry and exit instead of kprobe events. With this change, we can continue to trace function entry/exit even if the CONFIG_KPROBES_ON_FTRACE is not available. Since CONFIG_KPROBES_ON_FTRACE requires the CONFIG_DYNAMIC_FTRACE_WITH_REGS, it is not available if the architecture only supports CONFIG_DYNAMIC_FTRACE_WITH_ARGS. And that means kprobe events can not probe function entry/exit effectively on such architecture. But this can be solved if the dynamic events supports fprobe events. The fprobe event is a new dynamic events which is only for the function (symbol) entry and exit. This event accepts non register fetch arguments so that user can trace the function arguments and return values. The fprobe events syntax is here; f[:[GRP/][EVENT]] FUNCTION [FETCHARGS] f[MAXACTIVE][:[GRP/][EVENT]] FUNCTION%return [FETCHARGS] E.g. # echo 'f vfs_read $arg1' >> dynamic_events # echo 'f vfs_read%return $retval' >> dynamic_events # cat dynamic_events f:fprobes/vfs_read__entry vfs_read arg1=$arg1 f:fprobes/vfs_read__exit vfs_read%return arg1=$retval # echo 1 > events/fprobes/enable # head -n 20 trace | tail # TASK-PID CPU# ||||| TIMESTAMP FUNCTION # | | | ||||| | | sh-142 [005] ...1. 448.386420: vfs_read__entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.386436: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 sh-142 [005] ...1. 448.386451: vfs_read__entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.386458: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 sh-142 [005] ...1. 448.386469: vfs_read__entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.386476: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 sh-142 [005] ...1. 448.602073: vfs_read__entry: (vfs_read+0x4/0x340) arg1=0xffff888007f7c540 sh-142 [005] ..... 448.602089: vfs_read__exit: (ksys_read+0x75/0x100 <- vfs_read) arg1=0x1 Link: https://lore.kernel.org/all/168507469754.913472.6112857614708350210.stgit@mhiramat.roam.corp.google.com/ Reported-by: kernel test robot <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent 30460c2 commit 334e551

File tree

12 files changed

+1109
-8
lines changed

12 files changed

+1109
-8
lines changed

include/linux/fprobe.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter
6666
int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num);
6767
int register_fprobe_syms(struct fprobe *fp, const char **syms, int num);
6868
int unregister_fprobe(struct fprobe *fp);
69+
bool fprobe_is_registered(struct fprobe *fp);
6970
#else
7071
static inline int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter)
7172
{
@@ -83,6 +84,10 @@ static inline int unregister_fprobe(struct fprobe *fp)
8384
{
8485
return -EOPNOTSUPP;
8586
}
87+
static inline bool fprobe_is_registered(struct fprobe *fp)
88+
{
89+
return false;
90+
}
8691
#endif
8792

8893
/**

include/linux/trace_events.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ enum {
318318
TRACE_EVENT_FL_KPROBE_BIT,
319319
TRACE_EVENT_FL_UPROBE_BIT,
320320
TRACE_EVENT_FL_EPROBE_BIT,
321+
TRACE_EVENT_FL_FPROBE_BIT,
321322
TRACE_EVENT_FL_CUSTOM_BIT,
322323
};
323324

@@ -332,6 +333,7 @@ enum {
332333
* KPROBE - Event is a kprobe
333334
* UPROBE - Event is a uprobe
334335
* EPROBE - Event is an event probe
336+
* FPROBE - Event is an function probe
335337
* CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint)
336338
* This is set when the custom event has not been attached
337339
* to a tracepoint yet, then it is cleared when it is.
@@ -346,6 +348,7 @@ enum {
346348
TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
347349
TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
348350
TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT),
351+
TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT),
349352
TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT),
350353
};
351354

kernel/trace/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,20 @@ config BLK_DEV_IO_TRACE
650650

651651
If unsure, say N.
652652

653+
config FPROBE_EVENTS
654+
depends on FPROBE
655+
depends on HAVE_REGS_AND_STACK_ACCESS_API
656+
bool "Enable fprobe-based dynamic events"
657+
select TRACING
658+
select PROBE_EVENTS
659+
select DYNAMIC_EVENTS
660+
default y
661+
help
662+
This allows user to add tracing events on the function entry and
663+
exit via ftrace interface. The syntax is same as the kprobe events
664+
and the kprobe events on function entry and exit will be
665+
transparently converted to this fprobe events.
666+
653667
config KPROBE_EVENTS
654668
depends on KPROBES
655669
depends on HAVE_REGS_AND_STACK_ACCESS_API

kernel/trace/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ obj-$(CONFIG_BOOTTIME_TRACING) += trace_boot.o
104104
obj-$(CONFIG_FTRACE_RECORD_RECURSION) += trace_recursion_record.o
105105
obj-$(CONFIG_FPROBE) += fprobe.o
106106
obj-$(CONFIG_RETHOOK) += rethook.o
107+
obj-$(CONFIG_FPROBE_EVENTS) += trace_fprobe.o
107108

108109
obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o
109110
obj-$(CONFIG_RV) += rv/

kernel/trace/fprobe.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,14 @@ int register_fprobe_syms(struct fprobe *fp, const char **syms, int num)
348348
}
349349
EXPORT_SYMBOL_GPL(register_fprobe_syms);
350350

351+
bool fprobe_is_registered(struct fprobe *fp)
352+
{
353+
if (!fp || (fp->ops.saved_func != fprobe_handler &&
354+
fp->ops.saved_func != fprobe_kprobe_handler))
355+
return false;
356+
return true;
357+
}
358+
351359
/**
352360
* unregister_fprobe() - Unregister fprobe from ftrace
353361
* @fp: A fprobe data structure to be unregistered.
@@ -360,8 +368,7 @@ int unregister_fprobe(struct fprobe *fp)
360368
{
361369
int ret;
362370

363-
if (!fp || (fp->ops.saved_func != fprobe_handler &&
364-
fp->ops.saved_func != fprobe_kprobe_handler))
371+
if (!fprobe_is_registered(fp))
365372
return -EINVAL;
366373

367374
/*

kernel/trace/trace.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5672,10 +5672,16 @@ static const char readme_msg[] =
56725672
" uprobe_events\t\t- Create/append/remove/show the userspace dynamic events\n"
56735673
"\t\t\t Write into this file to define/undefine new trace events.\n"
56745674
#endif
5675-
#if defined(CONFIG_KPROBE_EVENTS) || defined(CONFIG_UPROBE_EVENTS)
5675+
#if defined(CONFIG_KPROBE_EVENTS) || defined(CONFIG_UPROBE_EVENTS) || \
5676+
defined(CONFIG_FPROBE_EVENTS)
56765677
"\t accepts: event-definitions (one definition per line)\n"
5678+
#if defined(CONFIG_KPROBE_EVENTS) || defined(CONFIG_UPROBE_EVENTS)
56775679
"\t Format: p[:[<group>/][<event>]] <place> [<args>]\n"
56785680
"\t r[maxactive][:[<group>/][<event>]] <place> [<args>]\n"
5681+
#endif
5682+
#ifdef CONFIG_FPROBE_EVENTS
5683+
"\t f[:[<group>/][<event>]] <func-name>[%return] [<args>]\n"
5684+
#endif
56795685
#ifdef CONFIG_HIST_TRIGGERS
56805686
"\t s:[synthetic/]<event> <field> [<field>]\n"
56815687
#endif

kernel/trace/trace.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,17 @@ struct kretprobe_trace_entry_head {
148148
unsigned long ret_ip;
149149
};
150150

151+
struct fentry_trace_entry_head {
152+
struct trace_entry ent;
153+
unsigned long ip;
154+
};
155+
156+
struct fexit_trace_entry_head {
157+
struct trace_entry ent;
158+
unsigned long func;
159+
unsigned long ret_ip;
160+
};
161+
151162
#define TRACE_BUF_SIZE 1024
152163

153164
struct trace_array;

0 commit comments

Comments
 (0)