[DTrace-devel] [PATCH v4] Add support for uregs[]

eugene.loh at oracle.com eugene.loh at oracle.com
Sat Feb 25 07:14:40 UTC 2023


From: Eugene Loh <eugene.loh at oracle.com>

The uregs[] essentially access (struct pt_regs) for the current task.
Therefore, we use the combination of BPF helper functions
bpf_task_pt_regs(bpf_get_current_task_btf()) to access pt_regs.

Note that older kernels might not support these helper functions.
So dt_bpf_init_helpers() checks, and if the needed functions are
missing an error results.

One place to put uregs[] support is in bpf/get_bvar.c.  On the other
hand, that means that the build system needs a gcc-bpf-unknown-none
that knows about these functions.  So, just generate the code ourselves
to call the two helper functions;  this is not much more difficult
than calling dt_get_bvar().

Further note that the documented symbolic indices to uregs[] seem
incorrect.  For x86, R_UESP is documented but not defined, and there
are many more indices that are defined but not documented.  For ARM,
the documented indices bear little resemblance to the defined (and
sensible!) values.

The support for symbolic indices to uregs[] on x86 mimics that found
in the legacy DTrace port to Linux -- that is, dtrace_getreg() from
kernel code arch/x86/dtrace/dtrace_isa_x86_64.c .  The logic is
convoluted and possibly incorrect.  Some uregs[] indices do not read
from (struct pt_regs) but from task->thread.*, complicating the
implementation.  This matter warrants further attention, but for now
mimicking the legacy port seems sufficient.

For the time being, there is no annotating disassembly with "uregs".
This can be added back in a future patch once other dust has settled.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/arm64/regs.d                        |   6 +-
 libdtrace/dt_bpf.c                            |   2 +
 libdtrace/dt_cg.c                             | 112 ++++++++-
 libdtrace/i386/regs.d                         |  20 +-
 test/demo/builtin/uregs.sparc64.aarch64.x     |   2 -
 test/demo/builtin/uregs.sparc64.d             | 233 ------------------
 test/demo/builtin/uregs.sparc64.x86_64.x      |   2 -
 test/demo/builtin/uregs.x86_64.aarch64.x      |   2 -
 test/demo/builtin/uregs.x86_64.d              |  76 ------
 test/demo/builtin/uregs.x86_64.sparc64.x      |   2 -
 .../arrays/err.D_PROTO_ARG.uregs_variable.d   |  19 ++
 .../arrays/err.D_PROTO_ARG.uregs_variable.r   |   4 +
 .../err.D_UNKNOWN.uregs_badkernelversion.d    |  19 ++
 .../err.D_UNKNOWN.uregs_badkernelversion.r    |   2 +
 .../err.D_UNKNOWN.uregs_badkernelversion.x    |  13 +
 .../err.D_UNKNOWN.uregs_toobig.aarch64.d      |  20 ++
 .../err.D_UNKNOWN.uregs_toobig.aarch64.r      |   2 +
 .../err.D_UNKNOWN.uregs_toobig.aarch64.x      |   4 +
 .../err.D_UNKNOWN.uregs_toobig.x86_64.d       |  20 ++
 .../err.D_UNKNOWN.uregs_toobig.x86_64.r       |   2 +
 .../err.D_UNKNOWN.uregs_toobig.x86_64.x       |   4 +
 test/unittest/arrays/tst.uregsarray-check.sh  | 121 +++++++++
 test/unittest/arrays/tst.uregsarray-check.x   |  13 +
 .../arrays/tst.uregsarray-constants.aarch64.d |  56 +++++
 .../arrays/tst.uregsarray-constants.aarch64.r |   2 +
 .../arrays/tst.uregsarray-constants.aarch64.x |   4 +
 .../arrays/tst.uregsarray-constants.x86_64.d  |  44 ++++
 .../arrays/tst.uregsarray-constants.x86_64.r  |   2 +
 .../arrays/tst.uregsarray-constants.x86_64.x  |   4 +
 test/unittest/arrays/tst.uregsarray.arm64.d   |   3 +-
 test/unittest/arrays/tst.uregsarray.arm64.x   |  17 +-
 test/unittest/arrays/tst.uregsarray.d         |   4 +-
 test/unittest/arrays/tst.uregsarray.x         |  13 +
 test/unittest/arrays/tst.uregsarray.x86_64.d  |   3 +-
 test/unittest/arrays/tst.uregsarray.x86_64.x  |  17 +-
 test/unittest/disasm/tst.ann-bvar.r           |   1 -
 test/unittest/disasm/tst.ann-bvar.sh          |   1 -
 test/unittest/disasm/tst.vartab-bvar-uregs0.r |   2 +
 .../unittest/disasm/tst.vartab-bvar-uregs0.sh |  59 +++++
 test/unittest/disasm/tst.vartab-bvar-uregs0.x |  13 +
 test/unittest/disasm/tst.vartab-bvar.r        |   1 -
 test/unittest/disasm/tst.vartab-bvar.sh       |   2 +-
 test/unittest/variables/bvar/tst.uregs.d      |  24 --
 43 files changed, 600 insertions(+), 372 deletions(-)
 delete mode 100755 test/demo/builtin/uregs.sparc64.aarch64.x
 delete mode 100644 test/demo/builtin/uregs.sparc64.d
 delete mode 100755 test/demo/builtin/uregs.sparc64.x86_64.x
 delete mode 100755 test/demo/builtin/uregs.x86_64.aarch64.x
 delete mode 100644 test/demo/builtin/uregs.x86_64.d
 delete mode 100755 test/demo/builtin/uregs.x86_64.sparc64.x
 create mode 100644 test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.d
 create mode 100644 test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.r
 create mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d
 create mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r
 create mode 100755 test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
 create mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.d
 create mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.r
 create mode 100755 test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x
 create mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.d
 create mode 100644 test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.r
 create mode 100755 test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x
 create mode 100755 test/unittest/arrays/tst.uregsarray-check.sh
 create mode 100755 test/unittest/arrays/tst.uregsarray-check.x
 create mode 100644 test/unittest/arrays/tst.uregsarray-constants.aarch64.d
 create mode 100644 test/unittest/arrays/tst.uregsarray-constants.aarch64.r
 create mode 100755 test/unittest/arrays/tst.uregsarray-constants.aarch64.x
 create mode 100644 test/unittest/arrays/tst.uregsarray-constants.x86_64.d
 create mode 100644 test/unittest/arrays/tst.uregsarray-constants.x86_64.r
 create mode 100755 test/unittest/arrays/tst.uregsarray-constants.x86_64.x
 create mode 100755 test/unittest/arrays/tst.uregsarray.x
 create mode 100644 test/unittest/disasm/tst.vartab-bvar-uregs0.r
 create mode 100755 test/unittest/disasm/tst.vartab-bvar-uregs0.sh
 create mode 100755 test/unittest/disasm/tst.vartab-bvar-uregs0.x
 delete mode 100644 test/unittest/variables/bvar/tst.uregs.d

