[DTrace-devel] [PATCH 1/8] Add support for string comparisons
eugene.loh at oracle.com
eugene.loh at oracle.com
Wed Sep 29 08:13:34 PDT 2021
From: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
bpf/Build | 1 +
bpf/strcmp.S | 191 ++++++++++++++++++
libdtrace/dt_bpf.c | 6 +-
libdtrace/dt_cg.c | 63 +++++-
libdtrace/dt_dlibs.c | 1 +
test/demo/builtin/probename.d | 1 -
test/demo/builtin/probeprov.d | 1 -
test/demo/fbt/xioctl.d | 3 +-
test/unittest/dif/strncmp.d | 1 -
.../dtrace-util/tst.ListProbesFunc.sh | 3 +-
.../dtrace-util/tst.ListProbesName.sh | 3 +-
.../operators/tst.str_comparison-basic.d | 74 +++++++
.../operators/tst.str_comparison-longer.d | 59 ++++++
.../operators/tst.str_comparison-nested.d | 39 ++++
.../operators/tst.str_comparison-nested.r | 1 +
.../operators/tst.str_comparison-signed.d | 59 ++++++
test/unittest/types/tst.condexpr.d | 3 +-
test/unittest/types/tst.relstring.d | 3 +-
18 files changed, 491 insertions(+), 21 deletions(-)
create mode 100644 bpf/strcmp.S
create mode 100644 test/unittest/operators/tst.str_comparison-basic.d
create mode 100644 test/unittest/operators/tst.str_comparison-longer.d
create mode 100644 test/unittest/operators/tst.str_comparison-nested.d
create mode 100644 test/unittest/operators/tst.str_comparison-nested.r
create mode 100644 test/unittest/operators/tst.str_comparison-signed.d
diff --git a/bpf/Build b/bpf/Build
index 5ea497a3..34150b20 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -26,6 +26,7 @@ bpf_dlib_SOURCES = \
get_bvar.c \
get_tvar.c set_tvar.c \
probe_error.c \
+ strcmp.S \
strjoin.S \
substr.S \
strlen.c
diff --git a/bpf/strcmp.S b/bpf/strcmp.S
new file mode 100644
index 00000000..2a295835
--- /dev/null
+++ b/bpf/strcmp.S
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define DT_STRLEN_BYTES 2
+
+#define BPF_FUNC_probe_read 4
+#define BPF_FUNC_probe_read_str 45
+
+ .text
+
+/*
+ * void dt_strcmp_xor(char *s, const char *t, uint64_t len) {
+ * for (r6 = 0; r6 < len; r6++)
+ * s[r6] ^= t[r6];
+ * }
+ * where len is a positive multiple of 8.
+ */
+ .align 4
+ .global dt_strcmp_xor
+dt_strcmp_xor :
+ mov %r6, 0
+.Lxor:
+ ldxdw %r4, [%r1+0]
+ ldxdw %r5, [%r2+0]
+
+ xor %r4, %r5
+ stxdw [%r1+0], %r4
+
+ add %r1, 8
+ add %r2, 8
+ add %r6, 8
+ jlt %r6, %r3, .Lxor
+ exit
+
+/*
+ * void dt_strcmp_not(char *s, uint64_t len) {
+ * for (r6 = 0; r6 < len; r6++)
+ * s[r6] = ! s[r6]
+ * }
+ */
+ .align 4
+ .global dt_strcmp_not
+dt_strcmp_not :
+ mov %r6, 0
+.Lnot:
+ ldxb %r3, [%r1+0]
+ and %r3, 0xff
+ sub %r3, 1
+ rsh %r3, 63
+ stxb [%r1+0], %r3
+ add %r1, 1
+ add %r6, 1
+ jlt %r6, %r2, .Lnot
+ exit
+
+/*
+ * int dt_strcmp(char *s, char *t, char *tmp1, char *tmp2) {
+ *
+ * [%fp-8]=s
+ * [%fp-16]=t
+ * [%fp-24]=tmp1
+ * [%fp-32]=tmp2
+ *
+ * r8 = STRSZ
+ *
+ * // make temporary copies of strings
+ * r6 = bpf_probe_read_str(tmp1, STRSZ, s + DT_STRLEN_BYTES);
+ * r7 = bpf_probe_read_str(tmp2, STRSZ, t + DT_STRLEN_BYTES);
+ * tmp1[r6] = '\0';
+ * tmp2[r7] = '\0';
+ *
+ * // round r8 up to a multiple of 8
+ * r8 = (r8 + 7) & -8;
+ *
+ * // xor strings together, "not" bytes, and find first NULL
+ * // (this gives us the first byte that differs in the two strings)
+ * dt_strcmp_xor(tmp1, tmp2, r8);
+ * dt_strcmp_not(tmp1, r8);
+ * r0 = bpf_probe_read_str(tmp2, r8, tmp1);
+ * r0 -= 1;
+ *
+ * // based on this location, judge if the strings are >, <, or ==
+ * if (r0 > r6) goto Lsame;
+ * if (r0 > r7) goto Lsame;
+ * r0 += DT_STRLEN_BYTES;
+ * if (s[r0] > t[r0]) return +1;
+ * if (s[r0] < t[r0]) return +1;
+ *
+ * // if all chars are the same, break tie on string length
+ * Lsame:
+ * if (r6 > r7) return +1
+ * if (r6 < r7) return -1
+ * return 0;
+ * }
+ */
+ .align 4
+ .global dt_strcmp
+dt_strcmp :
+
+ stxdw [%fp+-8], %r1 /* Spill s */
+ stxdw [%fp+-16], %r2 /* Spill t */
+ stxdw [%fp+-24], %r3 /* Spill tmp1 */
+ stxdw [%fp+-32], %r4 /* Spill tmp2 */
+
+ lddw %r8, STRSZ /* r8 = STRSZ */
+
+ ldxdw %r1, [%fp+-24]
+ mov %r2, %r8
+ ldxdw %r3, [%fp+-8]
+ add %r3, DT_STRLEN_BYTES
+ call BPF_FUNC_probe_read_str /* r6 = bpf_probe_read_str(tmp1, STRSZ, s + DT_STRLEN_BYTES) */
+ mov %r6, %r0
+ jle %r6, %r8, 1
+ mov %r6, %r8
+
+ ldxdw %r1, [%fp+-32]
+ mov %r2, %r8
+ ldxdw %r3, [%fp+-16]
+ add %r3, DT_STRLEN_BYTES
+ call BPF_FUNC_probe_read_str /* r7 = bpf_probe_read_str(tmp2, STRSZ, t + DT_STRLEN_BYTES) */
+ mov %r7, %r0
+ jle %r7, %r8, 1
+ mov %r7, %r8
+
+ mov %r2, 0
+ ldxdw %r1, [%fp+-24]
+ add %r1, %r6
+ stxb [%r1+0], %r2 /* tmp1[r6] = '\0' */
+ ldxdw %r1, [%fp+-32]
+ add %r1, %r7
+ stxb [%r1+0], %r2 /* tmp2[r7] = '\0' */
+
+ add %r8, 7 /* round r8 up to a multiple of 8 */
+ and %r8, -8
+
+ ldxdw %r1, [%fp+-24]
+ ldxdw %r2, [%fp+-32]
+ mov %r3, %r8
+ call dt_strcmp_xor /* dt_strcmp_xor(tmp1, tmp2, r8) */
+ ldxdw %r1, [%fp+-24]
+ mov %r2, %r8
+ call dt_strcmp_not /* dt_strcmp_not(tmp1, r8) */
+
+ ldxdw %r1, [%fp+-32]
+ mov %r2, %r8
+ ldxdw %r3, [%fp+-24]
+ call BPF_FUNC_probe_read_str /* r0 = bpf_probe_read_str(tmp2, r8, tmp1) */
+
+ jsle %r0, 0, .L0 /* help the BPF verifier */
+ lddw %r8, STRSZ
+ sub %r8, DT_STRLEN_BYTES
+ jlt %r0, %r8, 1
+ mov %r0, %r8
+
+ sub %r0, 1 /* r0 -= 1 */
+
+ jgt %r0, %r6, .Lsame /* if (r0 > r6) goto Lsame */
+ jgt %r0, %r8, .Lsame /* if (r0 > r8) goto Lsame */
+
+ add %r0, DT_STRLEN_BYTES /* r0 += DT_STRLEN_BYTES */
+
+ ldxdw %r4, [%fp+-8]
+ add %r4, %r0
+ ldxb %r4, [%r4+0] /* s[r0] */
+ and %r4, 0xff
+
+ ldxdw %r5, [%fp+-16]
+ add %r5, %r0
+ ldxb %r5, [%r5+0] /* t[r0] */
+ and %r5, 0xff
+
+ jle %r4, %r5, 2 /* if (s[r0] > t[r0]) return +1 */
+ mov %r0, 1
+ exit
+ jge %r4, %r5, 2 /* if (s[r0] < t[r0]) return +1 */
+ mov %r0, -1
+ exit
+
+.Lsame:
+ jle %r6, %r7, 2 /* if (r6 > r7) return +1 */
+ mov %r0, 1
+ exit
+ jge %r6, %r7, 2 /* if (r6 < r7) return -1 */
+ mov %r0, -1
+ exit
+
+.L0:
+ mov %r0, 0 /* return 0 */
+ exit
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index f5c724c4..ce54c354 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -276,7 +276,8 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
* multiple of 8
* - the greater of:
* + the maximum stack trace size
- * + four times the maximum string size (incl. length)
+ * + four times the maximum string size (incl. length
+ * and allowing round up to multiple of 8)
* plus the maximum string size (to accomodate the BPF
* verifier)
*/
@@ -285,7 +286,8 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
roundup(dtp->dt_maxreclen, 8) +
MAX(sizeof(uint64_t) * dtp->dt_options[DTRACEOPT_MAXFRAMES],
DT_TSTRING_SLOTS *
- (DT_STRLEN_BYTES + dtp->dt_options[DTRACEOPT_STRSIZE]) +
+ (DT_STRLEN_BYTES + 8 +
+ dtp->dt_options[DTRACEOPT_STRSIZE]) +
dtp->dt_options[DTRACEOPT_STRSIZE] + 1
);
if (create_gmap(dtp, "mem", BPF_MAP_TYPE_PERCPU_ARRAY,
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 391fd2d2..f25fb9f0 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -812,7 +812,7 @@ dt_cg_tstring_reset(dtrace_hdl_t *dtp)
ts = dtp->dt_tstrings;
for (i = 0; i < DT_TSTRING_SLOTS; i++, ts++)
- ts->offset = i * (DT_STRLEN_BYTES +
+ ts->offset = i * (DT_STRLEN_BYTES + 8 +
dtp->dt_options[DTRACEOPT_STRSIZE]);
}
@@ -2629,7 +2629,11 @@ dt_cg_compare_signed(dt_node_t *dnp)
if (dt_node_is_string(dnp->dn_left) ||
dt_node_is_string(dnp->dn_right))
- return 1; /* strings always compare signed */
+ /*
+ * String comparison looks at unsigned bytes, and
+ * "string op NULL" comparisons examine unsigned pointers.
+ */
+ return 0;
else if (!dt_node_is_arith(dnp->dn_left) ||
!dt_node_is_arith(dnp->dn_right))
return 0; /* non-arithmetic types always compare unsigned */
@@ -2648,10 +2652,57 @@ dt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
dt_cg_node(dnp->dn_left, dlp, drp);
dt_cg_node(dnp->dn_right, dlp, drp);
- /* FIXME: No support for string comparison yet */
- if (dt_node_is_string(dnp->dn_left) || dt_node_is_string(dnp->dn_right))
- xyerror(D_UNKNOWN, "internal error -- no support for "
- "string comparison yet\n");
+ /* by now, we have checked and both args are strings or neither is */
+ if (dt_node_is_string(dnp->dn_left) ||
+ dt_node_is_string(dnp->dn_right)) {
+ dt_ident_t *idp;
+ uint_t Lcomp = dt_irlist_label(dlp);
+ uint64_t off1, off2;
+
+ /* if either pointer is NULL, just compare pointers */
+ emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_left->dn_reg, 0, Lcomp));
+ emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_right->dn_reg, 0, Lcomp));
+
+ /*
+ * Otherwise, replace pointers with relative string values.
+ * Specifically, replace left with strcmp(left,right)+1 and
+ * right with 1, so we can use unsigned comparisons.
+ */
+
+ off1 = dt_cg_tstring_xalloc(yypcb);
+ off2 = dt_cg_tstring_xalloc(yypcb);
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, dnp->dn_left->dn_reg));
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, dnp->dn_right->dn_reg));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_3, BPF_REG_FP, DT_STK_DCTX));
+ emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_3, BPF_REG_3, DCTX_MEM));
+ 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));
+ idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_strcmp");
+ assert(idp != NULL);
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+ dt_regset_free_args(drp);
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1));
+ emit(dlp, BPF_MOV_REG(dnp->dn_left->dn_reg, BPF_REG_0));
+ dt_regset_free(drp, BPF_REG_0);
+ emit(dlp, BPF_MOV_IMM(dnp->dn_right->dn_reg, 1));
+
+ dt_cg_tstring_xfree(yypcb, off1);
+ dt_cg_tstring_xfree(yypcb, off2);
+
+ if (dnp->dn_left->dn_tstring)
+ dt_cg_tstring_free(yypcb, dnp->dn_left);
+ if (dnp->dn_right->dn_tstring)
+ dt_cg_tstring_free(yypcb, dnp->dn_right);
+
+ /* proceed with the comparison */
+ emitl(dlp, Lcomp,
+ BPF_NOP());
+ }
emit(dlp, BPF_BRANCH_REG(op, dnp->dn_left->dn_reg, dnp->dn_right->dn_reg, lbl_true));
dt_regset_free(drp, dnp->dn_right->dn_reg);
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index d87ccb5f..e65dc70b 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -59,6 +59,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_tvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_set_tvar, DT_IDENT_SYMBOL),
+ DT_BPF_SYMBOL(dt_strcmp, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strjoin, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_substr, DT_IDENT_SYMBOL),
/* BPF maps */
diff --git a/test/demo/builtin/probename.d b/test/demo/builtin/probename.d
index de5b1f79..b5ef1b6c 100644
--- a/test/demo/builtin/probename.d
+++ b/test/demo/builtin/probename.d
@@ -1,4 +1,3 @@
-/* @@xfail: dtv2 */
BEGIN {
exit(probename == "BEGIN" ? 0 : 1);
}
diff --git a/test/demo/builtin/probeprov.d b/test/demo/builtin/probeprov.d
index 410292c2..1850f97b 100644
--- a/test/demo/builtin/probeprov.d
+++ b/test/demo/builtin/probeprov.d
@@ -1,4 +1,3 @@
-/* @@xfail: dtv2 */
BEGIN {
exit(probeprov == "dtrace" ? 0 : 1);
}
diff --git a/test/demo/fbt/xioctl.d b/test/demo/fbt/xioctl.d
index fc74807d..75c18170 100644
--- a/test/demo/fbt/xioctl.d
+++ b/test/demo/fbt/xioctl.d
@@ -1,10 +1,9 @@
/*
* Oracle Linux DTrace.
- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2021, 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.
*/
-/* @@xfail: dtv2 */
/*
* To make the output more readable, we want to indent every function entry
diff --git a/test/unittest/dif/strncmp.d b/test/unittest/dif/strncmp.d
index cd008db6..1e5bfbde 100644
--- a/test/unittest/dif/strncmp.d
+++ b/test/unittest/dif/strncmp.d
@@ -1,4 +1,3 @@
-/* @@xfail: dtv2 */
BEGIN
{
rc = probename == "BEGIN" ? 0 : 1;
diff --git a/test/unittest/dtrace-util/tst.ListProbesFunc.sh b/test/unittest/dtrace-util/tst.ListProbesFunc.sh
index b4004e45..a311da21 100755
--- a/test/unittest/dtrace-util/tst.ListProbesFunc.sh
+++ b/test/unittest/dtrace-util/tst.ListProbesFunc.sh
@@ -1,11 +1,10 @@
#!/bin/bash
#
# Oracle Linux DTrace.
-# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2021, 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.
#
-# @@xfail: dtv2
##
#
diff --git a/test/unittest/dtrace-util/tst.ListProbesName.sh b/test/unittest/dtrace-util/tst.ListProbesName.sh
index 38b07e18..8f72493e 100755
--- a/test/unittest/dtrace-util/tst.ListProbesName.sh
+++ b/test/unittest/dtrace-util/tst.ListProbesName.sh
@@ -1,11 +1,10 @@
#!/bin/bash
#
# Oracle Linux DTrace.
-# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2021, 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.
#
-# @@xfail: dtv2
# @@timeout: 20
diff --git a/test/unittest/operators/tst.str_comparison-basic.d b/test/unittest/operators/tst.str_comparison-basic.d
new file mode 100644
index 00000000..344a2cf0
--- /dev/null
+++ b/test/unittest/operators/tst.str_comparison-basic.d
@@ -0,0 +1,74 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 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: String comparisons work.
+ *
+ * SECTION: Operators
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ nerrors = 0;
+
+ s1 = "abcdefghi";
+ s2 = "jklmnopqr";
+ s3 = "stuvwxyz!";
+
+ nerrors += (s1 <= s2 ? 0 : 1);
+ nerrors += (s1 < s2 ? 0 : 1);
+ nerrors += (s1 == s2 ? 1 : 0);
+ nerrors += (s1 != s2 ? 0 : 1);
+ nerrors += (s1 >= s2 ? 1 : 0);
+ nerrors += (s1 > s2 ? 1 : 0);
+
+ nerrors += (s2 <= s2 ? 0 : 1);
+ nerrors += (s2 < s2 ? 1 : 0);
+ nerrors += (s2 == s2 ? 0 : 1);
+ nerrors += (s2 != s2 ? 1 : 0);
+ nerrors += (s2 >= s2 ? 0 : 1);
+ nerrors += (s2 > s2 ? 1 : 0);
+
+ nerrors += (s3 <= s2 ? 1 : 0);
+ nerrors += (s3 < s2 ? 1 : 0);
+ nerrors += (s3 == s2 ? 1 : 0);
+ nerrors += (s3 != s2 ? 0 : 1);
+ nerrors += (s3 >= s2 ? 0 : 1);
+ nerrors += (s3 > s2 ? 0 : 1);
+
+ s2 = NULL;
+ nerrors += (s3 <= s2 ? 1 : 0);
+ nerrors += (s3 < s2 ? 1 : 0);
+ nerrors += (s3 == s2 ? 1 : 0);
+ nerrors += (s3 != s2 ? 0 : 1);
+ nerrors += (s3 >= s2 ? 0 : 0);
+ nerrors += (s3 > s2 ? 0 : 0);
+
+ nerrors += (s2 <= s3 ? 0 : 1);
+ nerrors += (s2 < s3 ? 0 : 1);
+ nerrors += (s2 == s3 ? 1 : 0);
+ nerrors += (s2 != s3 ? 0 : 1);
+ nerrors += (s2 >= s3 ? 1 : 0);
+ nerrors += (s2 > s3 ? 1 : 0);
+
+ s3 = NULL;
+ nerrors += (s2 <= s3 ? 0 : 1);
+ nerrors += (s2 < s3 ? 1 : 0);
+ nerrors += (s2 == s3 ? 0 : 1);
+ nerrors += (s2 != s3 ? 1 : 0);
+ nerrors += (s2 >= s3 ? 0 : 1);
+ nerrors += (s2 > s3 ? 1 : 0);
+
+ printf("%d errors\n", nerrors);
+ exit(nerrors == 0 ? 0 : 1);
+}
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/operators/tst.str_comparison-longer.d b/test/unittest/operators/tst.str_comparison-longer.d
new file mode 100644
index 00000000..2f92673e
--- /dev/null
+++ b/test/unittest/operators/tst.str_comparison-longer.d
@@ -0,0 +1,59 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 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: String comparisons work.
+ *
+ * SECTION: Operators
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ nerrors = 0;
+
+ s1 = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+ s2 = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~The quick brown fox jumped over the lazy dog. Now is the time for all good men to the aid of their party.";
+
+ nerrors += (s1 <= s2 ? 0 : 1);
+ nerrors += (s1 < s2 ? 0 : 1);
+ nerrors += (s1 == s2 ? 1 : 0);
+ nerrors += (s1 != s2 ? 0 : 1);
+ nerrors += (s1 >= s2 ? 1 : 0);
+ nerrors += (s1 > s2 ? 1 : 0);
+
+ nerrors += (s2 <= s1 ? 1 : 0);
+ nerrors += (s2 < s1 ? 1 : 0);
+ nerrors += (s2 == s1 ? 1 : 0);
+ nerrors += (s2 != s1 ? 0 : 1);
+ nerrors += (s2 >= s1 ? 0 : 1);
+ nerrors += (s2 > s1 ? 0 : 1);
+
+ s1 = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~The quick brown fox jumped over the lazy dog. Now is the time for all good men to the aid of their party. To infinity and beyond.";
+
+ nerrors += (s1 <= s2 ? 1 : 0);
+ nerrors += (s1 < s2 ? 1 : 0);
+ nerrors += (s1 == s2 ? 1 : 0);
+ nerrors += (s1 != s2 ? 0 : 1);
+ nerrors += (s1 >= s2 ? 0 : 1);
+ nerrors += (s1 > s2 ? 0 : 1);
+
+ nerrors += (s2 <= s1 ? 0 : 1);
+ nerrors += (s2 < s1 ? 0 : 1);
+ nerrors += (s2 == s1 ? 1 : 0);
+ nerrors += (s2 != s1 ? 0 : 1);
+ nerrors += (s2 >= s1 ? 1 : 0);
+ nerrors += (s2 > s1 ? 1 : 0);
+
+ printf("%d errors\n", nerrors);
+ exit(nerrors == 0 ? 0 : 1);
+}
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/operators/tst.str_comparison-nested.d b/test/unittest/operators/tst.str_comparison-nested.d
new file mode 100644
index 00000000..1352b9dd
--- /dev/null
+++ b/test/unittest/operators/tst.str_comparison-nested.d
@@ -0,0 +1,39 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 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: String comparisons work.
+ *
+ * SECTION: Operators
+ */
+
+#pragma D option quiet
+
+BEGIN {
+ trace
+ (strjoin("abc", "def") > strjoin("def", "abc") ? 1 :
+ (strjoin("ABC", "def") > strjoin("def", "ABC") ? 2 :
+ (strjoin("abc", "DEF") > strjoin("DEF", "abc") ? 3 :
+ (strjoin("ABC", "DEF") > strjoin("DEF", "ABC") ? 4 :
+ (strjoin("abc", "deF") > strjoin("deF", "abc") ? 5 :
+ (strjoin("ABC", "deF") > strjoin("deF", "ABC") ? 6 :
+ (strjoin("abc", "DEf") > strjoin("DEf", "abc") ? 7 :
+ (strjoin("ABC", "DEf") > strjoin("DEf", "ABC") ? 8 :
+ (strjoin("abC", "def") > strjoin("def", "abC") ? 9 :
+ (strjoin("ABc", "def") > strjoin("def", "ABc") ? 10 :
+ (strjoin("abC", "DEF") > strjoin("DEF", "abC") ? 11 :
+ (strjoin("ABc", "DEF") > strjoin("DEF", "ABc") ? 12 :
+ (strjoin("abC", "deF") > strjoin("deF", "abC") ? 13 :
+ (strjoin("ABc", "deF") > strjoin("deF", "ABc") ? 14 :
+ (strjoin("abC", "DEf") > strjoin("DEf", "abC") ? 15 :
+ (strjoin("ABc", "DEf") > strjoin("DEf", "ABc") ? 16 : 0))))))))))))))));
+ exit(0);
+}
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/operators/tst.str_comparison-nested.r b/test/unittest/operators/tst.str_comparison-nested.r
new file mode 100644
index 00000000..00750edc
--- /dev/null
+++ b/test/unittest/operators/tst.str_comparison-nested.r
@@ -0,0 +1 @@
+3
diff --git a/test/unittest/operators/tst.str_comparison-signed.d b/test/unittest/operators/tst.str_comparison-signed.d
new file mode 100644
index 00000000..0eb18d3d
--- /dev/null
+++ b/test/unittest/operators/tst.str_comparison-signed.d
@@ -0,0 +1,59 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 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: String comparisons work.
+ *
+ * SECTION: Operators
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ nerrors = 0;
+
+ s1 = "abcd\xfa";
+ s2 = "abcd\x0a";
+
+ nerrors += (s1 <= s2 ? 1 : 0);
+ nerrors += (s1 < s2 ? 1 : 0);
+ nerrors += (s1 == s2 ? 1 : 0);
+ nerrors += (s1 != s2 ? 0 : 1);
+ nerrors += (s1 >= s2 ? 0 : 1);
+ nerrors += (s1 > s2 ? 0 : 1);
+
+ nerrors += (s2 <= s1 ? 0 : 1);
+ nerrors += (s2 < s1 ? 0 : 1);
+ nerrors += (s2 == s1 ? 1 : 0);
+ nerrors += (s2 != s1 ? 0 : 1);
+ nerrors += (s2 >= s1 ? 1 : 0);
+ nerrors += (s2 > s1 ? 1 : 0);
+
+ s2 = "abcd";
+
+ nerrors += (s1 <= s2 ? 1 : 0);
+ nerrors += (s1 < s2 ? 1 : 0);
+ nerrors += (s1 == s2 ? 1 : 0);
+ nerrors += (s1 != s2 ? 0 : 1);
+ nerrors += (s1 >= s2 ? 0 : 1);
+ nerrors += (s1 > s2 ? 0 : 1);
+
+ nerrors += (s2 <= s1 ? 0 : 1);
+ nerrors += (s2 < s1 ? 0 : 1);
+ nerrors += (s2 == s1 ? 1 : 0);
+ nerrors += (s2 != s1 ? 0 : 1);
+ nerrors += (s2 >= s1 ? 1 : 0);
+ nerrors += (s2 > s1 ? 1 : 0);
+
+ printf("%d errors\n", nerrors);
+ exit(nerrors == 0 ? 0 : 1);
+}
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/types/tst.condexpr.d b/test/unittest/types/tst.condexpr.d
index d21115fc..be9d68a5 100644
--- a/test/unittest/types/tst.condexpr.d
+++ b/test/unittest/types/tst.condexpr.d
@@ -1,10 +1,9 @@
/*
* Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2021, 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.
*/
-/* @@xfail: dtv2 */
/*
* ASSERTION:
diff --git a/test/unittest/types/tst.relstring.d b/test/unittest/types/tst.relstring.d
index ab102647..d22beee5 100644
--- a/test/unittest/types/tst.relstring.d
+++ b/test/unittest/types/tst.relstring.d
@@ -1,10 +1,9 @@
/*
* Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2021, 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.
*/
-/* @@xfail: dtv2 */
/*
* ASSERTION:
--
2.18.4
More information about the DTrace-devel
mailing list