[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