[DTrace-devel] [PATCH v3] Add support for array/struct/union to trace()

Kris Van Hees kris.van.hees at oracle.com
Tue Feb 1 05:32:54 UTC 2022


Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                         | 73 +++++++++++++++--------
 test/unittest/actions/trace/tst.array.d   | 18 ++++++
 test/unittest/actions/trace/tst.array.r   |  8 +++
 test/unittest/actions/trace/tst.struct.d  | 27 +++++++++
 test/unittest/actions/trace/tst.struct.r  |  8 +++
 test/unittest/actions/trace/tst.struct2.d | 23 +++++++
 test/unittest/actions/trace/tst.struct2.r |  8 +++
 test/unittest/actions/trace/tst.struct3.d | 23 +++++++
 test/unittest/actions/trace/tst.struct3.r |  8 +++
 test/unittest/actions/trace/tst.struct4.d | 23 +++++++
 test/unittest/actions/trace/tst.struct4.r |  8 +++
 test/unittest/actions/trace/tst.struct5.d | 23 +++++++
 test/unittest/actions/trace/tst.struct5.r |  8 +++
 test/unittest/actions/trace/tst.union.d   | 25 ++++++++
 test/unittest/actions/trace/tst.union.r   |  8 +++
 15 files changed, 267 insertions(+), 24 deletions(-)
 create mode 100644 test/unittest/actions/trace/tst.array.d
 create mode 100644 test/unittest/actions/trace/tst.array.r
 create mode 100644 test/unittest/actions/trace/tst.struct.d
 create mode 100644 test/unittest/actions/trace/tst.struct.r
 create mode 100644 test/unittest/actions/trace/tst.struct2.d
 create mode 100644 test/unittest/actions/trace/tst.struct2.r
 create mode 100644 test/unittest/actions/trace/tst.struct3.d
 create mode 100644 test/unittest/actions/trace/tst.struct3.r
 create mode 100644 test/unittest/actions/trace/tst.struct4.d
 create mode 100644 test/unittest/actions/trace/tst.struct4.r
 create mode 100644 test/unittest/actions/trace/tst.struct5.d
 create mode 100644 test/unittest/actions/trace/tst.struct5.r
 create mode 100644 test/unittest/actions/trace/tst.union.d
 create mode 100644 test/unittest/actions/trace/tst.union.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index c8421109..fcf96429 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1,6 +1,6 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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.
  */
@@ -905,6 +905,25 @@ static const uint_t	ldstw[] = {
 					0,	0,	0, BPF_DW,
 				};
 
+/*
+ * When loading bit-fields, we want to convert a byte count in the range
+ * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
+ * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
+ */
+static size_t
+clp2(size_t x)
+{
+	x--;
+
+	x |= (x >> 1);
+	x |= (x >> 2);
+	x |= (x >> 4);
+	x |= (x >> 8);
+	x |= (x >> 16);
+
+	return x + 1;
+}
+
 static int
 dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 		dt_pfargv_t *pfp, int arg)
@@ -1002,6 +1021,31 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 		return 0;
 	}
 
+	/* Handle tracing of by-ref values (arrays, struct, union). */
+	if (kind == DTRACEACT_DIFEXPR && (arg & DT_NF_REF)) {
+		off = dt_rec_add(dtp, dt_cg_fill_gap, kind, size, 2, pfp, arg);
+
+		TRACE_REGSET("store_val(): Begin ");
+		dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
+
+		if (dt_regset_xalloc_args(drp) == -1)
+			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+		emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
+		emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off));
+		emit(dlp, BPF_MOV_IMM(BPF_REG_2, size));
+		emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
+		dt_regset_free(drp, dnp->dn_reg);
+		dt_regset_xalloc(drp, BPF_REG_0);
+		emit(dlp, BPF_CALL_HELPER(BPF_FUNC_probe_read));
+		dt_regset_free_args(drp);
+
+		dt_regset_free(drp, BPF_REG_0);
+		TRACE_REGSET("store_val(): End   ");
+
+		return 0;
+	}
+
 	return -1;
 }
 