diff --git a/libdtrace/arm64/regs.d b/libdtrace/arm64/regs.d
index 56fc461a..e47f8cfc 100644
--- a/libdtrace/arm64/regs.d
+++ b/libdtrace/arm64/regs.d
@@ -67,11 +67,11 @@ inline int R_X29 = 29 ;
 inline int R_X30 = 30 ;
 #pragma D binding "1.0" R_X30
 
-inline int R_SP = 32 ;
+inline int R_SP = 31 ;
 #pragma D binding "1.0" R_SP
-inline int R_PC = 33 ;
+inline int R_PC = 32 ;
 #pragma D binding "1.0" R_PC
-inline int R_PSTATE = 34 ;
+inline int R_PSTATE = 33 ;
 #pragma D binding "1.0" R_PSTATE
 
 inline int R_FP = R_X29;
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index f0f46c5c..80383e25 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -360,6 +360,8 @@ dt_bpf_init_helpers(dtrace_hdl_t *dtp)
 	BPF_HELPER_MAP(probe_read_user_str, probe_read_str);
 	BPF_HELPER_MAP(probe_read_kernel, probe_read);
 	BPF_HELPER_MAP(probe_read_kernel_str, probe_read_str);
+	BPF_HELPER_MAP(get_current_task_btf, unspec);
+	BPF_HELPER_MAP(task_pt_regs, unspec);
 #undef BPF_HELPER_MAP
 }
 
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 9f0675fa..43ad6971 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3944,6 +3944,107 @@ dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	TRACE_REGSET("    assoc_op: End  ");
 }
 
+#if defined(__amd64)
+static void
+dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
+	ctf_file_t *cfp = dtp->dt_shared_ctf;
+	ctf_id_t type;
+	ctf_membinfo_t ctm;
+	int offset, rc;
+
+	/* look up pt_regs[] */
+	if (idx <= 20 /* SS */) {
+		if (dtp->dt_bpfhelper[BPF_FUNC_get_current_task_btf] == BPF_FUNC_unspec
+		  || dtp->dt_bpfhelper[BPF_FUNC_task_pt_regs] == BPF_FUNC_unspec)
+			dnerror(dnp, D_UNKNOWN, "uregs[] is not supported on this kernel\n");
+		if (dt_regset_xalloc_args(drp) == -1)
+			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+		dt_regset_xalloc(drp, BPF_REG_0);
+		emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task_btf));
+		emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_0));
+		emit(dlp, BPF_CALL_HELPER(BPF_FUNC_task_pt_regs));
+		dt_regset_free_args(drp);
+		emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, idx * sizeof(uint64_t)));
+		emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_0, 0));
+		dt_regset_free(drp, BPF_REG_0);
+		return;
+	}
+
+	/* look up task->thread offset */
+	if (!cfp)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+
+	type = ctf_lookup_by_name(cfp, "struct task_struct");
+	if (type == CTF_ERR)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+	if (ctf_member_info(cfp, type, "thread", &ctm) == CTF_ERR)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+	offset = ctm.ctm_offset / NBBY;
+
+	/* add the thread->member offset */
+	type = ctf_lookup_by_name(cfp, "struct thread_struct");
+	if (type == CTF_ERR)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+	switch (idx) {
+	case 21: rc = ctf_member_info(cfp, type, "ds", &ctm); break;
+	case 22: rc = ctf_member_info(cfp, type, "es", &ctm); break;
+	case 23: rc = ctf_member_info(cfp, type, "fsbase", &ctm); break;
+	case 24: rc = ctf_member_info(cfp, type, "gsbase", &ctm); break;
+	case 25: rc = ctf_member_info(cfp, type, "trap_nr", &ctm); break;
+	default: dnerror(dnp, D_UNKNOWN, "uregs[]: index out of bounds (%d)\n", idx);
+	}
+	if (rc == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOCTF);
+	offset += ctm.ctm_offset / NBBY;
+
+	/* copy task->thread.member onto the stack */
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	dt_regset_xalloc(drp, BPF_REG_0);
+	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task));
+	emit(dlp, BPF_MOV_REG(BPF_REG_3, BPF_REG_0));
+	emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, offset));
+	emit(dlp, BPF_MOV_IMM(BPF_REG_2, sizeof(uint64_t)));
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_SP));
+	emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+	dt_regset_free_args(drp);
+	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_FP, DT_STK_SP));
+	emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_0, 0));
+	dt_regset_free(drp, BPF_REG_0);
+}
+
+#elif defined(__aarch64__)
+static void
+dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
+
+	if (idx >= sizeof(struct user_pt_regs) / sizeof(uint64_t)) {
+		dnerror(dnp, D_UNKNOWN, "uregs[]: index out of bounds (%d)\n", idx);
+		return;
+	}
+
+	if (dtp->dt_bpfhelper[BPF_FUNC_get_current_task_btf] == BPF_FUNC_unspec
+	  || dtp->dt_bpfhelper[BPF_FUNC_task_pt_regs] == BPF_FUNC_unspec)
+		dnerror(dnp, D_UNKNOWN, "uregs[] is not supported on this kernel\n");
+
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	dt_regset_xalloc(drp, BPF_REG_0);
+	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_current_task_btf));
+	emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_0));
+	emit(dlp, BPF_CALL_HELPER(BPF_FUNC_task_pt_regs));
+	dt_regset_free_args(drp);
+	emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, idx * sizeof(uint64_t)));
+	emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_0, 0));
+	dt_regset_free(drp, BPF_REG_0);
+}
+#else
+#error unknown ISA
+#endif
+
 /*
  * Currently, this code is only used for the args[] and uregs[] arrays.
  */
