[DTrace-devel] [PATCH 1/6] Deferred attach of underlying USDT probes
eugene.loh at oracle.com
eugene.loh at oracle.com
Sat Sep 28 02:21:53 UTC 2024
From: Eugene Loh <eugene.loh at oracle.com>
We would like dtrace to trace USDT processes that start
even after the dtrace session has been launched. In that
case, the underlying probe cannot be attached when dtrace
starts up; rather, the BPF program must be attached once
the USDT process has been detected.
Therefore:
*) Make dt_bpf_load_prog() callable outside of dt_bpf.c.
*) Have update_uprobe() call dt_construct(), dt_link(),
dt_bpf_load_prog(), and attach() for any new underlying
probes.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_bpf.c | 2 +-
libdtrace/dt_bpf.h | 3 ++
libdtrace/dt_prov_uprobe.c | 65 ++++++++++++++++++++++++++++++++++++--
3 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 90881e398..ab97be2cf 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -1134,7 +1134,7 @@ dt_bpf_reloc_prog(dtrace_hdl_t *dtp, const dtrace_difo_t *dp)
*
* Note that DTrace generates BPF programs that are licensed under the GPL.
*/
-static int
+int
dt_bpf_load_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
const dtrace_difo_t *dp, uint_t cflags)
{
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index 5716d2320..115adfbf0 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -14,6 +14,7 @@
#include <dtrace/difo.h>
#include <dt_btf.h>
#include <dt_impl.h>
+#include <dt_probe.h>
struct dtrace_hdl;
@@ -88,6 +89,8 @@ extern int dt_bpf_prog_load(struct dtrace_hdl *, const struct dt_probe *prp,
size_t sz);
extern int dt_bpf_raw_tracepoint_open(const void *tp, int fd);
extern int dt_bpf_make_progs(struct dtrace_hdl *, uint_t);
+extern int dt_bpf_load_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
+ const dtrace_difo_t *dp, uint_t cflags);
extern int dt_bpf_load_progs(struct dtrace_hdl *, uint_t);
extern void dt_bpf_init(struct dtrace_hdl *dtp);
diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index cf0a95fba..8fda85532 100644
--- a/libdtrace/dt_prov_uprobe.c
+++ b/libdtrace/dt_prov_uprobe.c
@@ -309,6 +309,10 @@ static int update_uprobe(dtrace_hdl_t *dtp, void *datap)
int i, prid = dtp->dt_probe_id;
uint_t old_strlen = dtp->dt_strlen;
dt_pcb_t pcb;
+ dtrace_optval_t dest_ok = DTRACEOPT_UNSET;
+
+ /* Determine whether destructive actions are okay. */
+ dtrace_getopt(dtp, "destructive", &dest_ok);
/* Clear stale pids. */
purge_BPFmap(dtp);
@@ -364,6 +368,61 @@ static int update_uprobe(dtrace_hdl_t *dtp, void *datap)
prp_next = dt_list_next(prp);
+ /* Handle underlying probe. */
+ if (prp->prov->impl == &dt_uprobe) {
+ dtrace_difo_t *dp;
+ int cflags, fd, rc = -1;
+
+ /*
+ * Strictly speaking, we want the value passed in to
+ * dtrace_go(). In practice, its flags pertain to
+ * compilation and disassembly, which at this stage
+ * no longer interest us.
+ */
+ cflags = 0;
+
+ /* Check if the probe is already set up. */
+ if (prp->difo)
+ continue;
+
+ /* Make program. */
+ dp = dt_construct(dtp, prp, cflags, NULL);
+ if (dp == NULL)
+ continue; // FIXME in dt_bpf_make_progs() this is a fatal error; should we do the same here?
+ prp->difo = dp;
+
+ /* Load program. */
+ if (dt_link(dtp, prp, dp, NULL) == -1)
+ continue; // FIXME in dt_bpf_load_progs() this is a fatal error; should we do the same here?
+ if (dp->dtdo_flags & DIFOFLG_DESTRUCTIVE &&
+ dest_ok == DTRACEOPT_UNSET)
+ return dt_set_errno(dtp, EDT_DESTRUCTIVE);
+
+ fd = dt_bpf_load_prog(dtp, prp, dp, cflags);
+ if (fd == -1)
+ continue; // FIXME in dt_bpf_load_progs() this is a fatal error; should we do the same here?
+
+ if (prp->prov->impl->attach)
+ rc = prp->prov->impl->attach(dtp, prp, fd);
+
+ if (rc == -ENOTSUPP) {
+ char *s;
+
+ close(fd);
+ if (asprintf(&s, "Failed to enable %s:%s:%s:%s",
+ prp->desc->prv, prp->desc->mod,
+ prp->desc->fun, prp->desc->prb) == -1)
+ return dt_set_errno(dtp, EDT_ENABLING_ERR);
+ dt_handle_rawerr(dtp, s);
+ free(s);
+ } else if (rc < 0) {
+ close(fd);
+ return dt_set_errno(dtp, EDT_ENABLING_ERR);
+ }
+
+ continue;
+ }
+
/* Make sure it is an overlying USDT probe. */
if (prp->prov->impl != &dt_usdt)
continue;
@@ -454,9 +513,11 @@ static int update_uprobe(dtrace_hdl_t *dtp, void *datap)
dt_bpf_map_update(dtp->dt_usdt_pridsmap_fd, &key, &val);
} else if (val.prid != oval.prid || val.mask != oval.mask) {
/*
- * This can happen when two overlying probes map to the same underlying probe for the same pid.
- * E.g., pid:::entry and pid:::0, or pid:::$offset and usdt:::.
+ * Two different USDT probes should never map to the same
+ * underlying probe for the same pid. Nor should the bit
+ * mask ever change.
*/
+ assert(0);
} else {
/*
* Nothing to do, it already is in the map.
--
2.43.5
More information about the DTrace-devel
mailing list