[DTrace-devel] [PATCH dtrace 1/3] dtrace: add support for probe-specific prog types, stack skips

Alan Maguire alan.maguire at oracle.com
Wed Oct 9 14:02:34 UTC 2024


Because fprobe-based tracing does not support all the functions
kprobes+available_filter_functions do, it would be useful to
fall back to a kprobe-based prog where fentry/fexit is not
feasible.

However there are a few blockers to that today.

First, we specify program type and number of stack frames to
skip on a provider basis.  Add support for a probe-specific
callback function that provider implementations can use
to return these values.

Secondly, the tp event id is ambiguous - it can represent a BTF
or a trace event id.  Add a field to allow specification, as
this will be useful in determining whether a probe has a kprobe
or a BTF (fentry/fexit)-based attachment.  This can be used
in provider implementation methods to determine which trampoline
to use for example.

Signed-off-by: Alan Maguire <alan.maguire at oracle.com>
---
 libdtrace/dt_bpf.c         |  4 ++--
 libdtrace/dt_cc.c          |  2 +-
 libdtrace/dt_probe.c       | 16 ++++++++++++++++
 libdtrace/dt_probe.h       |  2 ++
 libdtrace/dt_prov_fbt.c    |  2 +-
 libdtrace/dt_prov_rawtp.c  |  2 +-
 libdtrace/dt_prov_sdt.c    |  2 +-
 libdtrace/dt_provider.h    |  4 ++++
 libdtrace/dt_provider_tp.c | 12 +++++++++++-
 libdtrace/dt_provider_tp.h |  9 +++++++--
 10 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index ad11d178..20b564aa 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -117,7 +117,7 @@ int
 dt_bpf_prog_load(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		 const dtrace_difo_t *dp, uint32_t lvl, char *buf, size_t sz)
 {
-	return dt_bpf_prog_attach(prp->prov->impl->prog_type, 0, 0, 0, dp,
+	return dt_bpf_prog_attach(dt_probe_prog_type(dtp, prp), 0, 0, 0, dp,
 				  lvl, buf, sz);
 }
 
@@ -1226,7 +1226,7 @@ dt_bpf_make_progs(dtrace_hdl_t *dtp, uint_t cflags)
 		 * Enabled probes with no trampoline act like they exist but
 		 * no code is generated for them.
 		 */
-		if (prp->prov->impl->prog_type == BPF_PROG_TYPE_UNSPEC)
+		if (dt_probe_prog_type(dtp, prp) == BPF_PROG_TYPE_UNSPEC)
 			continue;
 
 		dp = dt_construct(dtp, prp, cflags, NULL);
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index 4202771a..ce0fd60b 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -1182,7 +1182,7 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
 				nrp->dofr_data = DMEM_STACK(dtp);
 				continue;
 			case DT_CONST_STACK_SKIP:
-				nrp->dofr_data = prp->prov->impl->stack_skip;
+				nrp->dofr_data = dt_probe_stack_skip(dtp, prp);
 				continue;
 			}
 
diff --git a/libdtrace/dt_probe.c b/libdtrace/dt_probe.c
index 686e2a66..4be7a81c 100644
--- a/libdtrace/dt_probe.c
+++ b/libdtrace/dt_probe.c
@@ -1378,3 +1378,19 @@ dtrace_id2desc(dtrace_hdl_t *dtp, dtrace_id_t id, dtrace_probedesc_t *pdp)
 
         return 0;
 }
+
+int
+dt_probe_prog_type(dtrace_hdl_t *dtp, const dt_probe_t *prp)
+{
+	if (prp->prov->impl->get_prog_type)
+		return prp->prov->impl->get_prog_type(dtp, prp);
+	return prp->prov->impl->prog_type;
+}
+
+int
+dt_probe_stack_skip(dtrace_hdl_t *dtp, const dt_probe_t *prp)
+{
+	if (prp->prov->impl->get_stack_skip)
+		return prp->prov->impl->get_stack_skip(dtp, prp);
+	return prp->prov->impl->stack_skip;
+}
diff --git a/libdtrace/dt_probe.h b/libdtrace/dt_probe.h
index 2a78cb9c..03bac787 100644
--- a/libdtrace/dt_probe.h
+++ b/libdtrace/dt_probe.h
@@ -103,6 +103,8 @@ extern void dt_probe_init(dtrace_hdl_t *dtp);
 extern void dt_probe_detach_all(dtrace_hdl_t *dtp);
 extern void dt_probe_fini(dtrace_hdl_t *dtp);
 extern void dt_probe_stats(dtrace_hdl_t *dtp);
+extern int dt_probe_prog_type(dtrace_hdl_t *, const dt_probe_t *);
+extern int dt_probe_stack_skip(dtrace_hdl_t *, const dt_probe_t *);
 
 #ifdef	__cplusplus
 }
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index 21f63ddf..718aadbe 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -239,7 +239,7 @@ static int fprobe_probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	if (btf_id <= 0)
 		goto done;
 