@@ -4001,9 +4102,18 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	dnp->dn_args->dn_value = saved;
 	dnp->dn_reg = dnp->dn_args->dn_reg;
 
+	if (idp->di_id == DIF_VAR_UREGS) {
+		/*
+		 * We can use dnp->dn_args->dn_value, even though it was
+		 * just overwritten by "saved", because we know the index
+		 * is is a constant integer DT_NODE_INT.
+		 */
+		dt_cg_uregs(dnp->dn_args->dn_value, dnp, dlp, drp);
+		return;
+	}
+
 	if (dt_regset_xalloc_args(drp) == -1)
 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
 	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_DCTX));
 	emit(dlp, BPF_MOV_IMM(BPF_REG_2, idp->di_id));
 	emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
diff --git a/libdtrace/i386/regs.d b/libdtrace/i386/regs.d
index cbde4cea..12ce3ac9 100644
--- a/libdtrace/i386/regs.d
+++ b/libdtrace/i386/regs.d
@@ -59,25 +59,25 @@ inline int R_R14 = 1;
 inline int R_R15 = 0;
 #pragma D binding "1.0" R_R15
 
-inline int R_EBX = R_GS + 1 + 0;
+inline int R_EBX = R_RBX;
 #pragma D binding "1.0" R_EBX
-inline int R_ECX = R_GS + 1 + 1;
+inline int R_ECX = R_RCX;
 #pragma D binding "1.0" R_ECX
-inline int R_EDX = R_GS + 1 + 2;
+inline int R_EDX = R_RDX;
 #pragma D binding "1.0" R_EDX
-inline int R_ESI = R_GS + 1 + 3;
+inline int R_ESI = R_RSI;
 #pragma D binding "1.0" R_ESI
-inline int R_EDI = R_GS + 1 + 4;
+inline int R_EDI = R_RDI;
 #pragma D binding "1.0" R_EDI
-inline int R_EBP = R_GS + 1 + 5;
+inline int R_EBP = R_RBP;
 #pragma D binding "1.0" R_EBP
-inline int R_EAX = R_GS + 1 + 6;
+inline int R_EAX = R_RAX;
 #pragma D binding "1.0" R_EAX
-inline int R_EIP = R_GS + 1 + 12;
+inline int R_EIP = R_RIP;
 #pragma D binding "1.0" R_EIP
-inline int R_EFL = R_GS + 1 + 14;
+inline int R_EFL = R_RFL;
 #pragma D binding "1.0" R_EFL
-inline int R_ESP = R_GS + 1 + 15;
+inline int R_ESP = R_RSP;
 #pragma D binding "1.0" R_ESP
 
 inline int R_PC = R_EIP;
