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

Kris Van Hees kris.van.hees at oracle.com
Fri Feb 24 20:15:26 UTC 2023


On Fri, Feb 24, 2023 at 02:12:36PM -0500, Kris Van Hees via DTrace-devel wrote:
> On Tue, Feb 21, 2023 at 11:49:11AM -0500, eugene.loh--- via DTrace-devel wrote:
> > 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>
> > 
> > sq
> > ---
> >  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   |  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 --
> >  42 files changed, 681 insertions(+), 362 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 .
> > + */
> 
> I dont think this comment block is needed, and ...
> 
> > +#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
> 
> We do not really need these (except for perhaps the _DS, _ES, etc ones since
> they are used in a switch statement below.  The rest can just be mentioned in
> comments in the regmap table which then can just use the numeric values.  At
> some point, we probably should ensure we have a single file that defines these
> constants and then use that here *and* in the regs.d file.  But right now, just
> use the values and comment.
> 
> > +
> > +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 */
> > +			};

Looking at this a bit more, I think that this mapping should really be
reflected in the regs.d file instead of here.  Since there is nothing that is
expected (or even supported) to depend on the numeric values of any of the
constants that are provided by regs.d, and since there is nothing that documents
the values such that you can expect to acces uregs using numeric values and
expect it to do "the right thing", I really think the mapping should be done
there...  I.e. ensure that each symbolic name has a value index value that
refers to the correct location of the value in pt_regs[].

And that means this entire business of mapping values can be removed here.  It
is too much of a mess (and was a mess in v1 also - without needing to be).

> > +	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);
> 
> I think a better message would be "uregs[]: index out of bounds (%d)\n" (also
> more consistent).
> 
> > +		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");
> 
> I think this is exposing more details than the average user cares to know.
> Just say "uregs[] is not supported on this kernel".
> 
> > +		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 */
> > +
> 
> Extra newline.
> 
> > +	if (!cfp)
> > +		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
> 
> Errr.... assert?????  And a dt_set_errno in comment?
> 
> > +
> > +	type = ctf_lookup_by_name(cfp, "struct task_struct");
> > +	if (type == CTF_ERR)
> > +		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
> 
> Errr.... assert?????  And a dt_set_errno in comment?
> 
> > +	if (ctf_member_info(cfp, type, "thread", &ctm) == CTF_ERR)
> > +		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
> 
> Errr.... assert?????  And a dt_set_errno in comment?
> 
> > +	offset = ctm.ctm_offset / NBBY;
> > +
> > +	/* add the thread->member offset */
> 
> Extra newline.
> 
> > +
> > +	type = ctf_lookup_by_name(cfp, "struct thread_struct");
> > +	if (type == CTF_ERR)
> > +		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
> 
> Errr.... assert?????  And a dt_set_errno in comment?
> 
> > +	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);
> 
> I think a better message would be "uregs[]: index out of bounds (%d)\n" (also
> more consistent).
> 
> > +	}
> > +	if (rc == -1)
> > +		assert(0); // return dt_set_errno(dtp, EDT_NOCTF);
> 
> Errr.... assert?????  And a dt_set_errno in comment?
> 
> > +	offset += ctm.ctm_offset / NBBY;
> > +
> > +	/* copy task->thread.member onto the stack*/
> 
> Extra newline and missing space at end of comment
> 
> > +
> > +	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));
> 
> We usually set up the arguments in ordinal order, if at all possible.
> 
> > +	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
> 
> See above.
> 
> > +
> > +#elif defined(__aarch64__)
> > +/* aarch64 */
> > +/* adapted from DTv1 kernel code arch/arm64/dtrace/dtrace_isa_arm64.c dtrace_getreg() */
> 
> Not necessary.
> 
> > +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);
> 
> I think a better message would be "uregs[]: index out of bounds (%d)\n" (also
> more consistent).
> 
> > +		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");
> 
> I think this is exposing more details than the average user cares to know.
> Just say "uregs[] is not supported on this kernel".
> 
> > +
> > +	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;
> 
> Move this into the code block below for uregs.
> 
> >  
> >  	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;
> 
> Move this into the code block below for uregs.  An perhaps add a comment that
> you can do this because we know the index is a constant integer (DT_NODE_INT).
> 
> >  	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..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..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..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..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..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
> > 
> > 
> > _______________________________________________
> > DTrace-devel mailing list
> > DTrace-devel at oss.oracle.com
> > https://oss.oracle.com/mailman/listinfo/dtrace-devel
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list