[DTrace-devel] [PATCH 08/12] Add support for built-in variable stackdepth

eugene.loh at oracle.com eugene.loh at oracle.com
Fri May 28 11:35:12 PDT 2021


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

Add space to the "mem" BPF map where we can write a stack of maximum
depth.  (This approach should be replaced eventually with a more general
mechanism for using scratch space.)

Since precompiled BPF code needs to verify the use of the new buffer, we
we make its offset and size available to get_bvar() via STKOFF and STKSIZ.

For DIF_VAR_STACKDEPTH, add code to write the stack and return its length.

Fix test/unittest/stackdepth/tst.value.d:

  *)  Use a probe that has a kernel stack.

  *)  Change the postprocessing to check properly whether a line is empty.

  *)  Remove xfail.

Consolidate stackdepth tests with other built-in-variable tests:

  *)  stackdepth/tst.default.d was already simply a subset of
      variables/bvar/tst.stackdepth.d and so can be deleted.

  *)  stackdepth/tst.value.* is moved to variables/bvar/tst.stackdepth2.*

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 bpf/get_bvar.c                                | 25 +++++++++++++++++--
 libdtrace/dt_bpf.c                            |  7 ++++--
 libdtrace/dt_bpf.h                            |  2 ++
 libdtrace/dt_cc.c                             |  6 +++++
 libdtrace/dt_dlibs.c                          |  2 ++
 test/unittest/stackdepth/tst.default.d        | 20 ---------------
 .../bvar/tst.stackdepth2.d}                   | 12 ++++++++-
 .../bvar/tst.stackdepth2.r}                   |  0
 .../bvar/tst.stackdepth2.r.p}                 |  4 +--
 9 files changed, 51 insertions(+), 27 deletions(-)
 delete mode 100644 test/unittest/stackdepth/tst.default.d
 rename test/unittest/{stackdepth/tst.value.d => variables/bvar/tst.stackdepth2.d} (80%)
 rename test/unittest/{stackdepth/tst.value.r => variables/bvar/tst.stackdepth2.r} (100%)
 rename test/unittest/{stackdepth/tst.value.r.p => variables/bvar/tst.stackdepth2.r.p} (100%)

diff --git a/bpf/get_bvar.c b/bpf/get_bvar.c
index 198cb673..570334f9 100644
--- a/bpf/get_bvar.c
+++ b/bpf/get_bvar.c
@@ -25,6 +25,8 @@ extern struct bpf_map_def probes;
 extern struct bpf_map_def state;
 
 extern uint64_t STBSZ;