diff --git a/test/demo/builtin/uregs.sparc64.aarch64.x b/test/demo/builtin/uregs.sparc64.aarch64.x
deleted file mode 100755
index 5c66540d..00000000
--- a/test/demo/builtin/uregs.sparc64.aarch64.x
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exit 2
diff --git a/test/demo/builtin/uregs.sparc64.d b/test/demo/builtin/uregs.sparc64.d
deleted file mode 100644
index a2c0879f..00000000
--- a/test/demo/builtin/uregs.sparc64.d
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2016, 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.
- */
-
-BEGIN
-{
-	printf("R_ASI = 0x%x\n", uregs[R_ASI]);
-}
-
-BEGIN
-{
-	printf("R_CCR = 0x%x\n", uregs[R_CCR]);
-}
-
-BEGIN
-{
-	printf("R_FP = 0x%x\n", uregs[R_FP]);
-}
-
-BEGIN
-{
-	printf("R_FPRS = 0x%x\n", uregs[R_FPRS]);
-}
-
-BEGIN
-{
-	printf("R_G0 = 0x%x\n", uregs[R_G0]);
-}
-
-BEGIN
-{
-	printf("R_G1 = 0x%x\n", uregs[R_G1]);
-}
-
-BEGIN
-{
-	printf("R_G2 = 0x%x\n", uregs[R_G2]);
-}
-
-BEGIN
-{
-	printf("R_G3 = 0x%x\n", uregs[R_G3]);
-}
-
-BEGIN
-{
-	printf("R_G4 = 0x%x\n", uregs[R_G4]);
-}
-
-BEGIN
-{
-	printf("R_G5 = 0x%x\n", uregs[R_G5]);
-}
-
-BEGIN
-{
-	printf("R_G6 = 0x%x\n", uregs[R_G6]);
-}
-
-BEGIN
-{
-	printf("R_G7 = 0x%x\n", uregs[R_G7]);
-}
-
-BEGIN
-{
-	printf("R_I0 = 0x%x\n", uregs[R_I0]);
-}
-
-BEGIN
-{
-	printf("R_I1 = 0x%x\n", uregs[R_I1]);
-}
-
-BEGIN
-{
-	printf("R_I2 = 0x%x\n", uregs[R_I2]);
-}
-
-BEGIN
-{
-	printf("R_I3 = 0x%x\n", uregs[R_I3]);
-}
-
-BEGIN
-{
-	printf("R_I4 = 0x%x\n", uregs[R_I4]);
-}
-
-BEGIN
-{
-	printf("R_I5 = 0x%x\n", uregs[R_I5]);
-}
-
-BEGIN
-{
-	printf("R_I6 = 0x%x\n", uregs[R_I6]);
-}
-
-BEGIN
-{
-	printf("R_I7 = 0x%x\n", uregs[R_I7]);
-}
-
-BEGIN
-{
-	printf("R_L0 = 0x%x\n", uregs[R_L0]);
-}
-
-BEGIN
-{
-	printf("R_L1 = 0x%x\n", uregs[R_L1]);
-}
-
-BEGIN
-{
-	printf("R_L2 = 0x%x\n", uregs[R_L2]);
-}
-
-BEGIN
-{
-	printf("R_L3 = 0x%x\n", uregs[R_L3]);
-}
-
-BEGIN
-{
-	printf("R_L4 = 0x%x\n", uregs[R_L4]);
-}
-
-BEGIN
-{
-	printf("R_L5 = 0x%x\n", uregs[R_L5]);
-}
-
-BEGIN
-{
-	printf("R_L6 = 0x%x\n", uregs[R_L6]);
-}
-
-BEGIN
-{
-	printf("R_L7 = 0x%x\n", uregs[R_L7]);
-}
-
-BEGIN
-{
-	printf("R_NPC = 0x%x\n", uregs[R_NPC]);
-}
-
-BEGIN
-{
-	printf("R_O0 = 0x%x\n", uregs[R_O0]);
-}
-
-BEGIN
-{
-	printf("R_O1 = 0x%x\n", uregs[R_O1]);
-}
-
-BEGIN
-{
-	printf("R_O2 = 0x%x\n", uregs[R_O2]);
-}
-
-BEGIN
-{
-	printf("R_O3 = 0x%x\n", uregs[R_O3]);
-}
-
-BEGIN
-{
-	printf("R_O4 = 0x%x\n", uregs[R_O4]);
-}
-
-BEGIN
-{
-	printf("R_O5 = 0x%x\n", uregs[R_O5]);
-}
-
-BEGIN
-{
-	printf("R_O6 = 0x%x\n", uregs[R_O6]);
-}
-
-BEGIN
-{
-	printf("R_O7 = 0x%x\n", uregs[R_O7]);
-}
-
-BEGIN
-{
-	printf("R_PC = 0x%x\n", uregs[R_PC]);
-}
-
-BEGIN
-{
-	printf("R_PS = 0x%x\n", uregs[R_PS]);
-}
-
-BEGIN
-{
-	printf("R_R0 = 0x%x\n", uregs[R_R0]);
-}
-
-BEGIN
-{
-	printf("R_R1 = 0x%x\n", uregs[R_R1]);
-}
-
-BEGIN
-{
-	printf("R_SP = 0x%x\n", uregs[R_SP]);
-}
-
-BEGIN
-{
-	printf("R_Y = 0x%x\n", uregs[R_Y]);
-}
-
-BEGIN
-{
-	printf("R_nPC = 0x%x\n", uregs[R_nPC]);
-	exit(0);
-}
-
-ERROR
-{
-	printf("uregs access failed.\n");
-	exit(1);
-}
diff --git a/test/demo/builtin/uregs.sparc64.x86_64.x b/test/demo/builtin/uregs.sparc64.x86_64.x
deleted file mode 100755
index 5c66540d..00000000
--- a/test/demo/builtin/uregs.sparc64.x86_64.x
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exit 2
diff --git a/test/demo/builtin/uregs.x86_64.aarch64.x b/test/demo/builtin/uregs.x86_64.aarch64.x
deleted file mode 100755
index 5c66540d..00000000
--- a/test/demo/builtin/uregs.x86_64.aarch64.x
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exit 2
diff --git a/test/demo/builtin/uregs.x86_64.d b/test/demo/builtin/uregs.x86_64.d
deleted file mode 100644
index 49886dea..00000000
--- a/test/demo/builtin/uregs.x86_64.d
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2011, 2020, 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 */
-BEGIN
-{
-	printf("R_GS = 0x%x\n", uregs[R_GS]);
-}
-BEGIN
-{
-	printf("R_ES = 0x%x\n", uregs[R_ES]);
-}
-BEGIN
-{
-	printf("R_DS = 0x%x\n", uregs[R_DS]);
-}
-BEGIN
-{
-	printf("R_RDI = 0x%x\n", uregs[R_RDI]);
-}
-BEGIN
-{
-	printf("R_RSI = 0x%x\n", uregs[R_RSI]);
-}
-BEGIN
-{
-	printf("R_RBP = 0x%x\n", uregs[R_RBP]);
-}
-BEGIN
-{
-	printf("R_RBX = 0x%x\n", uregs[R_RBX]);
-}
-BEGIN
-{
-	printf("R_RDX = 0x%x\n", uregs[R_RDX]);
-}
-BEGIN
-{
-	printf("R_RCX = 0x%x\n", uregs[R_RCX]);
-}
-BEGIN
-{
-	printf("R_RAX = 0x%x\n", uregs[R_RAX]);
-/*	printf("R_TRAPNO = 0x%x\n", uregs[R_TRAPNO]); */
-/*	printf("R_ERR = 0x%x\n", uregs[R_ERR]); */
-}
-BEGIN
-{
-	printf("R_RIP = 0x%x\n", uregs[R_RIP]);
-}
-BEGIN
-{
-	printf("R_CS = 0x%x\n", uregs[R_CS]);
-}
-BEGIN
-{
-	printf("R_EFL = 0x%x\n", uregs[R_EFL]);
-}
-BEGIN
-{
-	printf("R_RSP = 0x%x\n", uregs[R_RSP]);
-}
-BEGIN
-{
-	printf("R_SS = 0x%x\n", uregs[R_SS]);
-	exit(0);
-}
-ERROR
-{
-	printf("uregs access failed.\n");
-	exit(1);
-}
diff --git a/test/demo/builtin/uregs.x86_64.sparc64.x b/test/demo/builtin/uregs.x86_64.sparc64.x
deleted file mode 100755
index 5c66540d..00000000
--- a/test/demo/builtin/uregs.x86_64.sparc64.x
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exit 2
diff --git a/test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.d b/test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.d
new file mode 100644
index 00000000..dc57f8d3
--- /dev/null
+++ b/test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.d
@@ -0,0 +1,19 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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: uregs[] must have a constant index.
+ *
+ * SECTION: User Process Tracing/uregs Array
+ */
+
+BEGIN
+{
+	i = R_SP;
+	trace(uregs[i]);
+	exit(1);
+}
diff --git a/test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.r b/test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.r
new file mode 100644
index 00000000..2349e17e
--- /dev/null
+++ b/test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/arrays/err.D_PROTO_ARG.uregs_variable.d: [D_PROTO_ARG] line 17: uregs[ ] argument #1 is incompatible with prototype:
+	prototype: integer constant
+	 argument: int
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d
new file mode 100644
index 00000000..ed375348
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d
@@ -0,0 +1,19 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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: uregs[] not supported on old kernels.
+ *
+ * SECTION: User Process Tracing/uregs Array
+ */
+
+BEGIN
+{
+	trace(uregs[R_SP]);
+	exit(1);
+}
+
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r
new file mode 100644
index 00000000..09024896
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.d: [D_UNKNOWN] line 16: uregs[] is not supported on this kernel
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
new file mode 100755
index 00000000..0274240f
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
+
+if [ $MAJOR -lt 5 ]; then
+        exit 0
+fi
+if [ $MAJOR -eq 5 -a $MINOR -lt 15 ]; then
+        exit 0
+fi
+
+echo "no UNKNOWN-uregs problem on newer kernels"
+exit 2
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.d b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.d
new file mode 100644
index 00000000..f022984e
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.d
@@ -0,0 +1,20 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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:  Check the constants used to access uregs[].
+ *
+ * SECTION: User Process Tracing/uregs Array
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace(uregs[R_PSTATE + 1]);
+        exit(0);
+}
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.r b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.r
new file mode 100644
index 00000000..00a7a8cc
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.d: [D_UNKNOWN] line 18: uregs[]: index out of bounds (34)
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x
new file mode 100755
index 00000000..36074cb2
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.aarch64.x
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+[ `uname -m` = "aarch64" ] && exit 0
+exit 2
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.d b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.d
new file mode 100644
index 00000000..ea5c5db6
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.d
@@ -0,0 +1,20 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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:  Check the constants used to access uregs[].
+ *
+ * SECTION: User Process Tracing/uregs Array
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace(uregs[42]);
+        exit(0);
+}
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.r b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.r
new file mode 100644
index 00000000..02bfa4cf
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.d: [D_UNKNOWN] line 18: uregs[]: index out of bounds (42)
diff --git a/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x
new file mode 100755
index 00000000..69e36e70
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_toobig.x86_64.x
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+[ `uname -m` = "x86_64" ] && exit 0
+exit 2
diff --git a/test/unittest/arrays/tst.uregsarray-check.sh b/test/unittest/arrays/tst.uregsarray-check.sh
new file mode 100755
index 00000000..b672666e
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-check.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2023, 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.
+#
+
+dtrace=$1
+CC=/usr/bin/gcc
+CFLAGS=
+
+DIRNAME="$tmpdir/arrays-uregsarray-check.$$.$RANDOM"
+mkdir -p $DIRNAME
+cd $DIRNAME
+
+# compile USDT provider
+
+cat > prov.d <<EOF
+provider test_prov {
+	probe go();
+};
+EOF
+
+$dtrace -h -s prov.d
+if [ $? -ne 0 ]; then
+	echo "failed to generate header file" >& 2
+	exit 1
+fi
+
+# compile instrumented user test program
+
+cat > test.c <<EOF
+#include <stdio.h>
+
+#include <sys/types.h>
+#include "prov.h"
+
+int main(int c, char **v) {
+    int local_variable = 10;
+
+    printf("instructions start at %p\n", &main);
+    printf("local variable at %p\n", &local_variable);
+    TEST_PROV_GO();
+    return 0;
+}
+EOF
+
+${CC} ${CFLAGS} -c test.c
+if [ $? -ne 0 ]; then
+	echo "failed to compile test.c" >& 2
+	exit 1
+fi
+$dtrace -G -s prov.d test.o
+if [ $? -ne 0 ]; then
+	echo "failed to create DOF" >& 2
+	exit 1
+fi
+${CC} ${CFLAGS} -o test test.o prov.o
+if [ $? -ne 0 ]; then
+	echo "failed to link final executable" >& 2
+	exit 1
+fi
+
+# run DTrace
+
+$dtrace -c ./test -qn '
+test_prov$target:::
+{
+	printf("DTrace has PC %x and SP %x\n", uregs[R_PC], uregs[R_SP]);
+	exit(0);
+}' -o D.out > C.out
+
+if [ $? -ne 0 ]; then
+	echo DTrace ERROR
+	cat D.out C.out
+	exit 1
+fi
+
+# post processing
+
+awk '
+BEGIN { DTrace_PC = DTrace_SP = instructions = local_variable = -1 }
+
+# the first file has DTrace output
+NR == FNR && /^DTrace has PC / { DTrace_PC = "0x"$4; DTrace_SP = "0x"$7; next; }
+
+# the second file has output from the C program
+NR != FNR && /^instructions start at / { instructions = $4; next; }
+NR != FNR && /^local variable at /   { local_variable = $4; next; }
+
+END {
+	if ( DTrace_PC <= 0 ||
+	     DTrace_SP <= 0 ||
+	     instructions <= 0 ||
+	     local_variable <= 0 ) {
+		print "ERROR: did not see all output in post-processing";
+		exit 1;
+	}
+
+	# the PC must be early in the reported function
+	offset = strtonum(DTrace_PC) - strtonum(instructions);
+	print "PC offset is", DTrace_PC, " -", instructions, "=", offset;
+	if ( offset < 0 || offset > 100 ) {
+		print "ERROR: instruction offset is unreasonable";
+		exit 1;
+	}
+
+	# the local variable address must be a little higher than the SP
+	offset = strtonum(local_variable) - strtonum(DTrace_SP);
+	print "stack variable offset is", local_variable, " -", DTrace_SP, "=", offset;
+	if ( offset < 0 || offset > 100 ) {
+		print "ERROR: stack variable offset is unreasonable";
+		exit 1;
+	}
+
+	print "success: both offsets are reasonable";
+	exit 0;
+}' D.out C.out
+
+exit $?
diff --git a/test/unittest/arrays/tst.uregsarray-check.x b/test/unittest/arrays/tst.uregsarray-check.x
new file mode 100755
index 00000000..4fb7f8c1
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-check.x
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
+
+if [ $MAJOR -gt 5 ]; then
+        exit 0
+fi
+if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
+        exit 0
+fi
+
+echo "no uregs on older kernels"
+exit 1
diff --git a/test/unittest/arrays/tst.uregsarray-constants.aarch64.d b/test/unittest/arrays/tst.uregsarray-constants.aarch64.d
new file mode 100644
index 00000000..a8c3a7d9
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.aarch64.d
@@ -0,0 +1,56 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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:  Check the constants used to access uregs[].
+ *
+ * SECTION: User Process Tracing/uregs Array
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	printf(" %d", R_X0);
+	printf(" %d", R_X1);
+	printf(" %d", R_X2);
+	printf(" %d", R_X3);
+	printf(" %d", R_X4);
+	printf(" %d", R_X5);
+	printf(" %d", R_X6);
+	printf(" %d", R_X7);
+	printf(" %d", R_X8);
+	printf(" %d", R_X9);
+	printf(" %d", R_X10);
+	printf(" %d", R_X11);
+	printf(" %d", R_X12);
+	printf(" %d", R_X13);
+	printf(" %d", R_X14);
+	printf(" %d", R_X15);
+	printf(" %d", R_X16);
+	printf(" %d", R_X17);
+	printf(" %d", R_X18);
+	printf(" %d", R_X19);
+	printf(" %d", R_X20);
+	printf(" %d", R_X21);
+	printf(" %d", R_X22);
+	printf(" %d", R_X23);
+	printf(" %d", R_X24);
+	printf(" %d", R_X25);
+	printf(" %d", R_X26);
+	printf(" %d", R_X27);
+	printf(" %d", R_X28);
+	printf(" %d", R_X29);
+	printf(" %d", R_X30);
+	printf(" %d", R_SP);
+	printf(" %d", R_PC);
+	printf(" %d", R_PSTATE);
+	printf(" %d", R_FP);
+	printf("\n");
+
+        exit(0);
+}
diff --git a/test/unittest/arrays/tst.uregsarray-constants.aarch64.r b/test/unittest/arrays/tst.uregsarray-constants.aarch64.r
new file mode 100644
index 00000000..8b160812
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.aarch64.r
@@ -0,0 +1,2 @@
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 29
+
diff --git a/test/unittest/arrays/tst.uregsarray-constants.aarch64.x b/test/unittest/arrays/tst.uregsarray-constants.aarch64.x
new file mode 100755
index 00000000..36074cb2
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.aarch64.x
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+[ `uname -m` = "aarch64" ] && exit 0
+exit 2
diff --git a/test/unittest/arrays/tst.uregsarray-constants.x86_64.d b/test/unittest/arrays/tst.uregsarray-constants.x86_64.d
new file mode 100644
index 00000000..84ecd358
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.x86_64.d
@@ -0,0 +1,44 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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:  Check the constants used to access uregs[].
+ *
+ * SECTION: User Process Tracing/uregs Array
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	printf(" %d", R_PC);
+	printf(" %d", R_SP);
+	printf(" %d", R_R0);
+	printf(" %d", R_R1);
+	printf(" %d", R_CS);
+	printf(" %d", R_GS);
+	printf(" %d", R_ES);
+	printf(" %d", R_DS);
+	printf(" %d", R_EDI);
+	printf(" %d", R_ESI);
+	printf(" %d", R_EBP);
+	printf(" %d", R_EAX);
+	printf(" %d", R_ESP);
+	printf(" %d", R_EAX);
+	printf(" %d", R_EBX);
+	printf(" %d", R_ECX);
+	printf(" %d", R_EDX);
+	printf(" %d", R_TRAPNO);
+	printf(" %d", R_ERR);
+	printf(" %d", R_EIP);
+	printf(" %d", R_CS);
+	printf(" %d", R_EFL);
+	/* printf(" %d", R_UESP); */ /* in the User's Guide, but not defined in regs.d */
+	printf(" %d", R_SS);
+	printf("\n");
+        exit(0);
+}
diff --git a/test/unittest/arrays/tst.uregsarray-constants.x86_64.r b/test/unittest/arrays/tst.uregsarray-constants.x86_64.r
new file mode 100644
index 00000000..f41cc672
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.x86_64.r
@@ -0,0 +1,2 @@
+ 16 19 10 5 17 24 22 21 14 13 4 10 19 10 5 11 12 25 15 16 17 18 20
+
diff --git a/test/unittest/arrays/tst.uregsarray-constants.x86_64.x b/test/unittest/arrays/tst.uregsarray-constants.x86_64.x
new file mode 100755
index 00000000..69e36e70
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.x86_64.x
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+[ `uname -m` = "x86_64" ] && exit 0
+exit 2
diff --git a/test/unittest/arrays/tst.uregsarray.arm64.d b/test/unittest/arrays/tst.uregsarray.arm64.d
index 87b316a5..776bca8a 100644
--- a/test/unittest/arrays/tst.uregsarray.arm64.d
+++ b/test/unittest/arrays/tst.uregsarray.arm64.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2023, 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/arrays/tst.uregsarray.arm64.x b/test/unittest/arrays/tst.uregsarray.arm64.x
index 36074cb2..635c2a86 100755
--- a/test/unittest/arrays/tst.uregsarray.arm64.x
+++ b/test/unittest/arrays/tst.uregsarray.arm64.x
@@ -1,4 +1,15 @@
-#!/bin/sh
+#!/bin/bash
 
