[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