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

Kris Van Hees kris.van.hees at oracle.com
Fri Jan 28 19:25:01 UTC 2022


Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                        | 95 ++++++++++++++++++------
 test/unittest/actions/trace/tst.array.d  | 18 +++++
 test/unittest/actions/trace/tst.array.r  |  5 ++
 test/unittest/actions/trace/tst.struct.d | 27 +++++++
 test/unittest/actions/trace/tst.struct.r |  8 ++
 test/unittest/actions/trace/tst.union.d  | 25 +++++++
 test/unittest/actions/trace/tst.union.r  |  8 ++
 7 files changed, 162 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.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..1bdf30c7 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,53 @@ 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)) {
+		ctf_file_t	*ctfp = dnp->dn_ctfp;
+		ctf_arinfo_t	r;
+		ctf_id_t	type;
+		size_t		align;
+
+		/*
+		 * Determine the alignment size for the data item.  We do not
+		 * attempt to find the ideal alignment - just one that works.
+		 */
+		type = ctf_type_resolve(ctfp, dnp->dn_type);
+		if (ctf_type_kind(ctfp, type) == CTF_K_ARRAY) {
+			if (ctf_array_info(ctfp, type, &r) != 0) {
+				yypcb->pcb_hdl->dt_ctferr = ctf_errno(ctfp);
+				longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
+			}
+			type = r.ctr_contents;
+		}
+		align = clp2(ctf_type_size(ctfp, type));
+		if (align > 8)
+			align = 8;
+
+		off = dt_rec_add(dtp, dt_cg_fill_gap, kind, size, align, 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 +1735,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 +1747,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 +2000,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..906e684a
--- /dev/null
+++ b/test/unittest/actions/trace/tst.array.r
@@ -0,0 +1,5 @@
+                   FUNCTION:NAME
+                          :BEGIN   dtrace                           
+
+-- @@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.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