[DTrace-devel] [PATCH v2 4/6] procfs: implement d_execargs() for pr_psargs translator support

Kris Van Hees kris.van.hees at oracle.com
Fri Jan 31 16:37:32 UTC 2025


On Thu, Jan 30, 2025 at 02:22:44PM -0500, Eugene Loh wrote:
> Reviewed-by: Eugene Loh <eugene.loh at oracle.com>

Thanks.

> For
> test/unittest/funcs/d_execargs/tst.d_execargs.d
> test/unittest/proc/tst.pr_psargs.d
> how about a few more arguments?  E.g.,
> system("/bin/echo TEST abcde fghijkl");
> (I don't have anything particular in mind that this might catch. Just trying
> to poke a little harder.)

Sure, although it does not really improve the testing because we are looping
over all characters, changing '\0' into ' ', except for the last one.  If it
works for one it works for all, but I also do not mind adding a few extra
arguments.

> For bpf/d_execargs.S, how about ' ' instead of 32 (in that substitution
> loop).

OK

> For bpf/d_execargs.S, a few more comments would be nice.  Per your taste, of
> course.  But for me, e.g.,
> 
> - There should be a comment with the prototype of the function.
>   I think most other bpf/*.S files do this.

Sure.

> - One input arg is referred to as "args"... Most other bpf/*.S functions
>   refer to this as "dst" or something.  To me that makes more sense
>   since, as far as d_execargs() is concerned, this arg is the dest
>   location.

I prefer using 'args' here because this is a less generic function.  It is not
just a destination string but it is a destination string that has a particular
meaning/purpose.  A more generic name list 'dst' seems to be less useful here,
I think.

> - Comments refer to T.  This makes sense for the translators I
>   guess, but maybe saying it's the task struct or something.

That will be clear from adding the prototype.

> - Maybe it'd be helpful to lay out the strategy for how the registers
>   are being used?  E.g., %r9 points to the dest location, but meanwhile
>   used for scratch space.  %r6 is the pointer to memory we're accessing
>   so that, in case of probe_read() error, we know which address to report.

The code already includes comments showing what registers are for at the
places where they get assigned to.  I think adding more would merely add
clutter at this point.
> 
> On 1/29/25 02:00, Kris Van Hees via DTrace-devel wrote:
> > Implement d_execargs() to provide task argument string (pr_psargs)
> > for the psinfo translator.  It takes a task (struct task_struct) as
> > argument and returns a string.
> > 
> > psinfo->pr_psargs now simply calls d_execargs(T).
> > 
> > Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> > ---
> >   bpf/Build                                     |  1 +
> >   bpf/d_execargs.S                              | 91 +++++++++++++++++++
> >   dlibs/aarch64/5.11/procfs.d                   |  4 +-
> >   dlibs/aarch64/5.12/procfs.d                   |  4 +-
> >   dlibs/aarch64/5.14/procfs.d                   |  4 +-
> >   dlibs/aarch64/5.16/procfs.d                   |  4 +-
> >   dlibs/aarch64/5.2/procfs.d                    |  4 +-
> >   dlibs/aarch64/5.6/procfs.d                    |  4 +-
> >   dlibs/aarch64/6.1/procfs.d                    |  4 +-
> >   dlibs/aarch64/6.10/procfs.d                   |  4 +-
> >   dlibs/x86_64/5.11/procfs.d                    |  4 +-
> >   dlibs/x86_64/5.12/procfs.d                    |  4 +-
> >   dlibs/x86_64/5.14/procfs.d                    |  4 +-
> >   dlibs/x86_64/5.16/procfs.d                    |  4 +-
> >   dlibs/x86_64/5.2/procfs.d                     |  4 +-
> >   dlibs/x86_64/5.6/procfs.d                     |  4 +-
> >   dlibs/x86_64/6.1/procfs.d                     |  4 +-
> >   dlibs/x86_64/6.10/procfs.d                    |  4 +-
> >   include/dtrace/dif_defines.h                  |  7 +-
> >   libdtrace/dt_bpf.h                            | 21 +++--
> >   libdtrace/dt_cc.c                             | 33 ++++++-
> >   libdtrace/dt_cg.c                             |  9 +-
> >   libdtrace/dt_dlibs.c                          |  3 +
> >   libdtrace/dt_open.c                           |  2 +
> >   libdtrace/procfs.d.in                         |  4 +-
> >   .../d_execargs/err.D_PROTO_ARG.scalar_arg.d   | 16 ++++
> >   .../d_execargs/err.D_PROTO_ARG.scalar_arg.r   |  4 +
> >   .../d_execargs/err.D_PROTO_ARG.string_arg.d   | 16 ++++
> >   .../d_execargs/err.D_PROTO_ARG.string_arg.r   |  4 +
> >   .../d_execargs/err.D_PROTO_ARG.wrong_ptr.d    | 16 ++++
> >   .../d_execargs/err.D_PROTO_ARG.wrong_ptr.r    |  4 +
> >   .../d_execargs/err.D_PROTO_LEN.missing_arg.d  | 16 ++++
> >   .../d_execargs/err.D_PROTO_LEN.missing_arg.r  |  2 +
> >   .../err.D_PROTO_LEN.too_many_args.d           | 16 ++++
> >   .../err.D_PROTO_LEN.too_many_args.r           |  2 +
> >   .../funcs/d_execargs/tst.d_execargs.d         | 31 +++++++
> >   .../funcs/d_execargs/tst.d_execargs.r         |  2 +
> >   test/unittest/proc/tst.pr_psargs.d            | 31 +++++++
> >   test/unittest/proc/tst.pr_psargs.r            |  9 ++
> >   39 files changed, 339 insertions(+), 65 deletions(-)
> >   create mode 100644 bpf/d_execargs.S
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d
> >   create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r
> >   create mode 100644 test/unittest/funcs/d_execargs/tst.d_execargs.d
> >   create mode 100644 test/unittest/funcs/d_execargs/tst.d_execargs.r
> >   create mode 100644 test/unittest/proc/tst.pr_psargs.d
> >   create mode 100644 test/unittest/proc/tst.pr_psargs.r
> > 
> > diff --git a/bpf/Build b/bpf/Build
> > index 3e43f4b6..9355326c 100644
> > --- a/bpf/Build
> > +++ b/bpf/Build
> > @@ -24,6 +24,7 @@ bpf_dlib_SOURCES = \
> >   	agg_lqbin.c agg_qbin.c \
> >   	basename.S \
> >   	cleanpath.S \
> > +	d_execargs.S \
> >   	dirname.S \
> >   	get_agg.c \
> >   	get_bvar.c \
> > diff --git a/bpf/d_execargs.S b/bpf/d_execargs.S
> > new file mode 100644
> > index 00000000..3a5b1270
> > --- /dev/null
> > +++ b/bpf/d_execargs.S
> > @@ -0,0 +1,91 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2025, Oracle and/or its affiliates.
> > + */
> > +
> > +#include <bpf_asm_helpers.h>
> > +#include <dtrace/faults_defines.h>
> > +
> > +	.text
> > +	.align	4
> > +	.global	dt_d_execargs
> > +dt_d_execargs:
> > +	stxdw	[%fp+-8], %r1			/* save dctx to stack */
> > +	mov	%r9, %r3			/* %r9 = args */
> > +
> > +	mov	%r6, %r2			/* set %r6 in case of error */
> > +	jeq	%r6, 0, .Lerror
> > +
> > +	add	%r6, TASK_MM			/* ptr = &(T->mm) */
> > +
> > +	mov	%r1, %r9
> > +	mov	%r2, 8
> > +	mov	%r3, %r6
> > +	call	BPF_FUNC_probe_read
> > +	jne	%r0, 0, .Lerror
> > +
> > +	ldxdw	%r8, [%r9+0]			/* %r8 = T->mm */
> > +	jeq	%r8, 0, .Lempty
> > +	mov	%r6, %r8
> > +	add	%r6, TASK_MM_ARG_START		/* ptr = &(T->mm->arg_start) */
> > +
> > +	mov	%r1, %r9
> > +	mov	%r2, 8
> > +	mov	%r3, %r6
> > +	call	BPF_FUNC_probe_read
> > +	jne	%r0, 0, .Lerror
> > +
> > +	ldxdw	%r7, [%r9+0]			/* %r7 = T->mm->arg_start */
> > +	mov	%r6, %r8
> > +	add	%r6, TASK_MM_ARG_END		/* ptr = &(T->mm->arg_end) */
> > +
> > +	mov	%r1, %r9
> > +	mov	%r2, 8
> > +	mov	%r3, %r6
> > +	call	BPF_FUNC_probe_read
> > +	jne	%r0, 0, .Lerror
> > +
> > +	ldxdw	%r6, [%r9+0]			/* %r6 = T->mm->arg_end */
> > +
> > +	mov	%r8, %r6
> > +	sub	%r8, %r7			/* %r8 = len = arg_end - arg_start */
> > +	jslt	%r8, 2, .Lempty
> > +	mov	%r0, STRSZ
> > +	jslt	%r8, %r0, .Llen_ok
> > +	mov	%r8, %r0
> > +.Llen_ok:
> > +
> > +	/* read data from arg_start to arg_end */
> > +	mov	%r1, %r9
> > +	mov	%r2, %r8
> > +	mov	%r3, %r7
> > +	call	BPF_FUNC_probe_read		/* bpf_probe_read(&args, len + 1, arg_start) */
> > +	jne	%r0, 0, .Lerror
> > +
> > +	/* loop over args and replace '\0' with ' ' */
> > +	mov	%r1, %r8
> > +	sub	%r1, 2
> > +.Lloop:
> > +	mov	%r2, %r9
> > +	add	%r2, %r1
> > +	ldxb	%r0, [%r2+0]
> > +	jne	%r0, 0, .Lnot_nil
> > +	stb	[%r2+0], 32
> > +.Lnot_nil:
> > +	sub	%r1, 1
> > +	jsge	%r1, 0, .Lloop
> > +
> > +.Ldone:
> > +	mov	%r0, %r9
> > +	exit					/* return args */
> > +.Lerror:
> > +	ldxdw	%r1, [%fp+-8]
> > +	mov	%r2, PC
> > +	mov	%r3, DTRACEFLT_BADADDR
> > +	mov	%r4, %r6
> > +	call	dt_probe_error
> > +.Lempty:
> > +	mov	%r0, %r9
> > +	stb	[%r9+0], 0			/* args[0] = 0 */
> > +	exit					/* return args */
> > +	.size	dt_d_execargs, .-dt_d_execargs
> > diff --git a/dlibs/aarch64/5.11/procfs.d b/dlibs/aarch64/5.11/procfs.d
> > index 44ec4280..70a43ddf 100644
> > --- a/dlibs/aarch64/5.11/procfs.d
> > +++ b/dlibs/aarch64/5.11/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.12/procfs.d b/dlibs/aarch64/5.12/procfs.d
> > index 44ec4280..70a43ddf 100644
> > --- a/dlibs/aarch64/5.12/procfs.d
> > +++ b/dlibs/aarch64/5.12/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.14/procfs.d b/dlibs/aarch64/5.14/procfs.d
> > index 584ac325..ef27bb70 100644
> > --- a/dlibs/aarch64/5.14/procfs.d
> > +++ b/dlibs/aarch64/5.14/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.16/procfs.d b/dlibs/aarch64/5.16/procfs.d
> > index 5aabc6f1..cad2d2c5 100644
> > --- a/dlibs/aarch64/5.16/procfs.d
> > +++ b/dlibs/aarch64/5.16/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.2/procfs.d b/dlibs/aarch64/5.2/procfs.d
> > index 683ff5a8..6b1b1b9c 100644
> > --- a/dlibs/aarch64/5.2/procfs.d
> > +++ b/dlibs/aarch64/5.2/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.6/procfs.d b/dlibs/aarch64/5.6/procfs.d
> > index 44ec4280..70a43ddf 100644
> > --- a/dlibs/aarch64/5.6/procfs.d
> > +++ b/dlibs/aarch64/5.6/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/6.1/procfs.d b/dlibs/aarch64/6.1/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/aarch64/6.1/procfs.d
> > +++ b/dlibs/aarch64/6.1/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/6.10/procfs.d b/dlibs/aarch64/6.10/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/aarch64/6.10/procfs.d
> > +++ b/dlibs/aarch64/6.10/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.11/procfs.d b/dlibs/x86_64/5.11/procfs.d
> > index 7274554e..c2be76d8 100644
> > --- a/dlibs/x86_64/5.11/procfs.d
> > +++ b/dlibs/x86_64/5.11/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.12/procfs.d b/dlibs/x86_64/5.12/procfs.d
> > index 7274554e..c2be76d8 100644
> > --- a/dlibs/x86_64/5.12/procfs.d
> > +++ b/dlibs/x86_64/5.12/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.14/procfs.d b/dlibs/x86_64/5.14/procfs.d
> > index d1cf90d3..28fada6d 100644
> > --- a/dlibs/x86_64/5.14/procfs.d
> > +++ b/dlibs/x86_64/5.14/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.16/procfs.d b/dlibs/x86_64/5.16/procfs.d
> > index 5aabc6f1..cad2d2c5 100644
> > --- a/dlibs/x86_64/5.16/procfs.d
> > +++ b/dlibs/x86_64/5.16/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.2/procfs.d b/dlibs/x86_64/5.2/procfs.d
> > index 35538862..08696cf7 100644
> > --- a/dlibs/x86_64/5.2/procfs.d
> > +++ b/dlibs/x86_64/5.2/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.6/procfs.d b/dlibs/x86_64/5.6/procfs.d
> > index 7274554e..c2be76d8 100644
> > --- a/dlibs/x86_64/5.6/procfs.d
> > +++ b/dlibs/x86_64/5.6/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/6.1/procfs.d b/dlibs/x86_64/6.1/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/x86_64/6.1/procfs.d
> > +++ b/dlibs/x86_64/6.1/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/6.10/procfs.d b/dlibs/x86_64/6.10/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/x86_64/6.10/procfs.d
> > +++ b/dlibs/x86_64/6.10/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/include/dtrace/dif_defines.h b/include/dtrace/dif_defines.h
> > index c8c1d961..cd785723 100644
> > --- a/include/dtrace/dif_defines.h
> > +++ b/include/dtrace/dif_defines.h
> > @@ -207,10 +207,11 @@
> >   #define DIF_SUBR_INET_NTOP		41
> >   #define DIF_SUBR_INET_NTOA		42
> >   #define DIF_SUBR_INET_NTOA6		43
> > -#define DIF_SUBR_D_PATH			44
> > -#define DIF_SUBR_LINK_NTOP		45
> > +#define DIF_SUBR_LINK_NTOP		44
> > +#define DIF_SUBR_D_PATH			45
> > +#define DIF_SUBR_D_EXECARGS		46
> > -#define DIF_SUBR_MAX			45
> > +#define DIF_SUBR_MAX			46
> >   typedef uint32_t	dif_instr_t;
> > diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
> > index 6518de66..85934d2d 100644
> > --- a/libdtrace/dt_bpf.h
> > +++ b/libdtrace/dt_bpf.h
> > @@ -47,15 +47,18 @@ extern "C" {
> >   #define DT_CONST_TASK_TGID		12
> >   #define DT_CONST_TASK_REAL_PARENT	13
> >   #define DT_CONST_TASK_COMM		14
> > -#define DT_CONST_MUTEX_OWNER		15
> > -#define DT_CONST_RWLOCK_CNTS		16
> > -#define DT_CONST_DCTX_RODATA		17
> > -#define DT_CONST_RODATA_OFF		18
> > -#define DT_CONST_RODATA_SIZE		19
> > -#define DT_CONST_ZERO_OFF		20
> > -#define DT_CONST_STACK_OFF		21
> > -#define DT_CONST_STACK_SKIP		22
> > -#define DT_CONST_NPROBES		23
> > +#define DT_CONST_TASK_MM		15
> > +#define DT_CONST_TASK_MM_ARG_START	16
> > +#define DT_CONST_TASK_MM_ARG_END	17
> > +#define DT_CONST_MUTEX_OWNER		18
> > +#define DT_CONST_RWLOCK_CNTS		19
> > +#define DT_CONST_DCTX_RODATA		20
> > +#define DT_CONST_RODATA_OFF		21
> > +#define DT_CONST_RODATA_SIZE		22
> > +#define DT_CONST_ZERO_OFF		23
> > +#define DT_CONST_STACK_OFF		24
> > +#define DT_CONST_STACK_SKIP		25
> > +#define DT_CONST_NPROBES		26
> >   #define DT_BPF_LOG_SIZE_DEFAULT	(UINT32_MAX >> 8)
> >   #define DT_BPF_LOG_SIZE_SMALL	4096
> > diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
> > index 29cfbd84..1dc119ea 100644
> > --- a/libdtrace/dt_cc.c
> > +++ b/libdtrace/dt_cc.c
> > @@ -1082,7 +1082,8 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
> >   			case DT_CONST_TASK_PID:
> >   			case DT_CONST_TASK_TGID:
> >   			case DT_CONST_TASK_REAL_PARENT:
> > -			case DT_CONST_TASK_COMM: {
> > +			case DT_CONST_TASK_COMM:
> > +			case DT_CONST_TASK_MM: {
> >   				ctf_file_t *cfp = dtp->dt_shared_ctf;
> >   				ctf_id_t type;
> >   				ctf_membinfo_t ctm;
> > @@ -1108,6 +1109,36 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
> >   				case DT_CONST_TASK_COMM:
> >   					rc = ctf_member_info(cfp, type, "comm", &ctm);
> >   					break;
> > +				case DT_CONST_TASK_MM:
> > +					rc = ctf_member_info(cfp, type, "mm", &ctm);
> > +					break;
> > +				}
> > +				if (rc == CTF_ERR)
> > +					goto err_ctf;
> > +				nrp->dofr_data = ctm.ctm_offset / NBBY;
> > +				continue;
> > +			}
> > +			case DT_CONST_TASK_MM_ARG_START:
> > +			case DT_CONST_TASK_MM_ARG_END: {
> > +				ctf_file_t *cfp = dtp->dt_shared_ctf;
> > +				ctf_id_t type;
> > +				ctf_membinfo_t ctm;
> > +				int rc = 0;
> > +
> > +				if (!cfp)
> > +					return dt_set_errno(dtp, EDT_NOCTF);
> > +
> > +				type = ctf_lookup_by_name(cfp, "struct mm_struct");
> > +				if (type == CTF_ERR)
> > +					goto err_ctf;
> > +
> > +				switch (idp->di_id) {
> > +				case DT_CONST_TASK_MM_ARG_START:
> > +					rc = ctf_member_info(cfp, type, "arg_start", &ctm);
> > +					break;
> > +				case DT_CONST_TASK_MM_ARG_END:
> > +					rc = ctf_member_info(cfp, type, "arg_end", &ctm);
> > +					break;
> >   				}
> >   				if (rc == CTF_ERR)
> >   					goto err_ctf;
> > diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> > index 6e74b4b0..a1a39f3f 100644
> > --- a/libdtrace/dt_cg.c
> > +++ b/libdtrace/dt_cg.c
> > @@ -3300,7 +3300,6 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> >   	}
> >   	/* built-in variables (note: args[] is handled in dt_cg_array_op) */
> > -	/* Special case for arg0 through arg9; encode as args[n] */
> >   	if (idp->di_id >= DIF_VAR_ARG0 && idp->di_id <= DIF_VAR_ARG9) {
> >   		fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_bvar_args");
> >   		idx = idp->di_id - DIF_VAR_ARG0;
> > @@ -6661,6 +6660,13 @@ dt_cg_subr_inet_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> >   	tnp->dn_tstring = NULL;
> >   }
> > +static void
> > +dt_cg_subr_d_execargs(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > +{
> > +	dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_d_execargs", 0,
> > +				  DT_IGNOR, 0, DT_IGNOR, 0);
> > +}
> > +
> >   static void
> >   dt_cg_subr_d_path(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> >   {
> > @@ -6758,6 +6764,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
> >   	[DIF_SUBR_INET_NTOP]		= &dt_cg_subr_inet_ntop,
> >   	[DIF_SUBR_INET_NTOA]		= &dt_cg_subr_inet_ntoa,
> >   	[DIF_SUBR_INET_NTOA6]		= &dt_cg_subr_inet_ntoa6,
> > +	[DIF_SUBR_D_EXECARGS]		= &dt_cg_subr_d_execargs,
> >   	[DIF_SUBR_D_PATH]		= &dt_cg_subr_d_path,
> >   	[DIF_SUBR_LINK_NTOP]		= &dt_cg_subr_link_ntop,
> >   };
> > diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
> > index 07d22afd..9ad4f5e7 100644
> > --- a/libdtrace/dt_dlibs.c
> > +++ b/libdtrace/dt_dlibs.c
> > @@ -89,6 +89,9 @@ static const dt_ident_t		dt_bpf_symbols[] = {
> >   	DT_BPF_SYMBOL_ID(TASK_TGID, DT_IDENT_SCALAR, DT_CONST_TASK_TGID),
> >   	DT_BPF_SYMBOL_ID(TASK_REAL_PARENT, DT_IDENT_SCALAR, DT_CONST_TASK_REAL_PARENT),
> >   	DT_BPF_SYMBOL_ID(TASK_COMM, DT_IDENT_SCALAR, DT_CONST_TASK_COMM),
> > +	DT_BPF_SYMBOL_ID(TASK_MM, DT_IDENT_SCALAR, DT_CONST_TASK_MM),
> > +	DT_BPF_SYMBOL_ID(TASK_MM_ARG_START, DT_IDENT_SCALAR, DT_CONST_TASK_MM_ARG_START),
> > +	DT_BPF_SYMBOL_ID(TASK_MM_ARG_END, DT_IDENT_SCALAR, DT_CONST_TASK_MM_ARG_END),
> >   	DT_BPF_SYMBOL_ID(MUTEX_OWNER, DT_IDENT_SCALAR, DT_CONST_MUTEX_OWNER),
> >   	DT_BPF_SYMBOL_ID(RWLOCK_CNTS, DT_IDENT_SCALAR, DT_CONST_RWLOCK_CNTS),
> >   	DT_BPF_SYMBOL_ID(DCTX_RODATA, DT_IDENT_SCALAR, DT_CONST_DCTX_RODATA),
> > diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> > index a0205887..c8208de6 100644
> > --- a/libdtrace/dt_open.c
> > +++ b/libdtrace/dt_open.c
> > @@ -138,6 +138,8 @@ static const dt_ident_t _dtrace_globals[] = {
> >   	{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_PRIVATE,
> >   	DTRACE_CLASS_COMMON }, DT_VERS_1_0,
> >   	&dt_idops_type, "vmlinux`struct task_struct *" },
> > +{ "d_execargs", DT_IDENT_FUNC, 0, DIF_SUBR_D_EXECARGS, DT_ATTR_EVOLCMN,
> > +	DT_VERS_2_0, &dt_idops_func, "string(vmlinux`struct task_struct *)" },
> >   { "d_path", DT_IDENT_FUNC, DT_IDFLG_DPTR, DIF_SUBR_D_PATH, DT_ATTR_EVOLCMN,
> >   	DT_VERS_1_0, &dt_idops_func, "string(struct path *)" },
> >   { "ddi_pathname", DT_IDENT_FUNC, 0, DIF_SUBR_DDI_PATHNAME,
> > diff --git a/libdtrace/procfs.d.in b/libdtrace/procfs.d.in
> > index 038cf69b..e9d50349 100644
> > --- a/libdtrace/procfs.d.in
> > +++ b/libdtrace/procfs.d.in
> > @@ -179,9 +179,7 @@ translator psinfo_t < struct task_struct *T > {
> >   				   : (struct tty_struct *)-1;
> >   	pr_fname = T->comm;
> > -/*
> > -	pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > +	pr_psargs = d_execargs(T);
> >   	pr_wstat = 0;
> >   /*
> >   	pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d
> > new file mode 100644
> > index 00000000..c707184d
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The argument to d_execargs() should be a (struct task_struct *).
> > + */
> > +
> > +BEGIN
> > +{
> > +	trace(d_execargs(1));
> > +	exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r
> > new file mode 100644
> > index 00000000..0e9cda07
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r
> > @@ -0,0 +1,4 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d: [D_PROTO_ARG] line 14: d_execargs( ) argument #1 is incompatible with prototype:
> > +	prototype: struct task_struct *
> > +	 argument: int
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d
> > new file mode 100644
> > index 00000000..ba419689
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The argument to d_execargs() should be (struct task_struct *).
> > + */
> > +
> > +BEGIN
> > +{
> > +	trace(d_execargs("a"));
> > +	exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r
> > new file mode 100644
> > index 00000000..ac1c1401
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r
> > @@ -0,0 +1,4 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d: [D_PROTO_ARG] line 14: d_execargs( ) argument #1 is incompatible with prototype:
> > +	prototype: struct task_struct *
> > +	 argument: string
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d
> > new file mode 100644
> > index 00000000..473e35e4
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The argument to d_execargs() should be (struct task_struct *).
> > + */
> > +
> > +BEGIN
> > +{
> > +	trace(d_execargs(curthread->mm));
> > +	exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r
> > new file mode 100644
> > index 00000000..842371a3
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r
> > @@ -0,0 +1,4 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d: [D_PROTO_ARG] line 14: d_execargs( ) argument #1 is incompatible with prototype:
> > +	prototype: struct task_struct *
> > +	 argument: struct mm_struct *
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d
> > new file mode 100644
> > index 00000000..86b1b237
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, 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: d_execargs() requires an argument
> > + */
> > +
> > +BEGIN
> > +{
> > +	trace(d_execargs());
> > +	exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r
> > new file mode 100644
> > index 00000000..a4fcd162
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r
> > @@ -0,0 +1,2 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d: [D_PROTO_LEN] line 14: d_execargs( ) prototype mismatch: 0 args passed, 1 expected
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d
> > new file mode 100644
> > index 00000000..3add63f6
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The d_execargs() subroutine accepts no more than one argument.
> > + */
> > +
> > +BEGIN
> > +{
> > +	trace(d_execargs(curthread, 1));
> > +	exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r
> > new file mode 100644
> > index 00000000..f5a982ff
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r
> > @@ -0,0 +1,2 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d: [D_PROTO_LEN] line 14: d_execargs( ) prototype mismatch: 2 args passed, 1 expected
> > diff --git a/test/unittest/funcs/d_execargs/tst.d_execargs.d b/test/unittest/funcs/d_execargs/tst.d_execargs.d
> > new file mode 100644
> > index 00000000..b8b141aa
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/tst.d_execargs.d
> > @@ -0,0 +1,31 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, 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: d_execargs() provides correct results.
> > + */
> > +
> > +#pragma D option destructive
> > +#pragma D option quiet
> > +
> > +BEGIN
> > +{
> > +	mypid = pid;
> > +	system("/bin/echo TEST");
> > +}
> > +
> > +proc:::exec-success
> > +/progenyof(mypid) && d_execargs(curthread) == "/bin/echo TEST"/
> > +{
> > +	trace(d_execargs(curthread));
> > +	exit(0);
> > +}
> > +
> > +tick-1s
> > +{
> > +	exit(1);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/tst.d_execargs.r b/test/unittest/funcs/d_execargs/tst.d_execargs.r
> > new file mode 100644
> > index 00000000..d8ff6689
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/tst.d_execargs.r
> > @@ -0,0 +1,2 @@
> > +TEST
> > +/bin/echo TEST
> > diff --git a/test/unittest/proc/tst.pr_psargs.d b/test/unittest/proc/tst.pr_psargs.d
> > new file mode 100644
> > index 00000000..902ac1a3
> > --- /dev/null
> > +++ b/test/unittest/proc/tst.pr_psargs.d
> > @@ -0,0 +1,31 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, 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: psinfo->pr_psargs provides correct results.
> > + */
> > +
> > +#pragma D option destructive
> > +#pragma D option quiet
> > +
> > +BEGIN
> > +{
> > +	mypid = pid;
> > +	system("/bin/echo TEST");
> > +}
> > +
> > +proc:::exec-success
> > +/progenyof(mypid) && curpsinfo->pr_psargs == "/bin/echo TEST"/
> > +{
> > +	trace(curpsinfo->pr_psargs);
> > +	exit(0);
> > +}
> > +
> > +tick-1s
> > +{
> > +	exit(1);
> > +}
> > diff --git a/test/unittest/proc/tst.pr_psargs.r b/test/unittest/proc/tst.pr_psargs.r
> > new file mode 100644
> > index 00000000..397c8717
> > --- /dev/null
> > +++ b/test/unittest/proc/tst.pr_psargs.r
> > @@ -0,0 +1,9 @@
> > +TEST
> > +
> > +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> > +         0: 2f 62 69 6e 2f 65 63 68 6f 20 54 45 53 54 00 00  /bin/echo TEST..
> > +        10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> > +        20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> > +        30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> > +        40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
> > +



More information about the DTrace-devel mailing list