[DTrace-devel] [PATCH v2 3/3] String args to dt_strcmp() need to be copied if not DPTR
Kris Van Hees
kris.van.hees at oracle.com
Fri Oct 7 00:48:20 UTC 2022
The dt_strcmp() implementation makes use of indirect load instructions
to retrieve characters from either string argument. That only works for
DTrace-managed storage pointers. So, any argument that is not marked
DT_NF_DPTR must be copied into a tstring before the indirect loads are
done.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
bpf/strcmp.S | 51 ++++++++++++++-----
libdtrace/dt_cg.c | 13 ++++-
.../codegen/tst.execname-cmp-bvar_lhs.d | 19 +++++++
.../codegen/tst.execname-cmp-bvar_rhs.d | 19 +++++++
.../codegen/tst.execname-cmp-const_lhs.d | 19 +++++++
.../codegen/tst.execname-cmp-const_rhs.d | 19 +++++++
.../codegen/tst.kernel_str-cmp-bvar_lhs.d | 19 +++++++
.../codegen/tst.kernel_str-cmp-bvar_rhs.d | 19 +++++++
.../codegen/tst.kernel_str-cmp-const_lhs.d | 19 +++++++
.../codegen/tst.kernel_str-cmp-const_rhs.d | 19 +++++++
10 files changed, 202 insertions(+), 14 deletions(-)
create mode 100644 test/unittest/codegen/tst.execname-cmp-bvar_lhs.d
create mode 100644 test/unittest/codegen/tst.execname-cmp-bvar_rhs.d
create mode 100644 test/unittest/codegen/tst.execname-cmp-const_lhs.d
create mode 100644 test/unittest/codegen/tst.execname-cmp-const_rhs.d
create mode 100644 test/unittest/codegen/tst.kernel_str-cmp-bvar_lhs.d
create mode 100644 test/unittest/codegen/tst.kernel_str-cmp-bvar_rhs.d
create mode 100644 test/unittest/codegen/tst.kernel_str-cmp-const_lhs.d
create mode 100644 test/unittest/codegen/tst.kernel_str-cmp-const_rhs.d
diff --git a/bpf/strcmp.S b/bpf/strcmp.S
index 75177469..f1b3e445 100644
--- a/bpf/strcmp.S
+++ b/bpf/strcmp.S
@@ -58,12 +58,13 @@ dt_strcmp_not :
.size dt_strcmp_not, .-dt_strcmp_not
/*
- * int dt_strcmp(char *s, char *t, char *tmp1, char *tmp2) {
+ * int dt_strcmp(char *s, char *t, char *tmp1, char *tmp2, uint64_t flags) {
*
* [%fp-8]=s
* [%fp-16]=t
* [%fp-24]=tmp1
* [%fp-32]=tmp2
+ * r9=flags
*
* r8 = STRSZ
*
@@ -86,8 +87,14 @@ dt_strcmp_not :
* // based on this location, judge if the strings are >, <, or ==
* if (r0 > r6) goto Lsame;
* if (r0 > r7) goto Lsame;
- * if (s[r0] > t[r0]) return +1;
- * if (s[r0] < t[r0]) return +1;
+
+ * s += r0;
+ * t += r0;
+
+ * if (flags & 1) { } else { bpf_probe_read(tmp1, 1, s); s = tmp1; }
+ * if (flags & 2) { } else { bpf_probe_read(tmp2, 1, t); t = tmp2; }
+ * if (s[0] > t[0]) return +1;
+ * if (s[0] < t[0]) return +1;
*
* // if all chars are the same, break tie on string length
* Lsame:
@@ -105,6 +112,7 @@ dt_strcmp :
stxdw [%fp+-16], %r2 /* Spill t */
stxdw [%fp+-24], %r3 /* Spill tmp1 */
stxdw [%fp+-32], %r4 /* Spill tmp2 */
+ mov %r9, %r5 /* flags */
lddw %r8, STRSZ /* r8 = STRSZ */
@@ -158,20 +166,37 @@ dt_strcmp :
jgt %r0, %r6, .Lsame /* if (r0 > r6) goto Lsame */
jgt %r0, %r8, .Lsame /* if (r0 > r8) goto Lsame */
- ldxdw %r4, [%fp+-8]
- add %r4, %r0
- ldxb %r4, [%r4+0] /* s[r0] */
- and %r4, 0xff
+ ldxdw %r6, [%fp+-8]
+ add %r6, %r8 /* s += r0 */
+ ldxdw %r7, [%fp+-16]
+ add %r7, %r8 /* t += r0 */
+
+ jset %r9, 1, .Ls_is_dptr
+ ldxdw %r1, [%fp+-24]
+ mov %r2, 1
+ mov %r3, %r6
+ mov %r6, %r1 /* s = tmp1 (after the helper call) */
+ call BPF_FUNC_probe_read /* bpf_probe_read(tmp1, r8, s) */
+.Ls_is_dptr:
+
+ jset %r9, 2, .Lt_is_dptr
+ ldxdw %r1, [%fp+-32]
+ mov %r2, 1
+ mov %r3, %r7
+ mov %r7, %r1 /* t = tmp2 (after the helper call) */
+ call BPF_FUNC_probe_read /* bpf_probe_read(tmp2, r8, t) */
+.Lt_is_dptr:
+
+ ldxb %r6, [%r6+0] /* s[0] */
+ and %r6, 0xff
- ldxdw %r5, [%fp+-16]
- add %r5, %r0
- ldxb %r5, [%r5+0] /* t[r0] */
- and %r5, 0xff
+ ldxb %r7, [%r7+0] /* t[0] */
+ and %r7, 0xff
- jle %r4, %r5, 2 /* if (s[r0] > t[r0]) return +1 */
+ jle %r6, %r7, 2 /* if (s[0] > t[0]) return +1 */
mov %r0, 1
exit
- jge %r4, %r5, 2 /* if (s[r0] < t[r0]) return +1 */
+ jge %r6, %r7, 2 /* if (s[0] < t[0]) return +1 */
mov %r0, -1
exit
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index c4e49129..ef639161 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3294,6 +3294,7 @@ dt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
dt_node_is_string(dnp->dn_right)) {
dt_ident_t *idp;
uint_t Lcomp = dt_irlist_label(dlp);
+ uint32_t flags = 0;
uint64_t off1, off2;
/* if either pointer is NULL, just compare pointers */
@@ -3301,7 +3302,16 @@ dt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_right->dn_reg, 0, Lcomp));
/*
- * Otherwise, replace pointers with relative string values.
+ * Set flags to indicate which arguments (if any) are pointers
+ * to DTrace-managed storage.
+ */
+ if (dnp->dn_left->dn_flags & DT_NF_DPTR)
+ flags |= 1;
+ if (dnp->dn_right->dn_flags & DT_NF_DPTR)
+ flags |= 2;
+
+ /*
+ * Replace pointers with relative string values.
* Specifically, replace left with strcmp(left,right)+1 and
* right with 1, so we can use unsigned comparisons.
*/
@@ -3318,6 +3328,7 @@ dt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
emit(dlp, BPF_MOV_REG(BPF_REG_4, BPF_REG_3));
emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, off1));
emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, off2));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_5, flags));
idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_strcmp");
assert(idp != NULL);
dt_regset_xalloc(drp, BPF_REG_0);
diff --git a/test/unittest/codegen/tst.execname-cmp-bvar_lhs.d b/test/unittest/codegen/tst.execname-cmp-bvar_lhs.d
new file mode 100644
index 00000000..d36bbf07
--- /dev/null
+++ b/test/unittest/codegen/tst.execname-cmp-bvar_lhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(probename == execname);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.execname-cmp-bvar_rhs.d b/test/unittest/codegen/tst.execname-cmp-bvar_rhs.d
new file mode 100644
index 00000000..dcdf3507
--- /dev/null
+++ b/test/unittest/codegen/tst.execname-cmp-bvar_rhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(execname == probename);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.execname-cmp-const_lhs.d b/test/unittest/codegen/tst.execname-cmp-const_lhs.d
new file mode 100644
index 00000000..63e8d987
--- /dev/null
+++ b/test/unittest/codegen/tst.execname-cmp-const_lhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace("dtrace" == execname);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.execname-cmp-const_rhs.d b/test/unittest/codegen/tst.execname-cmp-const_rhs.d
new file mode 100644
index 00000000..e256f3a9
--- /dev/null
+++ b/test/unittest/codegen/tst.execname-cmp-const_rhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(execname == "dtrace");
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.kernel_str-cmp-bvar_lhs.d b/test/unittest/codegen/tst.kernel_str-cmp-bvar_lhs.d
new file mode 100644
index 00000000..ef95815a
--- /dev/null
+++ b/test/unittest/codegen/tst.kernel_str-cmp-bvar_lhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(probename == curthread->comm);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.kernel_str-cmp-bvar_rhs.d b/test/unittest/codegen/tst.kernel_str-cmp-bvar_rhs.d
new file mode 100644
index 00000000..1dd9a4ed
--- /dev/null
+++ b/test/unittest/codegen/tst.kernel_str-cmp-bvar_rhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(curthread->comm == probename);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.kernel_str-cmp-const_lhs.d b/test/unittest/codegen/tst.kernel_str-cmp-const_lhs.d
new file mode 100644
index 00000000..e877966e
--- /dev/null
+++ b/test/unittest/codegen/tst.kernel_str-cmp-const_lhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace("dtrace" == curthread->comm);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/codegen/tst.kernel_str-cmp-const_rhs.d b/test/unittest/codegen/tst.kernel_str-cmp-const_rhs.d
new file mode 100644
index 00000000..baebe17f
--- /dev/null
+++ b/test/unittest/codegen/tst.kernel_str-cmp-const_rhs.d
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(curthread->comm == "dtrace");
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
--
2.37.2
More information about the DTrace-devel
mailing list