-[ `uname -m` = "aarch64" ] && exit 0
-exit 2
+[ `uname -m` != "aarch64" ] && exit 2
+
+read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
+
+if [ $MAJOR -gt 5 ]; then
+	exit 0
+fi
+if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
+	exit 0
+fi
+
+echo "uregs[]: pt_regs[] lookup not implemented on older kernels"
+exit 1
diff --git a/test/unittest/arrays/tst.uregsarray.d b/test/unittest/arrays/tst.uregsarray.d
index 0037f181..9b2a537e 100644
--- a/test/unittest/arrays/tst.uregsarray.d
+++ b/test/unittest/arrays/tst.uregsarray.d
@@ -1,11 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2023, 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/arrays/tst.uregsarray.x b/test/unittest/arrays/tst.uregsarray.x
new file mode 100755
index 00000000..e63a58bd
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray.x
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
+
+if [ $MAJOR -gt 5 ]; then
+	exit 0
+fi
+if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
+	exit 0
+fi
+
+echo "uregs[]: pt_regs[] lookup not implemented on older kernels"
+exit 1
diff --git a/test/unittest/arrays/tst.uregsarray.x86_64.d b/test/unittest/arrays/tst.uregsarray.x86_64.d
index 26137dfe..fff6bcf0 100644
--- a/test/unittest/arrays/tst.uregsarray.x86_64.d
+++ b/test/unittest/arrays/tst.uregsarray.x86_64.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2023, 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/arrays/tst.uregsarray.x86_64.x b/test/unittest/arrays/tst.uregsarray.x86_64.x
index 69e36e70..5441e564 100755
--- a/test/unittest/arrays/tst.uregsarray.x86_64.x
+++ b/test/unittest/arrays/tst.uregsarray.x86_64.x
@@ -1,4 +1,15 @@
-#!/bin/sh
+#!/bin/bash
 
