[DTrace-devel] [PATCH v3 dtrace 2/4] fbt: support "."-suffixed functions for kprobes
Alan Maguire
alan.maguire at oracle.com
Wed Oct 16 15:54:07 UTC 2024
gcc adds suffixes when it carries out optimizations, but often
these leave parameters to functions intact. Many of these functions
(like finish_task_switch()) are important for tracing (and they
are present in available_filter_functions so are traceable) so it is
valuable to support probing them. For kprobes, the probe name removes
the "." suffix, so store it as additional tp event data for kprobe
attach (attach time is the only time we need the full function name).
fprobe does not support such functions, so the kprobe impl is always
used in such cases.
Signed-off-by: Alan Maguire <alan.maguire at oracle.com>
---
libdtrace/dt_prov_fbt.c | 76 ++++++++++++++++++++++++++++++++---------
1 file changed, 59 insertions(+), 17 deletions(-)
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index 21f63ddf..06ea78ca 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <port.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -63,8 +64,8 @@ static const dtrace_pattr_t pattr = {
*/
static int populate(dtrace_hdl_t *dtp)
{
- dt_provider_t *prv;
- dt_provimpl_t *impl;
+ dt_provider_t *default_prv, *kprobe_prv = NULL;
+ dt_provimpl_t *default_impl;
FILE *f;
char *buf = NULL;
char *p;
@@ -73,17 +74,25 @@ static int populate(dtrace_hdl_t *dtp)
dtrace_syminfo_t sip;
dtrace_probedesc_t pd;
- impl = BPF_HAS(dtp, BPF_FEAT_FENTRY) ? &dt_fbt_fprobe : &dt_fbt_kprobe;
+ default_impl = BPF_HAS(dtp, BPF_FEAT_FENTRY) ? &dt_fbt_fprobe : &dt_fbt_kprobe;
- prv = dt_provider_create(dtp, prvname, impl, &pattr, NULL);
- if (prv == NULL)
+ default_prv = dt_provider_create(dtp, prvname, default_impl, &pattr, NULL);
+ if (default_prv == NULL)
return -1; /* errno already set */
+ if (default_impl == &dt_fbt_kprobe)
+ kprobe_prv = default_prv;
f = fopen(PROBE_LIST, "r");
if (f == NULL)
return 0;
while (getline(&buf, &n, f) >= 0) {
+ dt_provimpl_t *impl = default_impl;
+ dt_provider_t *prv = default_prv;
+ char fun[DTRACE_FUNCNAMELEN] = {};
+ void *entry_data = NULL;
+ void *return_data = NULL;
+
/*
* Here buf is either "funcname\n" or "funcname [modname]\n".
* The last line may not have a linefeed.
@@ -106,10 +115,6 @@ static int populate(dtrace_hdl_t *dtp)
p++;
}
- /* Weed out synthetic symbol names (that are invalid). */
- if (strchr(buf, '.') != NULL)
- continue;
-
#define strstarts(var, x) (strncmp(var, x, strlen (x)) == 0)
/* Weed out __ftrace_invalid_address___* entries. */
if (strstarts(buf, "__ftrace_invalid_address__") ||
@@ -129,6 +134,31 @@ static int populate(dtrace_hdl_t *dtp)
} else
mod = p;
+ /* '.'-suffixed functions (e.g. foo.isra.0) must always be
+ * kprobe-backed as fprobe does not support them. They
+ * are represented with their unsuffixed names however, so
+ * the full name including suffix is stored as data associated
+ * with the tp event.
+ */
+ strlcpy(fun, buf, sizeof(fun));
+ if (strchr(buf, '.') != NULL) {
+ char *suffix;
+
+ impl = &dt_fbt_kprobe;
+ if (!kprobe_prv) {
+ kprobe_prv = dt_provider_create(dtp, prvname,
+ impl, &pattr,
+ NULL);
+ if (kprobe_prv == NULL)
+ return -1;
+ }
+ prv = kprobe_prv;
+ suffix = strchr(fun, '.');
+ *suffix = '\0';
+ entry_data = strdup(buf);
+ return_data = strdup(buf);
+ }
+
/*
* Due to the lack of module names in
* TRACEFS/available_filter_functions, there are some duplicate
@@ -138,14 +168,16 @@ static int populate(dtrace_hdl_t *dtp)
pd.id = DTRACE_IDNONE;
pd.prv = prvname;
pd.mod = mod;
- pd.fun = buf;
+ pd.fun = fun;
pd.prb = "entry";
if (dt_probe_lookup(dtp, &pd) != NULL)
continue;
- if (dt_tp_probe_insert(dtp, prv, prvname, mod, buf, "entry"))
+ if (dt_tp_probe_insert_data(dtp, prv, prvname, mod, fun,
+ "entry", entry_data))
n++;
- if (dt_tp_probe_insert(dtp, prv, prvname, mod, buf, "return"))
+ if (dt_tp_probe_insert_data(dtp, prv, prvname, mod, fun,
+ "return", return_data))
n++;
}
@@ -363,10 +395,11 @@ static int kprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
{
if (!dt_tp_probe_has_info(prp)) {
- char *fn;
- FILE *f;
- size_t len;
- int fd, rc = -1;
+ char *fn;
+ const char *fun;
+ FILE *f;
+ size_t len;
+ int fd, rc = -1;
/*
* Register the kprobe with the tracing subsystem. This will
@@ -376,9 +409,18 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
if (fd == -1)
return -ENOENT;
+ /* If actual function name contained a '.', it is stored in
+ * tp data; use non-suffix name for event as event names
+ * cannot contain a '.'. User-visible probe name does
+ * not contain a '.'.
+ */
+ fun = dt_tp_get_event_data(prp);
+ if (!fun)
+ fun = prp->desc->fun;
+
rc = dprintf(fd, "%c:" FBT_GROUP_FMT "/%s %s\n",
prp->desc->prb[0] == 'e' ? 'p' : 'r',
- FBT_GROUP_DATA, prp->desc->fun, prp->desc->fun);
+ FBT_GROUP_DATA, prp->desc->fun, fun);
close(fd);
if (rc == -1)
return -ENOENT;
--
2.43.5
More information about the DTrace-devel
mailing list