[DTrace-devel] [PATCH 2/2] Add support for substr() subroutine
Kris Van Hees
kris.van.hees at oracle.com
Thu Sep 2 08:34:09 PDT 2021
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
bpf/Build | 1 +
bpf/substr.S | 98 +++++++++++++++++++
libdtrace/dt_bpf.c | 3 +-
libdtrace/dt_cg.c | 59 ++++++++++-
libdtrace/dt_dlibs.c | 2 +-
.../err.D_PROTO_ARG.substr_non_scalar_arg2.d | 18 ++++
.../err.D_PROTO_ARG.substr_non_scalar_arg2.r | 4 +
.../err.D_PROTO_ARG.substr_non_scalar_arg3.d | 18 ++++
.../err.D_PROTO_ARG.substr_non_scalar_arg3.r | 4 +
.../err.D_PROTO_ARG.substr_non_string_arg1.d | 18 ++++
.../err.D_PROTO_ARG.substr_non_string_arg1.r | 4 +
.../err.D_PROTO_LEN.substr_missing_arg.d | 18 ++++
.../err.D_PROTO_LEN.substr_missing_arg.r | 2 +
.../err.D_PROTO_LEN.substr_too_few_args.d | 18 ++++
.../err.D_PROTO_LEN.substr_too_few_args.r | 2 +
.../err.D_PROTO_LEN.substr_too_many_args.d | 18 ++++
.../err.D_PROTO_LEN.substr_too_many_args.r | 2 +
.../funcs/substr/err.substr_null_arg1.d | 25 +++++
.../funcs/substr/err.substr_null_arg1.r | 3 +
.../{dif => funcs/substr}/substr2arg.d | 1 -
test/unittest/funcs/substr/substr2arg.r | 0
.../{dif => funcs/substr}/substr3arg.d | 1 -
test/unittest/funcs/substr/substr3arg.r | 0
.../funcs/substr/tst.substr-large-idx.d | 22 +++++
.../funcs/substr/tst.substr-large-idx.r | 1 +
.../substr/tst.substr-multi-const-cnt-neg.d | 30 ++++++
.../substr/tst.substr-multi-const-cnt-neg.r | 11 +++
.../substr/tst.substr-multi-const-cnt-pos.d | 31 ++++++
.../substr/tst.substr-multi-const-cnt-pos.r | 12 +++
.../substr/tst.substr-multi-const-idx-neg.d | 30 ++++++
.../substr/tst.substr-multi-const-idx-neg.r | 11 +++
.../substr/tst.substr-multi-const-idx-pos.d | 31 ++++++
.../substr/tst.substr-multi-const-idx-pos.r | 12 +++
.../substr/tst.substr-multi-var-cnt-neg.d | 40 ++++++++
.../substr/tst.substr-multi-var-cnt-neg.r | 11 +++
.../substr/tst.substr-multi-var-cnt-pos.d | 42 ++++++++
.../substr/tst.substr-multi-var-cnt-pos.r | 12 +++
.../substr/tst.substr-multi-var-idx-neg.d | 40 ++++++++
.../substr/tst.substr-multi-var-idx-neg.r | 11 +++
.../substr/tst.substr-multi-var-idx-pos.d | 42 ++++++++
.../substr/tst.substr-multi-var-idx-pos.r | 12 +++
.../funcs/substr/tst.substr-strjoin.d | 33 +++++++
.../funcs/substr/tst.substr-strjoin.r | 1 +
test/unittest/funcs/{ => substr}/tst.substr.d | 0
test/unittest/funcs/{ => substr}/tst.substr.r | 0
.../funcs/{ => substr}/tst.substrminate.d | 0
.../funcs/{ => substr}/tst.substrminate.r | 0
47 files changed, 748 insertions(+), 6 deletions(-)
create mode 100644 bpf/substr.S
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.d
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.r
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.d
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.r
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.d
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.r
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.d
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.r
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.d
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.r
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.d
create mode 100644 test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.r
create mode 100644 test/unittest/funcs/substr/err.substr_null_arg1.d
create mode 100644 test/unittest/funcs/substr/err.substr_null_arg1.r
rename test/unittest/{dif => funcs/substr}/substr2arg.d (71%)
create mode 100644 test/unittest/funcs/substr/substr2arg.r
rename test/unittest/{dif => funcs/substr}/substr3arg.d (72%)
create mode 100644 test/unittest/funcs/substr/substr3arg.r
create mode 100644 test/unittest/funcs/substr/tst.substr-large-idx.d
create mode 100644 test/unittest/funcs/substr/tst.substr-large-idx.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.r
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.d
create mode 100644 test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.r
create mode 100644 test/unittest/funcs/substr/tst.substr-strjoin.d
create mode 100644 test/unittest/funcs/substr/tst.substr-strjoin.r
rename test/unittest/funcs/{ => substr}/tst.substr.d (100%)
rename test/unittest/funcs/{ => substr}/tst.substr.r (100%)
rename test/unittest/funcs/{ => substr}/tst.substrminate.d (100%)
rename test/unittest/funcs/{ => substr}/tst.substrminate.r (100%)
diff --git a/bpf/Build b/bpf/Build
index d7dbbd5a..5ea497a3 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -27,6 +27,7 @@ bpf_dlib_SOURCES = \
get_tvar.c set_tvar.c \
probe_error.c \
strjoin.S \
+ substr.S \
strlen.c
bpf-check: $(objdir)/include/.dir.stamp
diff --git a/bpf/substr.S b/bpf/substr.S
new file mode 100644
index 00000000..9e032441
--- /dev/null
+++ b/bpf/substr.S
@@ -0,0 +1,98 @@
+// 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
+
+/*
+ * void dt_substr(char *dst, const char *src, int32_t idx, int32_t cnt,
+ * uint64_t argc)
+ */
+ .text
+ .align 4
+ .global dt_substr
+dt_substr :
+ stxdw [%fp+-8], %r1 /* Spill dst */
+ mov %r9, %r1
+ stxdw [%fp+-16], %r2 /* Spill src */
+ lsh %r3, 32 /* Sign-extend idx */
+ arsh %r3, 32
+ mov %r6, %r3 /* %r6 = idx */
+
+ lddw %r8, STRSZ /* %r8 = STRSZ (temporary) */
+ jgt %r5, 2, .Lhave_cnt
+ mov %r4, %r8 /* cnt = STRSZ */
+.Lhave_cnt:
+ lsh %r4, 32 /* Sign-extend cnt */
+ arsh %r4, 32
+ mov %r7, %r4 /* %r7 = cnt */
+
+ /*
+ * Get the source string length and validate it. If the length is 0,
+ * the result is the empty string. If the length is greater than the
+ * maximum string length (STRSZ), cap it at that value.
+ */
+ ldxdw %r1, [%fp+-16]
+ call dt_strlen /* len = dt_strlen(src) */
+ jeq %r0, 0, .Lempty
+ mov %r1, %r8 /* %r1 = STRSZ */
+ jle %r0, %r8, .Llen_ok
+ mov %r0, %r8 /* len = STRSZ */
+.Llen_ok:
+ mov %r8, %r0 /* %r8 = len */
+
+ jsge %r6, 0, .Ladjust_cnt
+
+.Lidx_neg:
+ add %r6, %r8 /* idx += len */
+ jsge %r6, 0, .Ladjust_cnt
+ mov %r0, 0
+ sub32 %r0, %r6 /* neg messes up the verifier */
+ jsle %r7, %r0, .Ladjust_cnt
+ add32 %r7, %r6 /* cnt += idx */
+ mov %r6, 0 /* idx = 0 */
+
+.Ladjust_cnt:
+ jsge %r6, %r1, .Lempty
+ jsge %r6, %r8, .Lempty
+ jslt %r6, 0, .Lempty
+ jsge %r7, 0, .Lcnt_pos
+ mov %r0, %r8
+ sub32 %r0, %r6
+ add32 %r7, %r0 /* cnt += len - idx */
+ lsh %r7, 32
+ arsh %r7, 32
+ jsle %r7, 0, .Lempty
+.Lcnt_pos:
+ sub %r1, %r6
+ jsge %r1, %r7, .Lcopy
+ mov %r7, %r1 /* cnt = STRSZ - idx */
+
+.Lcopy:
+ ldxdw %r8, [%fp+-16]
+ add %r8, DT_STRLEN_BYTES
+ add %r8, %r6 /* %r8 = src + DT_STRLEN_BYTES + idx */
+
+ mov %r1, %r7
+ ldxdw %r2, [%fp+-8]
+ mov %r9, %r2 /* %r9 = dst */
+ call dt_strlen_store /* plen = dt_strlen_store(cnt, dst) */
+ add %r9, DT_STRLEN_BYTES /* %r9 = dst + DT_STRLEN_BYTES */
+
+ mov %r1, %r9
+ mov %r2, %r7
+ mov %r3, %r8
+ call BPF_FUNC_probe_read
+
+ add %r9, %r7
+ stb [%r9+0],0
+ exit
+
+.Lempty:
+ /* Store the empty string in the destination. */
+ stb [%r9+0], 0
+ stb [%r9+1], 0
+ exit
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index b6e44a6e..58de3b4a 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -297,8 +297,7 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
* value that is used to store the strtab.
*/
dtp->dt_strlen = dt_strtab_size(dtp->dt_ccstab);
- stabsz = dtp->dt_strlen +
- ctf_type_size(DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ stabsz = dtp->dt_strlen + dtp->dt_options[DTRACEOPT_STRSIZE];
dtp->dt_strtab = dt_zalloc(dtp, stabsz);
if (dtp->dt_strtab == NULL)
return dt_set_errno(dtp, EDT_NOMEM);
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index b48b9f7b..749324e4 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3149,6 +3149,63 @@ dt_cg_subr_strjoin(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
TRACE_REGSET(" subr-strjoin:End ");
}
+static void
+dt_cg_subr_substr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+ dt_node_t *str = dnp->dn_args;
+ dt_node_t *idx = str->dn_list;
+ dt_node_t *cnt = idx->dn_list;
+ dt_ident_t *idp;
+
+ TRACE_REGSET(" subr-substr:Begin");
+
+ dt_cg_node(str, dlp, drp);
+ dt_cg_check_notnull(dlp, drp, str->dn_reg);
+ dt_cg_node(idx, dlp, drp);
+ if (cnt != NULL)
+ dt_cg_node(cnt, dlp, drp);
+
+ /*
+ * Allocate the result register and associate it with a temporary
+ * string slot.
+ */
+ dnp->dn_reg = dt_regset_alloc(drp);
+ if (dnp->dn_reg == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dt_node_tstring(dnp, dt_cg_tstring_alloc());
+
+ emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_DCTX));
+ emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, dnp->dn_reg, DCTX_MEM));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, dnp->dn_reg));
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, str->dn_reg));
+ dt_regset_free(drp, str->dn_reg);
+ if (str->dn_tstring)
+ dt_cg_tstring_free(str->dn_tstring->dn_value);
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, idx->dn_reg));
+ dt_regset_free(drp, idx->dn_reg);
+ if (cnt != NULL) {
+ emit(dlp, BPF_MOV_REG(BPF_REG_4, cnt->dn_reg));
+ dt_regset_free(drp, cnt->dn_reg);
+ emit(dlp, BPF_MOV_IMM(BPF_REG_5, 3));
+ } else {
+ emit(dlp, BPF_MOV_IMM(BPF_REG_4, 0));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_5, 2));
+ }
+ dt_regset_xalloc(drp, BPF_REG_0);
+ idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_substr");
+ assert(idp != NULL);
+ emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+ dt_regset_free_args(drp);
+ dt_regset_free(drp, BPF_REG_0);
+
+ TRACE_REGSET(" subr-substr:End ");
+}
+
typedef void dt_cg_subr_f(dt_node_t *, dt_irlist_t *, dt_regset_t *);
static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
@@ -3184,7 +3241,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_STRRCHR] = NULL,
[DIF_SUBR_STRSTR] = NULL,
[DIF_SUBR_STRTOK] = NULL,
- [DIF_SUBR_SUBSTR] = NULL,
+ [DIF_SUBR_SUBSTR] = &dt_cg_subr_substr,
[DIF_SUBR_INDEX] = NULL,
[DIF_SUBR_RINDEX] = NULL,
[DIF_SUBR_HTONS] = NULL,
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 771b7fe0..d87ccb5f 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -60,7 +60,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
DT_BPF_SYMBOL(dt_get_tvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_set_tvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_strjoin, DT_IDENT_SYMBOL),
- DT_BPF_SYMBOL(dt_strnlen, DT_IDENT_SYMBOL),
+ DT_BPF_SYMBOL(dt_substr, DT_IDENT_SYMBOL),
/* BPF maps */
DT_BPF_SYMBOL(aggs, DT_IDENT_PTR),
DT_BPF_SYMBOL(buffers, DT_IDENT_PTR),
diff --git a/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.d b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.d
new file mode 100644
index 00000000..bb2dc33a
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.d
@@ -0,0 +1,18 @@
+/*
+ * 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: The second argument to substr() should be a scalar.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+BEGIN
+{
+ trace(substr(probename, "a"));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.r b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.r
new file mode 100644
index 00000000..14a7e7f5
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg2.d: [D_PROTO_ARG] line 16: substr( ) argument #2 is incompatible with prototype:
+ prototype: int
+ argument: string
diff --git a/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.d b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.d
new file mode 100644
index 00000000..147ec362
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.d
@@ -0,0 +1,18 @@
+/*
+ * 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: The third argument to substr() should be a scalar.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+BEGIN
+{
+ trace(substr(probename, 1, "a"));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.r b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.r
new file mode 100644
index 00000000..102aef8e
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_scalar_arg3.d: [D_PROTO_ARG] line 16: substr( ) argument #3 is incompatible with prototype:
+ prototype: int
+ argument: string
diff --git a/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.d b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.d
new file mode 100644
index 00000000..bd9d1319
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.d
@@ -0,0 +1,18 @@
+/*
+ * 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: The first argument to substr() should be a string.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+BEGIN
+{
+ trace(substr(10, 1));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.r b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.r
new file mode 100644
index 00000000..85210c3c
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/substr/err.D_PROTO_ARG.substr_non_string_arg1.d: [D_PROTO_ARG] line 16: substr( ) argument #1 is incompatible with prototype:
+ prototype: char *
+ argument: int
diff --git a/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.d b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.d
new file mode 100644
index 00000000..c254e38a
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.d
@@ -0,0 +1,18 @@
+/*
+ * 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: substr() requires a string argument
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+BEGIN
+{
+ trace(substr());
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.r b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.r
new file mode 100644
index 00000000..b24cef0c
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/substr/err.D_PROTO_LEN.substr_missing_arg.d: [D_PROTO_LEN] line 16: substr( ) prototype mismatch: 0 args passed, at least 2 expected
diff --git a/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.d b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.d
new file mode 100644
index 00000000..2d6eccac
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.d
@@ -0,0 +1,18 @@
+/*
+ * 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: The substr() subroutine requires at least 2 arguments.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+BEGIN
+{
+ trace(substr(probename));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.r b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.r
new file mode 100644
index 00000000..5697f41f
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_few_args.d: [D_PROTO_LEN] line 16: substr( ) prototype mismatch: 1 arg passed, at least 2 expected
diff --git a/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.d b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.d
new file mode 100644
index 00000000..d69e93e6
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.d
@@ -0,0 +1,18 @@
+/*
+ * 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: The substr() subroutine accepts no more than three arguments.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+BEGIN
+{
+ trace(substr(probename, 1, 2, 3));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.r b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.r
new file mode 100644
index 00000000..1f82676f
--- /dev/null
+++ b/test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/substr/err.D_PROTO_LEN.substr_too_many_args.d: [D_PROTO_LEN] line 16: substr( ) prototype mismatch: 4 args passed, at most 3 expected
diff --git a/test/unittest/funcs/substr/err.substr_null_arg1.d b/test/unittest/funcs/substr/err.substr_null_arg1.d
new file mode 100644
index 00000000..50f9091e
--- /dev/null
+++ b/test/unittest/funcs/substr/err.substr_null_arg1.d
@@ -0,0 +1,25 @@
+/*
+ * 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: The first argument to substr() cannot be NULL.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(substr(0, 1));
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/substr/err.substr_null_arg1.r b/test/unittest/funcs/substr/err.substr_null_arg1.r
new file mode 100644
index 00000000..ef424aed
--- /dev/null
+++ b/test/unittest/funcs/substr/err.substr_null_arg1.r
@@ -0,0 +1,3 @@
+
+-- @@stderr --
+dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1
diff --git a/test/unittest/dif/substr2arg.d b/test/unittest/funcs/substr/substr2arg.d
similarity index 71%
rename from test/unittest/dif/substr2arg.d
rename to test/unittest/funcs/substr/substr2arg.d
index b29c601b..33670550 100644
--- a/test/unittest/dif/substr2arg.d
+++ b/test/unittest/funcs/substr/substr2arg.d
@@ -1,4 +1,3 @@
-/* @@xfail: dtv2 */
BEGIN
{
trace(substr(probename, 2));
diff --git a/test/unittest/funcs/substr/substr2arg.r b/test/unittest/funcs/substr/substr2arg.r
new file mode 100644
index 00000000..e69de29b
diff --git a/test/unittest/dif/substr3arg.d b/test/unittest/funcs/substr/substr3arg.d
similarity index 72%
rename from test/unittest/dif/substr3arg.d
rename to test/unittest/funcs/substr/substr3arg.d
index e2768b0a..8958acac 100644
--- a/test/unittest/dif/substr3arg.d
+++ b/test/unittest/funcs/substr/substr3arg.d
@@ -1,4 +1,3 @@
-/* @@xfail: dtv2 */
BEGIN
{
trace(substr(probename, 0, 2));
diff --git a/test/unittest/funcs/substr/substr3arg.r b/test/unittest/funcs/substr/substr3arg.r
new file mode 100644
index 00000000..e69de29b
diff --git a/test/unittest/funcs/substr/tst.substr-large-idx.d b/test/unittest/funcs/substr/tst.substr-large-idx.d
new file mode 100644
index 00000000..654a05e9
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-large-idx.d
@@ -0,0 +1,22 @@
+/*
+ * 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: The substr() subroutine supports index values well beyond the
+ * maximum string size.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+#pragma D option strsize=256
+
+BEGIN
+{
+ trace(substr("abcdefgh", 12345678));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-large-idx.r b/test/unittest/funcs/substr/tst.substr-large-idx.r
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-large-idx.r
@@ -0,0 +1 @@
+
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.d b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.d
new file mode 100644
index 00000000..c6e1230f
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.d
@@ -0,0 +1,30 @@
+/*
+ * 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: The substr() subroutine supports negative count values passed as
+ * constants.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ printf("\n% 3d % 3d %s", 2, -10, substr("abcdefghijklmnop", 2, -10));
+ printf("\n% 3d % 3d %s", 2, -9, substr("abcdefghijklmnop", 2, -9));
+ printf("\n% 3d % 3d %s", 2, -8, substr("abcdefghijklmnop", 2, -8));
+ printf("\n% 3d % 3d %s", 2, -7, substr("abcdefghijklmnop", 2, -7));
+ printf("\n% 3d % 3d %s", 2, -6, substr("abcdefghijklmnop", 2, -6));
+ printf("\n% 3d % 3d %s", 2, -5, substr("abcdefghijklmnop", 2, -5));
+ printf("\n% 3d % 3d %s", 2, -4, substr("abcdefghijklmnop", 2, -4));
+ printf("\n% 3d % 3d %s", 2, -3, substr("abcdefghijklmnop", 2, -3));
+ printf("\n% 3d % 3d %s", 2, -2, substr("abcdefghijklmnop", 2, -2));
+ printf("\n% 3d % 3d %s", 2, -1, substr("abcdefghijklmnop", 2, -1));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.r b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.r
new file mode 100644
index 00000000..555db8e0
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-neg.r
@@ -0,0 +1,11 @@
+
+ 2 -10 cdef
+ 2 -9 cdefg
+ 2 -8 cdefgh
+ 2 -7 cdefghi
+ 2 -6 cdefghij
+ 2 -5 cdefghijk
+ 2 -4 cdefghijkl
+ 2 -3 cdefghijklm
+ 2 -2 cdefghijklmn
+ 2 -1 cdefghijklmno
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.d b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.d
new file mode 100644
index 00000000..607df972
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.d
@@ -0,0 +1,31 @@
+/*
+ * 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: The substr() subroutine supports positive count values passed as
+ * constants.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ printf("\n% 3d % 3d %s", 2, 0, substr("abcdefghijklmnop", 2, 0));
+ printf("\n% 3d % 3d %s", 2, 1, substr("abcdefghijklmnop", 2, 1));
+ printf("\n% 3d % 3d %s", 2, 2, substr("abcdefghijklmnop", 2, 2));
+ printf("\n% 3d % 3d %s", 2, 3, substr("abcdefghijklmnop", 2, 3));
+ printf("\n% 3d % 3d %s", 2, 4, substr("abcdefghijklmnop", 2, 4));
+ printf("\n% 3d % 3d %s", 2, 5, substr("abcdefghijklmnop", 2, 5));
+ printf("\n% 3d % 3d %s", 2, 6, substr("abcdefghijklmnop", 2, 6));
+ printf("\n% 3d % 3d %s", 2, 7, substr("abcdefghijklmnop", 2, 7));
+ printf("\n% 3d % 3d %s", 2, 8, substr("abcdefghijklmnop", 2, 8));
+ printf("\n% 3d % 3d %s", 2, 9, substr("abcdefghijklmnop", 2, 9));
+ printf("\n% 3d % 3d %s", 2, 10, substr("abcdefghijklmnop", 2, 10));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.r b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.r
new file mode 100644
index 00000000..88b87861
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-cnt-pos.r
@@ -0,0 +1,12 @@
+
+ 2 0
+ 2 1 c
+ 2 2 cd
+ 2 3 cde
+ 2 4 cdef
+ 2 5 cdefg
+ 2 6 cdefgh
+ 2 7 cdefghi
+ 2 8 cdefghij
+ 2 9 cdefghijk
+ 2 10 cdefghijkl
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.d b/test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.d
new file mode 100644
index 00000000..d69af788
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.d
@@ -0,0 +1,30 @@
+/*
+ * 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: The substr() subroutine supports negative index values passed as
+ * constants.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ printf("\n% 3d % 3d %s", -10, 3, substr("abcdefghijklmnop", -10, 3));
+ printf("\n% 3d % 3d %s", -9, 3, substr("abcdefghijklmnop", -9, 3));
+ printf("\n% 3d % 3d %s", -8, 3, substr("abcdefghijklmnop", -8, 3));
+ printf("\n% 3d % 3d %s", -7, 3, substr("abcdefghijklmnop", -7, 3));
+ printf("\n% 3d % 3d %s", -6, 3, substr("abcdefghijklmnop", -6, 3));
+ printf("\n% 3d % 3d %s", -5, 3, substr("abcdefghijklmnop", -5, 3));
+ printf("\n% 3d % 3d %s", -4, 3, substr("abcdefghijklmnop", -4, 3));
+ printf("\n% 3d % 3d %s", -3, 3, substr("abcdefghijklmnop", -3, 3));
+ printf("\n% 3d % 3d %s", -2, 3, substr("abcdefghijklmnop", -2, 3));
+ printf("\n% 3d % 3d %s", -1, 3, substr("abcdefghijklmnop", -1, 3));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.r b/test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.r
new file mode 100644
index 00000000..d8dc0dbd
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-idx-neg.r
@@ -0,0 +1,11 @@
+
+-10 3 ghi
+ -9 3 hij
+ -8 3 ijk
+ -7 3 jkl
+ -6 3 klm
+ -5 3 lmn
+ -4 3 mno
+ -3 3 nop
+ -2 3 op
+ -1 3 p
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.d b/test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.d
new file mode 100644
index 00000000..558b747f
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.d
@@ -0,0 +1,31 @@
+/*
+ * 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: The substr() subroutine supports positive index values passed as
+ * constants.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ printf("\n% 3d % 3d %s", 0, 3, substr("abcdefghijklmnop", 0, 3));
+ printf("\n% 3d % 3d %s", 1, 3, substr("abcdefghijklmnop", 1, 3));
+ printf("\n% 3d % 3d %s", 2, 3, substr("abcdefghijklmnop", 2, 3));
+ printf("\n% 3d % 3d %s", 3, 3, substr("abcdefghijklmnop", 3, 3));
+ printf("\n% 3d % 3d %s", 4, 3, substr("abcdefghijklmnop", 4, 3));
+ printf("\n% 3d % 3d %s", 5, 3, substr("abcdefghijklmnop", 5, 3));
+ printf("\n% 3d % 3d %s", 6, 3, substr("abcdefghijklmnop", 6, 3));
+ printf("\n% 3d % 3d %s", 7, 3, substr("abcdefghijklmnop", 7, 3));
+ printf("\n% 3d % 3d %s", 8, 3, substr("abcdefghijklmnop", 8, 3));
+ printf("\n% 3d % 3d %s", 9, 3, substr("abcdefghijklmnop", 9, 3));
+ printf("\n% 3d % 3d %s", 10, 3, substr("abcdefghijklmnop", 10, 3));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.r b/test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.r
new file mode 100644
index 00000000..bf1f462f
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-const-idx-pos.r
@@ -0,0 +1,12 @@
+
+ 0 3 abc
+ 1 3 bcd
+ 2 3 cde
+ 3 3 def
+ 4 3 efg
+ 5 3 fgh
+ 6 3 ghi
+ 7 3 hij
+ 8 3 ijk
+ 9 3 jkl
+ 10 3 klm
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.d b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.d
new file mode 100644
index 00000000..84b6efcb
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.d
@@ -0,0 +1,40 @@
+/*
+ * 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: The substr() subroutine supports negative count values passed by
+ * variable.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ cnt = -10;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -9;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -8;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -7;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -6;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -5;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -4;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -3;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -2;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = -1;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.r b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.r
new file mode 100644
index 00000000..555db8e0
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-neg.r
@@ -0,0 +1,11 @@
+
+ 2 -10 cdef
+ 2 -9 cdefg
+ 2 -8 cdefgh
+ 2 -7 cdefghi
+ 2 -6 cdefghij
+ 2 -5 cdefghijk
+ 2 -4 cdefghijkl
+ 2 -3 cdefghijklm
+ 2 -2 cdefghijklmn
+ 2 -1 cdefghijklmno
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.d b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.d
new file mode 100644
index 00000000..7bd234ad
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.d
@@ -0,0 +1,42 @@
+/*
+ * 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: The substr() subroutine supports positive count values passed by
+ * variable.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ cnt = 0;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 1;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 2;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 3;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 4;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 5;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 6;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 7;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 8;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 9;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ cnt = 10;
+ printf("\n% 3d % 3d %s", 2, cnt, substr("abcdefghijklmnop", 2, cnt));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.r b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.r
new file mode 100644
index 00000000..88b87861
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-cnt-pos.r
@@ -0,0 +1,12 @@
+
+ 2 0
+ 2 1 c
+ 2 2 cd
+ 2 3 cde
+ 2 4 cdef
+ 2 5 cdefg
+ 2 6 cdefgh
+ 2 7 cdefghi
+ 2 8 cdefghij
+ 2 9 cdefghijk
+ 2 10 cdefghijkl
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.d b/test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.d
new file mode 100644
index 00000000..232e2f5f
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.d
@@ -0,0 +1,40 @@
+/*
+ * 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: The substr() subroutine supports negative index values passed by
+ * variable.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ idx = -10;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -9;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -8;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -7;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -6;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -5;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -4;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -3;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -2;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = -1;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.r b/test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.r
new file mode 100644
index 00000000..d8dc0dbd
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-idx-neg.r
@@ -0,0 +1,11 @@
+
+-10 3 ghi
+ -9 3 hij
+ -8 3 ijk
+ -7 3 jkl
+ -6 3 klm
+ -5 3 lmn
+ -4 3 mno
+ -3 3 nop
+ -2 3 op
+ -1 3 p
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.d b/test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.d
new file mode 100644
index 00000000..eb38999e
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.d
@@ -0,0 +1,42 @@
+/*
+ * 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: The substr() subroutine supports positive index values passed by
+ * variable.
+ *
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ idx = 0;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 1;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 2;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 3;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 4;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 5;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 6;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 7;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 8;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 9;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ idx = 10;
+ printf("\n% 3d % 3d %s", idx, 3, substr("abcdefghijklmnop", idx, 3));
+ exit(0);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.r b/test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.r
new file mode 100644
index 00000000..bf1f462f
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-multi-var-idx-pos.r
@@ -0,0 +1,12 @@
+
+ 0 3 abc
+ 1 3 bcd
+ 2 3 cde
+ 3 3 def
+ 4 3 efg
+ 5 3 fgh
+ 6 3 ghi
+ 7 3 hij
+ 8 3 ijk
+ 9 3 jkl
+ 10 3 klm
diff --git a/test/unittest/funcs/substr/tst.substr-strjoin.d b/test/unittest/funcs/substr/tst.substr-strjoin.d
new file mode 100644
index 00000000..f844d261
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-strjoin.d
@@ -0,0 +1,33 @@
+/*
+ * 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: Combining strjoin) and substr() works.
+ *
+ * SECTION: Actions and Subroutines/strjoin()
+ * SECTION: Actions and Subroutines/substr()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace(
+ substr(
+ strjoin(
+ strjoin(substr(probeprov, 0, 2), substr(probeprov, 2)),
+ strjoin(substr(probename, 0, 3), substr(probename, 3))
+ ), 6, 3
+ )
+ );
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/substr/tst.substr-strjoin.r b/test/unittest/funcs/substr/tst.substr-strjoin.r
new file mode 100644
index 00000000..f7836aea
--- /dev/null
+++ b/test/unittest/funcs/substr/tst.substr-strjoin.r
@@ -0,0 +1 @@
+BEG
diff --git a/test/unittest/funcs/tst.substr.d b/test/unittest/funcs/substr/tst.substr.d
similarity index 100%
rename from test/unittest/funcs/tst.substr.d
rename to test/unittest/funcs/substr/tst.substr.d
diff --git a/test/unittest/funcs/tst.substr.r b/test/unittest/funcs/substr/tst.substr.r
similarity index 100%
rename from test/unittest/funcs/tst.substr.r
rename to test/unittest/funcs/substr/tst.substr.r
diff --git a/test/unittest/funcs/tst.substrminate.d b/test/unittest/funcs/substr/tst.substrminate.d
similarity index 100%
rename from test/unittest/funcs/tst.substrminate.d
rename to test/unittest/funcs/substr/tst.substrminate.d
diff --git a/test/unittest/funcs/tst.substrminate.r b/test/unittest/funcs/substr/tst.substrminate.r
similarity index 100%
rename from test/unittest/funcs/tst.substrminate.r
rename to test/unittest/funcs/substr/tst.substrminate.r
--
2.33.0
More information about the DTrace-devel
mailing list