-	dt_tp_set_event_id(prp, btf_id);
+	dt_tp_set_event_id(prp, btf_id, TP_EVENT_ID_BTF);
 
 	if (strcmp(desc->prb, "return") == 0) {
 		/* Void function return probes only provide 1 argument. */
diff --git a/libdtrace/dt_prov_rawtp.c b/libdtrace/dt_prov_rawtp.c
index 778a6f9c..22a18050 100644
--- a/libdtrace/dt_prov_rawtp.c
+++ b/libdtrace/dt_prov_rawtp.c
@@ -221,7 +221,7 @@ done:
 static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		      int *argcp, dt_argdesc_t **argvp)
 {
-	dt_tp_set_event_id(prp, UINT32_MAX);
+	dt_tp_set_event_id(prp, UINT32_MAX, TP_EVENT_ID_TRACEPOINT);
 
 #ifdef HAVE_LIBCTF
 	int			rc, i;
diff --git a/libdtrace/dt_prov_sdt.c b/libdtrace/dt_prov_sdt.c
index 675e0458..8d43282a 100644
--- a/libdtrace/dt_prov_sdt.c
+++ b/libdtrace/dt_prov_sdt.c
@@ -241,7 +241,7 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	if (rc < 0 || id == 0)
 		return dt_set_errno(dtp, EDT_ENABLING_ERR);
 
-	dt_tp_set_event_id(prp, id);
+	dt_tp_set_event_id(prp, id, TP_EVENT_ID_TRACEPOINT);
 
 	if (asprintf(&str, "struct trace_event_raw_%s", prp->desc->prb) == -1)
 		return dt_set_errno(dtp, EDT_NOMEM);
diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
index 17b1844c..724d72d7 100644
--- a/libdtrace/dt_provider.h
+++ b/libdtrace/dt_provider.h
@@ -44,7 +44,11 @@ typedef struct dt_argdesc {
 typedef struct dt_provimpl {
 	const char *name;			/* provider generic name */
 	int prog_type;				/* BPF program type */
+	int (*get_prog_type)(dtrace_hdl_t *dtp, /* probe-specific type */
+			     const struct dt_probe *prp);
 	uint32_t stack_skip;			/* # of stack frames to skip */
+	int (*get_stack_skip)(dtrace_hdl_t *dtp,/* probe-specific # */
+			      const struct dt_probe *prp);
 	int (*populate)(dtrace_hdl_t *dtp);	/* register probes */
 	int (*provide)(dtrace_hdl_t *dtp,	/* provide probes */
 		       const dtrace_probedesc_t *pdp);
diff --git a/libdtrace/dt_provider_tp.c b/libdtrace/dt_provider_tp.c
index 50df2328..f8e68f24 100644
--- a/libdtrace/dt_provider_tp.c
+++ b/libdtrace/dt_provider_tp.c
@@ -33,6 +33,7 @@
 struct tp_probe {
 	uint32_t	event_id;	/* tracepoint event id or BTF id */
 	int		event_fd;	/* tracepoint perf event fd */
+	tp_event_id_type event_type;	/* tracepoint event or BTF-based */
 };
 
 /*
@@ -342,12 +343,21 @@ dt_tp_get_event_id(const dt_probe_t *prp)
 	return tpp->event_id;
 }
 
+tp_event_id_type
+dt_tp_get_event_id_type(const dt_probe_t *prp)
+{
+	tp_probe_t	*tpp = prp->prv_data;
+
+	return tpp->event_type;
+}
+
 void
-dt_tp_set_event_id(const dt_probe_t *prp, uint32_t id)
+dt_tp_set_event_id(const dt_probe_t *prp, uint32_t id, tp_event_id_type type)
 {
 	tp_probe_t	*tpp = prp->prv_data;
 
 	tpp->event_id = id;
+	tpp->event_type = type;
 }
 
 /*
diff --git a/libdtrace/dt_provider_tp.h b/libdtrace/dt_provider_tp.h
index e7d52876..09002fa8 100644
--- a/libdtrace/dt_provider_tp.h
+++ b/libdtrace/dt_provider_tp.h
@@ -28,9 +28,14 @@ extern "C" {
 
 typedef struct tp_probe tp_probe_t;
 
+typedef enum {
+	TP_EVENT_ID_TRACEPOINT = 0,
+	TP_EVENT_ID_BTF
+} tp_event_id_type;
+
 extern tp_probe_t *dt_tp_alloc(dtrace_hdl_t *dtp);
 extern int dt_tp_attach(dtrace_hdl_t *dtp, tp_probe_t *tpp, int bpf_fd);
-extern void dt_tp_set_event_id(const struct dt_probe *prp, uint32_t id);
+extern void dt_tp_set_event_id(const struct dt_probe *prp, uint32_t id, tp_event_id_type);
 extern int dt_tp_has_info(const tp_probe_t *tpp);
 extern int dt_tp_event_info(dtrace_hdl_t *dtp, FILE *f, int skip,
 			    tp_probe_t *tpp, int *argcp, dt_argdesc_t **argvp);
@@ -42,7 +47,7 @@ extern struct dt_probe *dt_tp_probe_insert(dtrace_hdl_t *dtp,
 					   const char *prv, const char *mod,
 					   const char *fun, const char *prb);
 extern uint32_t dt_tp_get_event_id(const struct dt_probe *prp);
-extern void dt_tp_set_event_id(const struct dt_probe *prp, uint32_t id);
+extern tp_event_id_type dt_tp_get_event_id_type(const struct dt_probe *prp);
 extern int dt_tp_probe_info(dtrace_hdl_t *dtp, FILE *f, int skip,
 			    const struct dt_probe *prp, int *argcp,
 			    dt_argdesc_t **argvp);
-- 
2.43.5




More information about the DTrace-devel mailing list