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

eugene.loh at oracle.com eugene.loh at oracle.com
Wed Feb 15 20:22:05 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                             | 203 ++++++++++++++-
 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   |  15 +-
 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  |  15 +-
 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 --
 42 files changed, 679 insertions(+), 360 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 50846942..eec7b243 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3944,6 +3944,201 @@ dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	TRACE_REGSET("    assoc_op: End  ");
 }
 
+#if defined(__amd64)
+/* 64-bit programs on x86 */
+/* adapted from DTv1 kernel code arch/x86/dtrace/dtrace_isa_x86_64.c dtrace_getreg() */
+
+/*
+ * dtrace_isa_x86_64.c defines REG_*.
+ * We call them DT_CG_REG_*
+ * to avoid name collisions with /usr/include/sys/ucontext.h .
+ */
+#define DT_CG_REG_TRAPNO      25
+#define DT_CG_REG_GS          24
+#define DT_CG_REG_FS          23
+#define DT_CG_REG_ES          22
+#define DT_CG_REG_DS          21
+#define DT_CG_REG_SS          20
+#define DT_CG_REG_RSP         19
+#define DT_CG_REG_RFL         18
+#define DT_CG_REG_CS          17
+#define DT_CG_REG_RIP         16
+#define DT_CG_REG_ERR         15
+#define DT_CG_REG_RDI         14
+#define DT_CG_REG_RSI         13
+#define DT_CG_REG_RDX         12
+#define DT_CG_REG_RCX         11
+#define DT_CG_REG_RAX         10
+#define DT_CG_REG_R8          9
+#define DT_CG_REG_R9          8
+#define DT_CG_REG_R10         7
+#define DT_CG_REG_R11         6
+#define DT_CG_REG_RBX         5
+#define DT_CG_REG_RBP         4
+#define DT_CG_REG_R12         3
+#define DT_CG_REG_R13         2
+#define DT_CG_REG_R14         1
+#define DT_CG_REG_R15         0
+
+static void
+dt_cg_uregs(unsigned int idx, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	int regmap[] = { DT_CG_REG_RBX,	/*  0 -> EBX */
+			 DT_CG_REG_RCX,	/*  1 -> ECX */
+			 DT_CG_REG_RDX,	/*  2 -> EDX */
+			 DT_CG_REG_RSI,	/*  3 -> ESI */
+			 DT_CG_REG_RDI,	/*  4 -> EDI */
+			 DT_CG_REG_RBP,	/*  5 -> EBP */
+			 DT_CG_REG_RAX,	/*  6 -> EAX */
+			 DT_CG_REG_DS,	/*  7 -> DS */
+			 DT_CG_REG_ES,	/*  8 -> ES */
+			 DT_CG_REG_FS,	/*  9 -> FS */
+			 DT_CG_REG_GS,	/* 10 -> GS */
+			 DT_CG_REG_TRAPNO,	/* 11 -> TRAPNO */
+			 DT_CG_REG_RIP,	/* 12 -> EIP */
+			 DT_CG_REG_CS,	/* 13 -> CS */
+			 DT_CG_REG_RFL,	/* 14 -> EFL */
+			 DT_CG_REG_RSP,	/* 15 -> UESP */
+			 DT_CG_REG_SS,	/* 16 -> SS */
+			};
+	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;
+
+	if (idx >= sizeof(regmap) / sizeof(int) + DT_CG_REG_GS + 1) {
+		dnerror(dnp, D_UNKNOWN, "uregs[%d]: unrecognized index\n", idx);
+		return;
+	}
+
+	/* convert register alias index into register mapping index */
+	if (idx > DT_CG_REG_TRAPNO)
+		idx = regmap[idx - DT_CG_REG_GS - 1];
+
+	/* look up pt_regs[] */
+	if (idx <= DT_CG_REG_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[]: pt_regs[] look up is not implemented for this kernel version\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)
+		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
+
+	type = ctf_lookup_by_name(cfp, "struct task_struct");
+	if (type == CTF_ERR)
+		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
+	if (ctf_member_info(cfp, type, "thread", &ctm) == CTF_ERR)
+		assert(0); // return dt_set_errno(dtp, 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)
+		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
+	switch (idx) {
+	case DT_CG_REG_DS: rc = ctf_member_info(cfp, type, "ds", &ctm); break;
+	case DT_CG_REG_ES: rc = ctf_member_info(cfp, type, "es", &ctm); break;
+	case DT_CG_REG_FS: rc = ctf_member_info(cfp, type, "fsbase", &ctm); break;
+	case DT_CG_REG_GS: rc = ctf_member_info(cfp, type, "gsbase", &ctm); break;
+	case DT_CG_REG_TRAPNO: rc = ctf_member_info(cfp, type, "trap_nr", &ctm); break;
+	default: dnerror(dnp, D_UNKNOWN, "uregs[%d]: unrecognized index\n", idx);
+	}
+	if (rc == -1)
+		assert(0); // return dt_set_errno(dtp, 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);
+}
+
+#undef DT_CG_REG_TRAPNO
+#undef DT_CG_REG_GS
+#undef DT_CG_REG_FS
+#undef DT_CG_REG_ES
+#undef DT_CG_REG_DS
+#undef DT_CG_REG_SS
+#undef DT_CG_REG_RSP
+#undef DT_CG_REG_RFL
+#undef DT_CG_REG_CS
+#undef DT_CG_REG_RIP
+#undef DT_CG_REG_ERR
+#undef DT_CG_REG_RDI
+#undef DT_CG_REG_RSI
+#undef DT_CG_REG_RDX
+#undef DT_CG_REG_RCX
+#undef DT_CG_REG_RAX
+#undef DT_CG_REG_R8
+#undef DT_CG_REG_R9
+#undef DT_CG_REG_R10
+#undef DT_CG_REG_R11
+#undef DT_CG_REG_RBX
+#undef DT_CG_REG_RBP
+#undef DT_CG_REG_R12
+#undef DT_CG_REG_R13
+#undef DT_CG_REG_R14
+#undef DT_CG_REG_R15
+
+#elif defined(__aarch64__)
+/* aarch64 */
+/* adapted from DTv1 kernel code arch/arm64/dtrace/dtrace_isa_arm64.c dtrace_getreg() */
+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[%d]: unrecognized index\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[]: pt_regs[] look up is not implemented for this kernel version\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.
  */
