[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