Skip to contentSkip to conversation

fbt: retrieve function return value using helper

PATCH In review Kris Van Hees 2 participants 2 messages Apr 28

lore
Share & tools
lore
#0 lore raw

PATCH 5/6 fbt: retrieve function return value using helper

We were causing BPF verifier errors when trying to access the return value of some functions due to incorrect calculation of the offset to read from. Rather than implementing the more complex logic needed to calculate the proper offset of the return value, we can just use the bpf_get_func_ret() BPF helper. This does not impose a performance decrease because that helper gets inlined by the BPF verifier.

---
 libdtrace/dt_prov_fbt.c                |  9 +++++----
 test/unittest/codegen/tst.fbt-return.d | 24 ++++++++++++++++++++++++
 test/unittest/codegen/tst.fbt-return.r |  5 +++++
 3 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 test/unittest/codegen/tst.fbt-return.d
 create mode 100644 test/unittest/codegen/tst.fbt-return.r
libdtrace/dt_prov_fbt.c +5 -4
index d6f57c67f..3ae035819 100644
@@ -336,10 +336,11 @@ static int fprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 		 */
 		dmp = dt_module_lookup_by_name(dtp, prp->desc->mod);
 		if (dmp && prp->argc == 2) {
-			int32_t	btf_id = dt_tp_probe_get_id(prp);
-			int	i = dt_btf_func_argc(dtp, dmp->dm_btf, btf_id);
-
-			emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_8, i * 8));
+			emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_8));
+			emit(dlp, BPF_MOV_REG(BPF_REG_2, BPF_REG_FP));
+			emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, DT_TRAMP_SP_SLOT(0)));
+			emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_get_func_ret]));
+			emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_FP, DT_TRAMP_SP_SLOT(0)));
 			emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(1), BPF_REG_0));
 		}
 	}
test/unittest/codegen/tst.fbt-return.d new file +24 -0
new file mode 100644
index 000000000..123641bb8
@@ -0,0 +1,24 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Ensure BPF code generated for an FBT return probe passes the BPF
+ *	      verifiier.
+ *
+ * SECTION: FBT Provider/Probe arguments
+ */
+
+dtrace:::BEGIN,
+fbt:vmlinux:adxl_get_component_names:return
+{
+	exit(0);
+}
+
+dtrace:::ERROR 
+{
+	exit(1);
+}
test/unittest/codegen/tst.fbt-return.r new file +5 -0
new file mode 100644
index 000000000..1283918b1
@@ -0,0 +1,5 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+
+-- @@stderr --
+dtrace: script 'test/unittest/codegen/tst.fbt-return.d' matched 3 probes
Signature · 1 line
2.53.0
Reviewed-by on v1 5/6
#1 lore raw

On 28 Apr 2026, Kris Van Hees outgrape:

Quoted 6 lines

We were causing BPF verifier errors when trying to access the return value of some functions due to incorrect calculation of the offset to read from. Rather than implementing the more complex logic needed to calculate the proper offset of the return value, we can just use the bpf_get_func_ret() BPF helper. This does not impose a performance decrease because that helper gets inlined by the BPF verifier.

Presumably we are a suitable probe type? ... yes, we are.

Quoted 1 line

Looks much nicer.

Signature · 1 line
NULL && (void)