@@ -1669,7 +1713,7 @@ dt_cg_act_trace(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 {
 	char		n[DT_TYPE_NAMELEN];
 	dt_node_t	*arg = dnp->dn_args;
-	int		type = 0;
+	int		flags = 0;
 
 	if (dt_node_is_void(arg))
 		dnerror(arg, D_TRACE_VOID,
@@ -1681,11 +1725,11 @@ dt_cg_act_trace(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 			"expression\n");
 
 	if (arg->dn_flags & DT_NF_REF)
-		type = DT_NF_REF;
+		flags = DT_NF_REF;
 	else if (arg->dn_flags & DT_NF_SIGNED)
-		type = DT_NF_SIGNED;
+		flags = DT_NF_SIGNED;
 
-	if (dt_cg_store_val(pcb, arg, DTRACEACT_DIFEXPR, NULL, type) == -1)
+	if (dt_cg_store_val(pcb, arg, DTRACEACT_DIFEXPR, NULL, flags) == -1)
 		dnerror(arg, D_PROTO_ARG,
 			"trace( ) argument #1 is incompatible with prototype:\n"
 			"\tprototype: scalar or string\n\t argument: %s\n",
@@ -1934,25 +1978,6 @@ dt_cg_setx(dt_irlist_t *dlp, int reg, uint64_t x)
 	dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, reg, x);
 }
 
-/*
- * When loading bit-fields, we want to convert a byte count in the range
- * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
- * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
- */
-static size_t
-clp2(size_t x)
-{
-	x--;
-
-	x |= (x >> 1);
-	x |= (x >> 2);
-	x |= (x >> 4);
-	x |= (x >> 8);
-	x |= (x >> 16);
-
-	return x + 1;
-}
-
 /*
  * Lookup the correct load opcode to use for the specified node and CTF type.
  * We determine the size and convert it to a 3-bit index.  Our lookup table
diff --git a/test/unittest/actions/trace/tst.array.d b/test/unittest/actions/trace/tst.array.d
new file mode 100644
index 00000000..104d42e1
--- /dev/null
+++ b/test/unittest/actions/trace/tst.array.d
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints an array correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+BEGIN
+{
+	trace(curthread->comm);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.array.r b/test/unittest/actions/trace/tst.array.r
new file mode 100644
index 00000000..872f16f6
--- /dev/null
+++ b/test/unittest/actions/trace/tst.array.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 64 74 72 61 63 65 00 00 73 68 00 00 00 00 00 00  dtrace..sh......
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.array.d' matched 1 probe
diff --git a/test/unittest/actions/trace/tst.struct.d b/test/unittest/actions/trace/tst.struct.d
new file mode 100644
index 00000000..ec60ea11
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct.d
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints a struct correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+struct {
+	int	a;
+	char	b;
+	int	c;
+} st;
+
+BEGIN
+{
+	st.a = 0x1234;
+	st.b = 0;
+	st.c = 0x9876;
+	trace(st);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.struct.r b/test/unittest/actions/trace/tst.struct.r
new file mode 100644
index 00000000..0658ea88
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 34 12 00 00 00 00 00 00 76 98 00 00              4.......v...
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.struct.d' matched 1 probe
diff --git a/test/unittest/actions/trace/tst.struct2.d b/test/unittest/actions/trace/tst.struct2.d
new file mode 100644
index 00000000..36de485f
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct2.d
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints a struct { int8_t } correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+struct {
+	int8_t	x;
+} st;
+
+BEGIN
+{
+	st.x = 0x34;
+	trace(st);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.struct2.r b/test/unittest/actions/trace/tst.struct2.r
new file mode 100644
index 00000000..2154b90e
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct2.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 34                                               4
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.struct2.d' matched 1 probe
diff --git a/test/unittest/actions/trace/tst.struct3.d b/test/unittest/actions/trace/tst.struct3.d
new file mode 100644
index 00000000..642364f2
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct3.d
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints a struct { int16_t } correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+struct {
+	int16_t	x;
+} st;
+
+BEGIN
+{
+	st.x = 0x34;
+	trace(st);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.struct3.r b/test/unittest/actions/trace/tst.struct3.r
new file mode 100644
index 00000000..3b8fb3b3
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct3.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 34 00                                            4.
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.struct3.d' matched 1 probe
diff --git a/test/unittest/actions/trace/tst.struct4.d b/test/unittest/actions/trace/tst.struct4.d
new file mode 100644
index 00000000..94360d90
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct4.d
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints a struct { int32_t } correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+struct {
+	int32_t	x;
+} st;
+
+BEGIN
+{
+	st.x = 0x34;
+	trace(st);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.struct4.r b/test/unittest/actions/trace/tst.struct4.r
new file mode 100644
index 00000000..90fa1a17
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct4.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 34 00 00 00                                      4...
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.struct4.d' matched 1 probe
diff --git a/test/unittest/actions/trace/tst.struct5.d b/test/unittest/actions/trace/tst.struct5.d
new file mode 100644
index 00000000..0ecc9771
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct5.d
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints a struct { int64_t } correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+struct {
+	int64_t	x;
+} st;
+
+BEGIN
+{
+	st.x = 0x34;
+	trace(st);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.struct5.r b/test/unittest/actions/trace/tst.struct5.r
new file mode 100644
index 00000000..687a0e59
--- /dev/null
+++ b/test/unittest/actions/trace/tst.struct5.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 34 00 00 00 00 00 00 00                          4.......
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.struct5.d' matched 1 probe
diff --git a/test/unittest/actions/trace/tst.union.d b/test/unittest/actions/trace/tst.union.d
new file mode 100644
index 00000000..56b2ff81
--- /dev/null
+++ b/test/unittest/actions/trace/tst.union.d
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/*
+ * ASSERTION: The trace() action prints a union correctly.
+ *
+ * SECTION: Actions and Subroutines/trace()
+ */
+
+union {
+	int	a;
+	char	b[3];
+	short	c;
+} u;
+
+BEGIN
+{
+	u.a = 0x12345678;
+	trace(u);
+	exit(0);
+}
diff --git a/test/unittest/actions/trace/tst.union.r b/test/unittest/actions/trace/tst.union.r
new file mode 100644
index 00000000..48098d11
--- /dev/null
+++ b/test/unittest/actions/trace/tst.union.r
@@ -0,0 +1,8 @@
+                   FUNCTION:NAME
+                          :BEGIN 
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 78 56 34 12                                      xV4.
+
+
+-- @@stderr --
+dtrace: script 'test/unittest/actions/trace/tst.union.d' matched 1 probe
-- 
2.34.1




More information about the DTrace-devel mailing list