[DTrace-devel] [PATCH dtrace 2/3] fbt: support ".isra.0" suffixed functions

Alan Maguire alan.maguire at oracle.com
Wed Oct 9 14:02:35 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, all that is needed
is to ensure that the event name does not contain a ".".

For fprobes the situation is more complex - the function may be
in BTF, but even if it is, its BTF representation does not have
a "." suffix so searching kallsyms based on the BTF name fails.
As a result it is desirable to fall back to using kprobes for
such cases.  Implement fallbacks in the fprobe provider methods
which use kprobe trampoline, attachment etc to cover these cases.
Having callback functions for stack size/prog type allows us to
dynamically determine these values on a per-probe basis.

Signed-off-by: Alan Maguire <alan.maguire at oracle.com>
---
 libdtrace/dt_prov_fbt.c | 82 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 69 insertions(+), 13 deletions(-)

diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index 718aadbe..a7c2627a 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -57,6 +57,10 @@ static const dtrace_pattr_t	pattr = {
 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
 };
 
+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);
+static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp);
+
 /*
  * Scan the PROBE_LIST file and add entry and return probes for every function
  * that is listed.
@@ -106,10 +110,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__") ||
@@ -176,6 +176,10 @@ static int fprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 	dt_irlist_t	*dlp = &pcb->pcb_ir;
 	dt_probe_t	*prp = pcb->pcb_probe;
 
+	/* legacy kprobe fallback? */
+	if (dt_tp_get_event_id_type(prp) == TP_EVENT_ID_TRACEPOINT)
+		return kprobe_trampoline(pcb, exitlbl);
+
 	dt_cg_tramp_prologue(pcb);
 
 	if (strcmp(pcb->pcb_probe->desc->prb, "entry") == 0) {
@@ -236,8 +240,12 @@ static int fprobe_probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 
 	btf_id = dt_btf_lookup_name_kind(dtp, dmp->dm_btf, desc->fun,
 					 BTF_KIND_FUNC);
-	if (btf_id <= 0)
+	if (btf_id <= 0) {
+		/* No BTF info, we will fall back to kprobe */
+		if (btf_id == -ENOENT)
+			return 0;
 		goto done;
+	}
 
 	dt_tp_set_event_id(prp, btf_id, TP_EVENT_ID_BTF);
 
@@ -294,6 +302,10 @@ static int fprobe_prog_load(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	const dtrace_probedesc_t	*desc = prp->desc;
 	dt_module_t			*dmp;
 
+	/* legacy kprobe fallback? */
+	if (dt_tp_get_event_id_type(prp) == TP_EVENT_ID_TRACEPOINT)
+		return dt_bpf_prog_load(dtp, prp, dp, lvl, buf, sz);
+
 	atype = strcmp(desc->prb, "entry") == 0 ? BPF_TRACE_FENTRY
 						: BPF_TRACE_FEXIT;
 
@@ -312,6 +324,34 @@ static int fprobe_prog_load(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	return rc;
 }
 
+static int fprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
+{
+	if (dt_tp_get_event_id_type(prp) == TP_EVENT_ID_TRACEPOINT)
+		return kprobe_attach(dtp, prp, bpf_fd);
+	return dt_tp_probe_attach_raw(dtp, prp, bpf_fd);
+}
+
+static void fprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
+{
+	if (dt_tp_get_event_id_type(prp) == TP_EVENT_ID_TRACEPOINT)
+		return kprobe_detach(dtp, prp);
+	return dt_tp_probe_detach(dtp, prp);
+}
+
+static int fprobe_prog_type(dtrace_hdl_t *dtp, const dt_probe_t *prp)
+{
+	if (dt_tp_get_event_id_type(prp) == TP_EVENT_ID_TRACEPOINT)
+		return BPF_PROG_TYPE_KPROBE;
+	return BPF_PROG_TYPE_TRACING;
+}
+
+static int fprobe_stack_skip(dtrace_hdl_t *dtp, const dt_probe_t *prp)
+{
+	if (dt_tp_get_event_id_type(prp) == TP_EVENT_ID_TRACEPOINT)
+		return 0;
+	return 4;
+}
+
 /*******************************\
  * KPROBE-based implementation *
 \*******************************/
@@ -363,7 +403,7 @@ 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;
+		char	*fn, *fun, *suffix;
 		FILE	*f;
 		size_t	len;
 		int	fd, rc = -1;
@@ -376,22 +416,36 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 		if (fd == -1)
 			return -ENOENT;
 
+		/* remove possible .isra.0 suffix as "." is not supported in
+		 * trace event names.
+		 */
+		if (asprintf(&fun, "%s", prp->desc->fun) < 0)
+			return -ENOMEM;
+		suffix = strchr(fun, '.');
+		if (suffix)
+			*suffix = '\0';
+
 		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, fun, prp->desc->fun);
 		close(fd);
-		if (rc == -1)
+		if (rc == -1) {
+			free(fun);
 			return -ENOENT;
+		}
 
 		/* create format file name */
 		len = snprintf(NULL, 0, "%s" FBT_GROUP_FMT "/%s/format",
-			       EVENTSFS, FBT_GROUP_DATA, prp->desc->fun) + 1;
+			       EVENTSFS, FBT_GROUP_DATA, fun) + 1;
 		fn = dt_alloc(dtp, len);
-		if (fn == NULL)
+		if (fn == NULL) {
+			free(fun);
 			return -ENOENT;
+		}
 
 		snprintf(fn, len, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
-			 FBT_GROUP_DATA, prp->desc->fun);
+			 FBT_GROUP_DATA, fun);
+		free(fun);
 
 		/* open format file */
 		f = fopen(fn, "r");
@@ -443,13 +497,15 @@ static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 dt_provimpl_t	dt_fbt_fprobe = {
 	.name		= prvname,
 	.prog_type	= BPF_PROG_TYPE_TRACING,
+	.get_prog_type  = fprobe_prog_type,
 	.stack_skip	= 4,
+	.get_stack_skip	= fprobe_stack_skip,
 	.populate	= &populate,
 	.load_prog	= &fprobe_prog_load,
 	.trampoline	= &fprobe_trampoline,
-	.attach		= &dt_tp_probe_attach_raw,
+	.attach		= &fprobe_attach,
 	.probe_info	= &fprobe_probe_info,
-	.detach		= &dt_tp_probe_detach,
+	.detach		= &fprobe_detach,
 	.probe_destroy	= &dt_tp_probe_destroy,
 };
 
-- 
2.43.5




More information about the DTrace-devel mailing list