[DTrace-devel] [PATCH v2 3/3] Fix fbt:::return and pid:::return arg1

eugene.loh at oracle.com eugene.loh at oracle.com
Thu May 5 20:26:26 UTC 2022


From: Eugene Loh <eugene.loh at oracle.com>

Meanwhile, set fbt:::return arg0=-1 to indicate we do not know the
real value.

Also, remove the unused PT_REGS_BPF_*().

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_cg.c                       | 24 +++++++++++-
 libdtrace/dt_cg.h                       |  1 +
 libdtrace/dt_prov_fbt.c                 | 20 +++++++++-
 libdtrace/dt_prov_pid.c                 |  5 ++-
 libdtrace/dt_pt_regs.h                  | 25 ++-----------
 test/unittest/fbtprovider/tst.return0.d |  6 +--
 test/unittest/fbtprovider/tst.return0.r |  1 +
 test/unittest/fbtprovider/tst.return1.d | 50 +++++++++++++++++++++++++
 test/unittest/fbtprovider/tst.return1.r |  1 +
 test/unittest/pid/tst.ret1.d            |  3 +-
 test/unittest/pid/tst.ret2.d            |  3 +-
 11 files changed, 105 insertions(+), 34 deletions(-)
 create mode 100644 test/unittest/fbtprovider/tst.return0.r
 create mode 100644 test/unittest/fbtprovider/tst.return1.d
 create mode 100644 test/unittest/fbtprovider/tst.return1.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 3c97a6c9..4729710d 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -279,7 +279,7 @@ dt_cg_tramp_copy_args_from_regs(dt_pcb_t *pcb, int rp)
 
 	/*
 	 *	for (i = 0; i < PT_REGS_ARGC; i++)
-	 *		dctx->mst->argv[i] = PT_REGS_BPF_ARGi((dt_pt_regs *)rp);
+	 *		dctx->mst->argv[i] = PT_REGS_ARGi((dt_pt_regs *)rp);
 	 *				// lddw %r0, [%rp + PT_REGS_ARGi]
 	 *				// stdw [%r7 + DMST_ARG(i)], %r0
 	 */
@@ -369,6 +369,28 @@ dt_cg_tramp_copy_args_from_regs(dt_pcb_t *pcb, int rp)
 	}
 }
 
+/*
+ * Copy return value from a dt_pt_regs structure referenced by the 'rp' argument.
+ * to mst->arg[1].  Zero the other args.
+ *
+ * The caller must ensure that %r7 contains the value set by the
+ * dt_cg_tramp_prologue*() functions.
+ */
+void
+dt_cg_tramp_copy_rval_from_regs(dt_pcb_t *pcb, int rp)
+{
+	dt_irlist_t	*dlp = &pcb->pcb_ir;
+	int		i;
+
+	emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_ARG(0), 0));
+
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_8, PT_REGS_RET));
+	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(1), BPF_REG_0));
+
+	for (i = 2; i < ARRAY_SIZE(((dt_mstate_t *)0)->argv); i++)
+		emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_ARG(i), 0));
+}
+
 typedef struct {
 	dt_irlist_t	*dlp;
 	dt_activity_t	act;
diff --git a/libdtrace/dt_cg.h b/libdtrace/dt_cg.h
index 5752151b..bc592fea 100644
--- a/libdtrace/dt_cg.h
+++ b/libdtrace/dt_cg.h
@@ -25,6 +25,7 @@ extern void dt_cg_tramp_prologue(dt_pcb_t *pcb);
 extern void dt_cg_tramp_clear_regs(dt_pcb_t *pcb);
 extern void dt_cg_tramp_copy_regs(dt_pcb_t *pcb, int rp);
 extern void dt_cg_tramp_copy_args_from_regs(dt_pcb_t *pcb, int rp);
+extern void dt_cg_tramp_copy_rval_from_regs(dt_pcb_t *pcb, int rp);
 extern void dt_cg_tramp_call_clauses(dt_pcb_t *pcb, const dt_probe_t *prp,
 				     dt_activity_t act);
 extern void dt_cg_tramp_return(dt_pcb_t *pcb);
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index 62fea51e..ff2fd364 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -167,9 +167,25 @@ static void trampoline(dt_pcb_t *pcb)
 	 *				//     (%r7 = dctx->mst)
 	 *				//     (%r8 = dctx->ctx)
 	 */
-
 	dt_cg_tramp_copy_regs(pcb, BPF_REG_8);
-	dt_cg_tramp_copy_args_from_regs(pcb, BPF_REG_8);
+	if (strcmp(pcb->pcb_probe->desc->prb, "return") == 0) {
+		dt_irlist_t *dlp = &pcb->pcb_ir;
+
+		dt_cg_tramp_copy_rval_from_regs(pcb, BPF_REG_8);
+
+		/*
+		 * fbt:::return arg0 should be the function offset for
+		 * return instruction.  Since we use kretprobes, however,
+		 * which do not fire until the function has returned to
+		 * its caller, information about the returning instruction
+		 * in the callee has been lost.
+		 *
+		 * Set arg0=-1 to indicate that we do not know the value.
+		 */
+		dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, BPF_REG_0, -1);
+		emit(dlp,  BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
+	} else
+		dt_cg_tramp_copy_args_from_regs(pcb, BPF_REG_8);
 	dt_cg_tramp_epilogue(pcb);
 }
 