@@ -3956,6 +4151,7 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	dt_ident_t	*fidp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_bvar");
 	size_t		size;
 	int		n;
+	unsigned int	idx;
 
 	assert(dnp->dn_kind == DT_NODE_VAR);
 	assert(!(idp->di_flags & (DT_IDFLG_TLS | DT_IDFLG_LOCAL)));
@@ -3998,12 +4194,17 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	}
 
 	dt_cg_node(dnp->dn_args, dlp, drp);
+	idx = dnp->dn_args->dn_value;
 	dnp->dn_args->dn_value = saved;
 	dnp->dn_reg = dnp->dn_args->dn_reg;
 
+	if (idp->di_id == DIF_VAR_UREGS) {
+		dt_cg_uregs(idx, 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/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..3fb2c007
--- /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[]: pt_regs[] look up is not implemented for this kernel version
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..5a59adee
--- /dev/null
+++ b/test/unittest/arrays/err.D_UNKNOWN.uregs_badkernelversion.x
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+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..79042461
--- /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[34]: unrecognized index
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..d8e3fb73
--- /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[42]: unrecognized index
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..b5ce6a1d
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-check.x
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+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..74766ec5
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray-constants.x86_64.r
@@ -0,0 +1,2 @@
+ 37 40 31 25 17 24 22 21 29 28 30 31 40 31 25 26 27 25 15 37 17 39 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..affd405f 100755
--- a/test/unittest/arrays/tst.uregsarray.arm64.x
+++ b/test/unittest/arrays/tst.uregsarray.arm64.x
@@ -1,4 +1,15 @@
 #!/bin/sh
 
-[ `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..32e676e8
--- /dev/null
+++ b/test/unittest/arrays/tst.uregsarray.x
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+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..c5d64eaf 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
 
-[ `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..b5ce6a1d
--- /dev/null
+++ b/test/unittest/disasm/tst.vartab-bvar-uregs0.x
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+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