-[ `uname -m` = "x86_64" ] && exit 0
-exit 2
+[ `uname -m` != "x86_64" ] && exit 2
+
+read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
+
+if [ $MAJOR -gt 5 ]; then
+	exit 0
+fi
+if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
+	exit 0
+fi
+
+echo "uregs[]: pt_regs[] lookup not implemented on older kernels"
+exit 1
diff --git a/test/unittest/disasm/tst.ann-bvar.r b/test/unittest/disasm/tst.ann-bvar.r
index ec8c2c09..b514dd99 100644
--- a/test/unittest/disasm/tst.ann-bvar.r
+++ b/test/unittest/disasm/tst.ann-bvar.r
@@ -29,7 +29,6 @@
 85 0 1 0000 ffffffff    call dt_get_bvar              ! timestamp
 85 0 1 0000 ffffffff    call dt_get_bvar              ! ucaller
 85 0 1 0000 ffffffff    call dt_get_bvar              ! uid
-85 0 1 0000 ffffffff    call dt_get_bvar              ! uregs
 85 0 1 0000 ffffffff    call dt_get_bvar              ! ustackdepth
 85 0 1 0000 ffffffff    call dt_get_bvar              ! vtimestamp
 85 0 1 0000 ffffffff    call dt_get_bvar              ! walltimestamp