+extern uint64_t STKOFF;
+extern uint64_t STKSIZ;
 
 #define error(dctx, fault, illval) \
 	({ \
@@ -54,8 +56,27 @@ noinline uint64_t dt_get_bvar(dt_dctx_t *dctx, uint32_t id)
 	case DIF_VAR_ARG9:
 		return mst->argv[id - DIF_VAR_ARG0];
 	case DIF_VAR_STACKDEPTH: {
-		/* FIXME: no stack() yet */
-		return 0;
+		uint64_t stacksize = (uint64_t) &STKSIZ;
+		uint64_t flags = 0 & BPF_F_SKIP_FIELD_MASK;
+		char *buf = ((char *) dctx->buf) + ((uint64_t) &STKOFF);
+		uint64_t copylen;
+
+		copylen = bpf_get_stack(dctx->ctx, buf, stacksize, flags);
+		if (copylen < 0)
+			return error(dctx, DTRACEFLT_BADSTACK, 0 /* FIXME */);
+
+		/* FIXME: if we filled the buffer, was it too small? */
+#if 0
+		if (copylen == stacksize)
+			return error(dctx, DTRACEFLT_BADSTACK, 0 /* FIXME */);
+#endif
+
+		/*
+		 * While linux/bpf.h does not describe the meaning of
+		 * bpf_get_stack()'s return value outside of its sign,
+		 * it is presumably the length of the copied stack.
+		 */
+		return copylen / 8;
 	}
 	case DIF_VAR_CALLER: {
 		uint64_t flags = 0 & BPF_F_SKIP_FIELD_MASK;
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 3ef0b262..a5bfafa6 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -274,8 +274,11 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 
 	if (create_gmap(dtp, "mem", BPF_MAP_TYPE_PERCPU_ARRAY,
 			sizeof(uint32_t),
-			roundup(sizeof(dt_mstate_t), 8) + 8 +
-				roundup(dtp->dt_maxreclen, 8), 1) == -1)
+			roundup(sizeof(dt_mstate_t), 8)
+			  + 8
+			  + roundup(dtp->dt_maxreclen, 8)
+			  + 8 * dtp->dt_maxframes,
+			1) == -1)
 		return -1;		/* dt_errno is set for us */
 
 	/*
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index 7fa9eed3..3afc95fa 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -23,6 +23,8 @@ extern "C" {
 #define DT_CONST_CLID	3
 #define DT_CONST_ARGC	4
 #define DT_CONST_STBSZ	5
+#define DT_CONST_STKOFF	6
+#define DT_CONST_STKSIZ	7
 
 extern int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
 			   int group_fd, unsigned long flags);
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index a374a747..050a9bf6 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -2327,6 +2327,12 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
 			case DT_CONST_STBSZ:
 				nrp->dofr_data = dtp->dt_strlen;
 				continue;
+			case DT_CONST_STKOFF:
+				nrp->dofr_data = roundup(dtp->dt_maxreclen, 8);
+				continue;
+			case DT_CONST_STKSIZ:
+				nrp->dofr_data = 8 * dtp->dt_maxframes;
+				continue;
 			default:
 				/* probe name -> value is probe id */
 				if (strchr(idp->di_name, ':') != NULL)
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index fae58b1a..10886adb 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -78,6 +78,8 @@ static const dt_ident_t		dt_bpf_symbols[] = {
 	DT_BPF_SYMBOL_ID(CLID, DT_IDENT_SCALAR, DT_CONST_CLID),
 	DT_BPF_SYMBOL_ID(ARGC, DT_IDENT_SCALAR, DT_CONST_ARGC),
 	DT_BPF_SYMBOL_ID(STBSZ, DT_IDENT_SCALAR, DT_CONST_STBSZ),
+	DT_BPF_SYMBOL_ID(STKOFF, DT_IDENT_SCALAR, DT_CONST_STKOFF),
+	DT_BPF_SYMBOL_ID(STKSIZ, DT_IDENT_SCALAR, DT_CONST_STKSIZ),
 	/* End-of-list marker */
 	{ NULL, }
 };
diff --git a/test/unittest/stackdepth/tst.default.d b/test/unittest/stackdepth/tst.default.d
deleted file mode 100644
index 7267ccf1..00000000
--- a/test/unittest/stackdepth/tst.default.d
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, 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 stackdepth variable.
- *
- * SECTION: Variables/Built-in Variables
- *
- */
-
-BEGIN
-{
-	trace(stackdepth);
-	exit(0);
-}
diff --git a/test/unittest/stackdepth/tst.value.d b/test/unittest/variables/bvar/tst.stackdepth2.d
similarity index 80%
rename from test/unittest/stackdepth/tst.value.d
rename to test/unittest/variables/bvar/tst.stackdepth2.d
index 97cc54df..7e28a24b 100644
--- a/test/unittest/stackdepth/tst.value.d
+++ b/test/unittest/variables/bvar/tst.stackdepth2.d
@@ -4,8 +4,8 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
+#pragma D option destructive
 #pragma D option quiet
 
 /*
@@ -17,6 +17,11 @@
  */
 
 BEGIN
+{
+	system("echo write something > /dev/null");
+}
+
+fbt::__vfs_write:entry
 {
 	printf("DEPTH %d\n", stackdepth);
 	printf("TRACE BEGIN\n");
@@ -24,3 +29,8 @@ BEGIN
 	printf("TRACE END\n");
 	exit(0);
 }
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/stackdepth/tst.value.r b/test/unittest/variables/bvar/tst.stackdepth2.r
similarity index 100%
rename from test/unittest/stackdepth/tst.value.r
rename to test/unittest/variables/bvar/tst.stackdepth2.r
diff --git a/test/unittest/stackdepth/tst.value.r.p b/test/unittest/variables/bvar/tst.stackdepth2.r.p
similarity index 100%
rename from test/unittest/stackdepth/tst.value.r.p
rename to test/unittest/variables/bvar/tst.stackdepth2.r.p
index fa83eb0c..9b071181 100755
--- a/test/unittest/stackdepth/tst.value.r.p
+++ b/test/unittest/variables/bvar/tst.stackdepth2.r.p
@@ -12,12 +12,12 @@
 	getline;
 	count = 0;
 	while ($0 !~ /^TRACE END/) {
+		if (NF)
+			count++;
 		if (getline != 1) {
 			print "EOF or error while processing stack\n";
 			exit 0;
 		}
-		if (NF)
-			count++;
 	}
 }
 
-- 
2.18.4




More information about the DTrace-devel mailing list