diff --git a/libdtrace/dt_prov_pid.c b/libdtrace/dt_prov_pid.c
index af894f79..d2b1b0d7 100644
--- a/libdtrace/dt_prov_pid.c
+++ b/libdtrace/dt_prov_pid.c
@@ -211,7 +211,10 @@ static void trampoline(dt_pcb_t *pcb)
 	 */
 
 	dt_cg_tramp_copy_regs(pcb, BPF_REG_8);
-	dt_cg_tramp_copy_args_from_regs(pcb, BPF_REG_8);
+	if (strcmp(pcb->pcb_probe->desc->prb, "return") == 0)
+		dt_cg_tramp_copy_rval_from_regs(pcb, BPF_REG_8);
+	else
+		dt_cg_tramp_copy_args_from_regs(pcb, BPF_REG_8);
 
 	/*
 	 * Retrieve the PID of the process that caused the probe to fire.
diff --git a/libdtrace/dt_pt_regs.h b/libdtrace/dt_pt_regs.h
index 5f851573..057f1fdb 100644
--- a/libdtrace/dt_pt_regs.h
+++ b/libdtrace/dt_pt_regs.h
@@ -1,6 +1,6 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2022, 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.
  */
@@ -19,7 +19,7 @@ extern "C" {
 
 #if defined(__amd64)
 typedef struct pt_regs		dt_pt_regs;
-
+# define PT_REGS_RET		offsetof(dt_pt_regs, rax)
 # define PT_REGS_ARG0		offsetof(dt_pt_regs, rdi)
 # define PT_REGS_ARG1		offsetof(dt_pt_regs, rsi)
 # define PT_REGS_ARG2		offsetof(dt_pt_regs, rdx)
@@ -30,17 +30,9 @@ typedef struct pt_regs		dt_pt_regs;
 # define PT_REGS_ARGSTKBASE	1
 # define PT_REGS_IP		offsetof(dt_pt_regs, rip)
 # define PT_REGS_SP		offsetof(dt_pt_regs, rsp)
-
-# define PT_REGS_BPF_ARG0(r)	((r)->rdi)
-# define PT_REGS_BPF_ARG1(r)	((r)->rsi)
-# define PT_REGS_BPF_ARG2(r)	((r)->rdx)
-# define PT_REGS_BPF_ARG3(r)	((r)->rcx)
-# define PT_REGS_BPF_ARG4(r)	((r)->r8)
-# define PT_REGS_BPF_ARG5(r)	((r)->r9)
-# define PT_REGS_BPF_IP(r)	((r)->rip)
-# define PT_REGS_BPF_SP(r)	((r)->rsp)
 #elif defined(__aarch64__)
 typedef struct user_pt_regs	dt_pt_regs;
+# define PT_REGS_RET		offsetof(dt_pt_regs, regs[0])
 # define PT_REGS_ARG0		offsetof(dt_pt_regs, regs[0])
 # define PT_REGS_ARG1		offsetof(dt_pt_regs, regs[1])
 # define PT_REGS_ARG2		offsetof(dt_pt_regs, regs[2])
@@ -53,17 +45,6 @@ typedef struct user_pt_regs	dt_pt_regs;
 # define PT_REGS_ARGSTKBASE	0
 # define PT_REGS_IP		offsetof(dt_pt_regs, pc)
 # define PT_REGS_SP		offsetof(dt_pt_regs, sp)
-
-# define PT_REGS_BPF_ARG0(r)	((r)->regs[0])
-# define PT_REGS_BPF_ARG1(r)	((r)->regs[1])
-# define PT_REGS_BPF_ARG2(r)	((r)->regs[2])
-# define PT_REGS_BPF_ARG3(r)	((r)->regs[3])
-# define PT_REGS_BPF_ARG4(r)	((r)->regs[4])
-# define PT_REGS_BPF_ARG5(r)	((r)->regs[5])
-# define PT_REGS_BPF_ARG6(r)	((r)->regs[6])
-# define PT_REGS_BPF_ARG7(r)	((r)->regs[7])
-# define PT_REGS_BPF_IP(r)	((r)->pc)
-# define PT_REGS_BPF_SP(r)	((r)->sp)
 #else
 # error ISA not supported
 #endif
diff --git a/test/unittest/fbtprovider/tst.return0.d b/test/unittest/fbtprovider/tst.return0.d
index 3d58e84f..0b7091b3 100644
--- a/test/unittest/fbtprovider/tst.return0.d
+++ b/test/unittest/fbtprovider/tst.return0.d
@@ -1,18 +1,16 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, 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: simple fbt provider arg0 and probfunc print test.
+ * ASSERTION: simple fbt provider arg0 and probefunc print test.
  *
  * SECTION: FBT Provider/Probe arguments
  */
 
-/* @@runtest-opts: -Z */
-
 #pragma D option quiet
 #pragma D option statusrate=10ms
 
diff --git a/test/unittest/fbtprovider/tst.return0.r b/test/unittest/fbtprovider/tst.return0.r
new file mode 100644
index 00000000..53308c30
--- /dev/null
+++ b/test/unittest/fbtprovider/tst.return0.r
@@ -0,0 +1 @@
+do_sys_poll ffffffffffffffff returned 0
diff --git a/test/unittest/fbtprovider/tst.return1.d b/test/unittest/fbtprovider/tst.return1.d
new file mode 100644
index 00000000..751e8865
--- /dev/null
+++ b/test/unittest/fbtprovider/tst.return1.d
@@ -0,0 +1,50 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, 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.
+ */
+
+/* @@trigger: bogus-ioctl */
+/* @@trigger-timing: before */
+/* @@runtest-opts: $_pid */
+
+#pragma D option destructive
+#pragma D option quiet
+#pragma D option zdefs
+
+BEGIN
+{
+	niter = 0;
+	rval = -1;
+}
+
+/* notify the trigger to exit its ioctl() loop */
+syscall::ioctl:entry
+/pid == $1/
+{
+	raise(SIGUSR1);
+}
+
+/* if we enter open(), reset the expected return value */
+syscall::open*:entry
+/pid == $1/
+{
+	reset = 1;
+}
+
+/* check the return value (the first probe resets the expected value) */
+syscall:vmlinux:open*:return,
+fbt:vmlinux:do_sys_open*:return
+/pid == $1/
+{
+	rval = (reset ? arg1 : rval);
+	printf("%s", arg1 == rval ? "" : "ERROR mismatch\n");
+	reset = 0;
+}
+
+syscall::open*:return
+/pid == $1 && ++niter >= 20/
+{
+	exit(0);
+}
diff --git a/test/unittest/fbtprovider/tst.return1.r b/test/unittest/fbtprovider/tst.return1.r
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/test/unittest/fbtprovider/tst.return1.r
@@ -0,0 +1 @@
+
diff --git a/test/unittest/pid/tst.ret1.d b/test/unittest/pid/tst.ret1.d
index bdf7d274..398e2cc8 100644
--- a/test/unittest/pid/tst.ret1.d
+++ b/test/unittest/pid/tst.ret1.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, 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.
  */
-/* @@xfail: dtv2 */
 /* @@runtest-opts: $_pid */
 /* @@trigger: pid-tst-ret1 */
 /* @@trigger-timing: before */
diff --git a/test/unittest/pid/tst.ret2.d b/test/unittest/pid/tst.ret2.d
index d3d482e3..a542646a 100644
--- a/test/unittest/pid/tst.ret2.d
+++ b/test/unittest/pid/tst.ret2.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, 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.
  */
-/* @@xfail: dtv2 */
 /* @@runtest-opts: $_pid */
 /* @@trigger: pid-tst-ret2 */
 /* @@trigger-timing: before */
-- 
2.18.4




More information about the DTrace-devel mailing list