diff --git a/test/unittest/disasm/tst.ann-bvar.sh b/test/unittest/disasm/tst.ann-bvar.sh
index e53123f3..1986de66 100755
--- a/test/unittest/disasm/tst.ann-bvar.sh
+++ b/test/unittest/disasm/tst.ann-bvar.sh
@@ -42,7 +42,6 @@ sdt:task::task_rename
 	trace(timestamp);
 	trace(ucaller);
 	trace(uid);
-	trace(uregs[0]);
 	trace(ustackdepth);
 	trace(vtimestamp);
 	trace(walltimestamp);
diff --git a/test/unittest/disasm/tst.vartab-bvar-uregs0.r b/test/unittest/disasm/tst.vartab-bvar-uregs0.r
new file mode 100644
index 00000000..b1c07635
--- /dev/null
+++ b/test/unittest/disasm/tst.vartab-bvar-uregs0.r
@@ -0,0 +1,2 @@
+NAME             OFFSET KND SCP FLAG TYPE
+uregs                   arr glb r    D type (integer) (size 8)
diff --git a/test/unittest/disasm/tst.vartab-bvar-uregs0.sh b/test/unittest/disasm/tst.vartab-bvar-uregs0.sh
new file mode 100755
index 00000000..9a37f4bd
--- /dev/null
+++ b/test/unittest/disasm/tst.vartab-bvar-uregs0.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2022, 2023, 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: Built-in variables should not displayed with an offset
+#	     Test uregs[0] separately until it works on all kernel versions.
+#
+# SECTION: Variables/Scalar Variables
+#
+##
+
+dtrace=$1
+
+$dtrace $dt_flags -Sen '
+sdt:task::task_rename
+{
+	trace(uregs[0]);
+	exit(0);
+}
+' 2>&1 | awk '
+BEGIN {
+	rc = 1;
+}
+
+/^NAME/ && /KND SCP/ {
+	printf "%-16s %-6s %-3s %-3s %-4s %s\n",
+	       "NAME", "OFFSET", "KND", "SCP","FLAG", "TYPE";
+	while (getline == 1 && NF > 0) {
+		if ($3 == "scl" || $3 == "arr") {
+			$2 = $5 = "";
+			gsub(/ +/, " ");
+			printf "%-16s %-6s %-3s %-3s %-4s", $1, "", $2, $3, $4;
+			$1 = $2 = $3 = $4 = "";
+			gsub(/ +/, " ");
+		} else {
+			$2 = $6 = "";
+			gsub(/ +/, " ");
+			printf "%-16s %-6s %-3s %-3s %-4s", $1, $2, $3, $4, $5;
+			$1 = $2 = $3 = $4 = $5 = "";
+			gsub(/ +/, " ");
+		}
+
+		print $0;
+		rc = 0;
+	}
+}
+
+END {
+	exit(rc);
+}
+'
+
+exit $?
diff --git a/test/unittest/disasm/tst.vartab-bvar-uregs0.x b/test/unittest/disasm/tst.vartab-bvar-uregs0.x
new file mode 100755
index 00000000..4fb7f8c1
--- /dev/null
+++ b/test/unittest/disasm/tst.vartab-bvar-uregs0.x
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+read MAJOR MINOR <<< `uname -r | grep -Eo '^[0-9]+\.[0-9]+' | tr '.' ' '`
+
+if [ $MAJOR -gt 5 ]; then
+        exit 0
+fi
+if [ $MAJOR -eq 5 -a $MINOR -ge 15 ]; then
+        exit 0
+fi
+
+echo "no uregs on older kernels"
+exit 1
diff --git a/test/unittest/disasm/tst.vartab-bvar.r b/test/unittest/disasm/tst.vartab-bvar.r
index 8a1c5fd2..06d7c52b 100644
--- a/test/unittest/disasm/tst.vartab-bvar.r
+++ b/test/unittest/disasm/tst.vartab-bvar.r
@@ -1,6 +1,5 @@
 NAME             OFFSET KND SCP FLAG TYPE
 args                    arr glb r    any (unknown) by ref (size 0)
