[DTrace-devel] [PATCH 3/7] Add support for the stack() action

eugene.loh at oracle.com eugene.loh at oracle.com
Thu May 6 12:31:46 PDT 2021


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

Implement the stack() action using the bpf_get_stack() helper
function.  This implementation most closely resembles the legacy
DTrace implementation.  Someday it may make sense to switch over
to the bpf_get_stackid() instead, which would allow consolidation
of like stacks.

Change the stack() testing.  Specifically, replace the default
test since BEGIN no longer has a kernel stack.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_cg.c                         | 47 ++++++++++++++++++-----
 libdtrace/dt_consume.c                    |  8 ++++
 test/unittest/stack/tst.default.aarch64.r | 14 +++++++
 test/unittest/stack/tst.default.d         | 14 ++++---
 test/unittest/stack/tst.default.r         |  1 -
 test/unittest/stack/tst.default.r.p       |  5 ---
 test/unittest/stack/tst.default.x86_64.r  | 13 +++++++
 test/unittest/stack/tst.stack3.aarch64.r  | 11 ++++++
 test/unittest/stack/tst.stack3.d          | 25 ++++++++++++
 test/unittest/stack/tst.stack3.x86_64.r   | 11 ++++++
 10 files changed, 129 insertions(+), 20 deletions(-)
 create mode 100644 test/unittest/stack/tst.default.aarch64.r
 delete mode 100644 test/unittest/stack/tst.default.r
 delete mode 100755 test/unittest/stack/tst.default.r.p
 create mode 100644 test/unittest/stack/tst.default.x86_64.r
 create mode 100644 test/unittest/stack/tst.stack3.aarch64.r
 create mode 100644 test/unittest/stack/tst.stack3.d
 create mode 100644 test/unittest/stack/tst.stack3.x86_64.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 12548ea2..54f6171d 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1293,21 +1293,50 @@ dt_cg_act_speculate(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 static void
 dt_cg_act_stack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 {
-	dt_node_t *arg = dnp->dn_args;
-#ifdef FIXME
-	uint32_t nframes = 0;
-#endif
+	dt_irlist_t	*dlp = &pcb->pcb_ir;
+	dt_regset_t	*drp = pcb->pcb_regs;
+	dt_node_t	*arg = dnp->dn_args;
+	int		nframes = pcb->pcb_hdl->dt_options[DTRACEOPT_STACKFRAMES];
+	int		skip = 0;
+	uint_t		off;
+
+	/*
+	 * Legacy default was dtrace_stackframes_default,
+	 * in kernel file dtrace/dtrace_state.c.
+	 */
+	if (nframes == DTRACEOPT_UNSET)
+		nframes = 20;
 
 	if (arg != NULL) {
-		if (!dt_node_is_posconst(arg)) {
+		if (!dt_node_is_posconst(arg))
 			dnerror(arg, D_STACK_SIZE, "stack( ) argument #1 must "
 				"be a non-zero positive integer constant\n");
-		}
 
-#ifdef FIXME
-		nframes = (uint32_t)arg->dn_value;
-#endif
+		nframes = arg->dn_value;
 	}
+
+	/* FIXME: should this trigger failure instead? */
+	if (nframes > PERF_MAX_STACK_DEPTH)
+		nframes = PERF_MAX_STACK_DEPTH;
+
+	/* Figure out where we want to be in the output buffer. */
+	off = dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, DTRACEACT_LIBACT,
+			 8 * nframes, 8, NULL, DT_ACT_STACK);
+
+	/* Now call bpf_get_stack(ctx, buf, size, flags). */
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_DCTX));
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_1, DCTX_CTX));
+	emit(dlp, BPF_MOV_REG(BPF_REG_2, BPF_REG_9));
+	emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, off));
+	emit(dlp, BPF_MOV_IMM(BPF_REG_3, 8 * nframes));
+	emit(dlp, BPF_MOV_IMM(BPF_REG_4, skip & BPF_F_SKIP_FIELD_MASK));
+	dt_regset_xalloc(drp, BPF_REG_0);
+	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_stack));
+	dt_regset_free_args(drp);
+	/* FIXME: if (BPF_REG_0 < 0) error */
+	dt_regset_free(drp, BPF_REG_0);
 }
 
 static void
diff --git a/libdtrace/dt_consume.c b/libdtrace/dt_consume.c
index f39156df..0e05b495 100644
--- a/libdtrace/dt_consume.c
+++ b/libdtrace/dt_consume.c
@@ -2043,6 +2043,14 @@ dt_consume_one(dtrace_hdl_t *dtp, FILE *fp, char *buf,
 
 					i++;
 					continue;
+				case DT_ACT_STACK: {
+					int depth = rec->dtrd_size / 8;
+
+					if (dt_print_stack(dtp, fp, NULL,
+					    pdat->dtpda_data, depth, 8) < 0)
+						return -1;
+					continue;
+				}
 				}
 			}
 
