[DTrace-devel] [PATCH 1/8] Add support for string comparisons

Kris Van Hees kris.van.hees at oracle.com
Thu Oct 14 10:10:25 PDT 2021


On Wed, Sep 29, 2021 at 11:13:34AM -0400, eugene.loh at oracle.com wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
> 
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>

Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>

... with small changes a outlined below.  I made the changes already and
added the patch to my staging dev branch.

Nice work!

> ---
>  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

Added:
	.type	dt_strcmp_xor, @function

> +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

Added:
	.size	dt_strcmp_xor, .-dt_strcmp_xor

(and the same for the other two functions in this file)

> +
> +/*
> + * 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]) +

Per your updated comment above, this should be:

			roundup(DT_STRLEN_BYTES +
				dtp->dt_options[DTRACEOPT_STRSIZE], 8) +

>  		    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]);

Adjusted to be (as above):

			ts->offset = i *
				roundup(DT_STRLEN_BYTES +
					dtp->dt_options[DTRACEOPT_STRSIZE], 8);

>  	}
>  
> @@ -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
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list