-uregs                   arr glb r    D type (integer) (size 8)
 curthread               scl glb r    D type (pointer) (size 8)
 timestamp               scl glb r    D type (integer) (size 8)
 vtimestamp              scl glb r    D type (integer) (size 8)
diff --git a/test/unittest/disasm/tst.vartab-bvar.sh b/test/unittest/disasm/tst.vartab-bvar.sh
index b368f8bd..996cc332 100755
--- a/test/unittest/disasm/tst.vartab-bvar.sh
+++ b/test/unittest/disasm/tst.vartab-bvar.sh
@@ -50,7 +50,7 @@ sdt:task::task_rename
 	trace(timestamp);
 	trace(ucaller);
 	trace(uid);
-	trace(uregs[0]);
+	/* trace(uregs[0]); */ /* test this separately until uregs[0] works on all kernels */
 	trace(ustackdepth);
 	trace(vtimestamp);
 	trace(walltimestamp);
diff --git a/test/unittest/variables/bvar/tst.uregs.d b/test/unittest/variables/bvar/tst.uregs.d
deleted file mode 100644
index 5e0d507e..00000000
--- a/test/unittest/variables/bvar/tst.uregs.d
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2020, 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: The 'uregs' variable can be accessed and is not -1.
- *
- * SECTION: Variables/Built-in Variables/uregs
- */
-
-#pragma D option quiet
-
-BEGIN {
-	trace(uregs);
-	exit(uregs != -1 ? 0 : 1);
-}
-
-ERROR {
-	exit(1);
-}
-- 
2.18.4




More information about the DTrace-devel mailing list