diff --git a/test/unittest/stack/tst.default.aarch64.r b/test/unittest/stack/tst.default.aarch64.r
new file mode 100644
index 00000000..f6056987
--- /dev/null
+++ b/test/unittest/stack/tst.default.aarch64.r
@@ -0,0 +1,14 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+               __vfs_write:entry 
+              vmlinux`__vfs_write
+              vmlinux`ksys_write+{ptr}
+              vmlinux`__arm64_sys_write+{ptr}
+              vmlinux`el0_svc_common+{ptr}
+              vmlinux`el0_svc_handler+{ptr}
+              vmlinux`el0_svc+{ptr}
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/stack/tst.default.d' matched 2 probes
+dtrace: allowing destructive actions
diff --git a/test/unittest/stack/tst.default.d b/test/unittest/stack/tst.default.d
index 2e50ec39..27db2116 100644
--- a/test/unittest/stack/tst.default.d
+++ b/test/unittest/stack/tst.default.d
@@ -1,20 +1,24 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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 */
 
 /*
- * ASSERTION:
- *   Test the stack action with the default stack depth.
+ * ASSERTION: Test the stack action with the default stack depth.
  *
  * SECTION: Output Formatting/printf()
- *
  */
 
+#pragma D option destructive
+
 BEGIN
+{
+	system("echo write something > /dev/null");
+}
+
+fbt::__vfs_write:entry
 {
 	stack();
 	exit(0);
diff --git a/test/unittest/stack/tst.default.r b/test/unittest/stack/tst.default.r
deleted file mode 100644
index e3a4e4c3..00000000
--- a/test/unittest/stack/tst.default.r
+++ /dev/null
@@ -1 +0,0 @@
-              dtrace`dtrace_ioctl+{ptr}
diff --git a/test/unittest/stack/tst.default.r.p b/test/unittest/stack/tst.default.r.p
deleted file mode 100755
index 281c025f..00000000
--- a/test/unittest/stack/tst.default.r.p
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sed -nf
-
-# Eliminate all lines other than dtrace`ioctl.
-
-/dtrace`dtrace_ioctl/p
diff --git a/test/unittest/stack/tst.default.x86_64.r b/test/unittest/stack/tst.default.x86_64.r
new file mode 100644
index 00000000..858dd91a
--- /dev/null
+++ b/test/unittest/stack/tst.default.x86_64.r
@@ -0,0 +1,13 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+               __vfs_write:entry 
+              vmlinux`__vfs_write+{ptr}
+              vmlinux`ksys_write+{ptr}
+              vmlinux`__x64_sys_write+{ptr}
+              vmlinux`do_syscall_64+{ptr}
+              vmlinux`entry_SYSCALL_64+{ptr}
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/stack/tst.default.d' matched 2 probes
+dtrace: allowing destructive actions
diff --git a/test/unittest/stack/tst.stack3.aarch64.r b/test/unittest/stack/tst.stack3.aarch64.r
new file mode 100644
index 00000000..8f285fe5
--- /dev/null
+++ b/test/unittest/stack/tst.stack3.aarch64.r
@@ -0,0 +1,11 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+               __vfs_write:entry 
+              vmlinux`__vfs_write
+              vmlinux`ksys_write+{ptr}
+              vmlinux`__arm64_sys_write+{ptr}
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/stack/tst.stack3.d' matched 2 probes
+dtrace: allowing destructive actions
diff --git a/test/unittest/stack/tst.stack3.d b/test/unittest/stack/tst.stack3.d
new file mode 100644
index 00000000..1a2eaf58
--- /dev/null
+++ b/test/unittest/stack/tst.stack3.d
@@ -0,0 +1,25 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 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: Test the stack action with depth 3.
+ *
+ * SECTION: Output Formatting/printf()
+ */
+
+#pragma D option destructive
+
+BEGIN
+{
+	system("echo write something > /dev/null");
+}
+
+fbt::__vfs_write:entry
+{
+	stack(3);
+	exit(0);
+}
diff --git a/test/unittest/stack/tst.stack3.x86_64.r b/test/unittest/stack/tst.stack3.x86_64.r
new file mode 100644
index 00000000..68d63e1e
--- /dev/null
+++ b/test/unittest/stack/tst.stack3.x86_64.r
@@ -0,0 +1,11 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+               __vfs_write:entry 
+              vmlinux`__vfs_write+{ptr}
+              vmlinux`ksys_write+{ptr}
+              vmlinux`__x64_sys_write+{ptr}
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/stack/tst.stack3.d' matched 2 probes
+dtrace: allowing destructive actions
-- 
2.18.4




More information about the DTrace-devel mailing list