Skip to content

Commit

Permalink
tracing/fprobe: Support raw tracepoint events on modules
Browse files Browse the repository at this point in the history
Support raw tracepoint event on module by fprobe events.
Since it only uses for_each_kernel_tracepoint() to find a tracepoint,
the tracepoints on modules are not handled. Thus if user specified a
tracepoint on a module, it shows an error.
This adds new for_each_module_tracepoint() API to tracepoint subsystem,
and uses it to find tracepoints on modules.

Link: https://lore.kernel.org/all/172397779651.286558.15903703620679186867.stgit@devnote2/

Reported-by: don <zds100@gmail.com>
Closes: https://lore.kernel.org/all/20240530215718.aeec973a1d0bf058d39cb1e3@kernel.org/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
  • Loading branch information
Masami Hiramatsu (Google) committed Sep 25, 2024
1 parent d4df54f commit 67e9a9e
Showing 1 changed file with 38 additions and 8 deletions.
46 changes: 38 additions & 8 deletions kernel/trace/trace_fprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
const char *event,
const char *symbol,
struct tracepoint *tpoint,
struct module *mod,
int maxactive,
int nargs, bool is_return)
{
Expand All @@ -405,6 +406,7 @@ static struct trace_fprobe *alloc_trace_fprobe(const char *group,
tf->fp.entry_handler = fentry_dispatcher;

tf->tpoint = tpoint;
tf->mod = mod;
tf->fp.nr_maxactive = maxactive;

ret = trace_probe_init(&tf->tp, event, group, false, nargs);
Expand Down Expand Up @@ -895,8 +897,23 @@ static struct notifier_block tracepoint_module_nb = {
struct __find_tracepoint_cb_data {
const char *tp_name;
struct tracepoint *tpoint;
struct module *mod;
};

static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mod, void *priv)
{
struct __find_tracepoint_cb_data *data = priv;

if (!data->tpoint && !strcmp(data->tp_name, tp->name)) {
data->tpoint = tp;
data->mod = mod;
if (!try_module_get(data->mod)) {
data->tpoint = NULL;
data->mod = NULL;
}
}
}

static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
{
struct __find_tracepoint_cb_data *data = priv;
Expand All @@ -905,14 +922,28 @@ static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
data->tpoint = tp;
}

static struct tracepoint *find_tracepoint(const char *tp_name)
/*
* Find a tracepoint from kernel and module. If the tracepoint is in a module,
* this increments the module refcount to prevent unloading until the
* trace_fprobe is registered to the list. After registering the trace_fprobe
* on the trace_fprobe list, the module refcount is decremented because
* tracepoint_probe_module_cb will handle it.
*/
static struct tracepoint *find_tracepoint(const char *tp_name,
struct module **tp_mod)
{
struct __find_tracepoint_cb_data data = {
.tp_name = tp_name,
.mod = NULL,
};

for_each_kernel_tracepoint(__find_tracepoint_cb, &data);

if (!data.tpoint && IS_ENABLED(CONFIG_MODULES)) {
for_each_module_tracepoint(__find_tracepoint_module_cb, &data);
*tp_mod = data.mod;
}

return data.tpoint;
}

Expand Down Expand Up @@ -996,6 +1027,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
char abuf[MAX_BTF_ARGS_LEN];
char *dbuf = NULL;
bool is_tracepoint = false;
struct module *tp_mod = NULL;
struct tracepoint *tpoint = NULL;
struct traceprobe_parse_context ctx = {
.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
Expand Down Expand Up @@ -1080,7 +1112,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])

if (is_tracepoint) {
ctx.flags |= TPARG_FL_TPOINT;
tpoint = find_tracepoint(symbol);
tpoint = find_tracepoint(symbol, &tp_mod);
if (!tpoint) {
trace_probe_log_set_index(1);
trace_probe_log_err(0, NO_TRACEPOINT);
Expand Down Expand Up @@ -1110,19 +1142,15 @@ static int __trace_fprobe_create(int argc, const char *argv[])
goto out;

/* setup a probe */
tf = alloc_trace_fprobe(group, event, symbol, tpoint, maxactive,
argc, is_return);
tf = alloc_trace_fprobe(group, event, symbol, tpoint, tp_mod,
maxactive, argc, is_return);
if (IS_ERR(tf)) {
ret = PTR_ERR(tf);
/* This must return -ENOMEM, else there is a bug */
WARN_ON_ONCE(ret != -ENOMEM);
goto out; /* We know tf is not allocated */
}

if (is_tracepoint)
tf->mod = __module_text_address(
(unsigned long)tf->tpoint->probestub);

/* parse arguments */
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
trace_probe_log_set_index(i + 2);
Expand Down Expand Up @@ -1155,6 +1183,8 @@ static int __trace_fprobe_create(int argc, const char *argv[])
}

out:
if (tp_mod)
module_put(tp_mod);
traceprobe_finish_parse(&ctx);
trace_probe_log_clear();
kfree(new_argv);
Expand Down

0 comments on commit 67e9a9e

Please sign in to comment.