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

Eugene Loh eugene.loh at oracle.com
Thu Jan 30 19:22:44 UTC 2025


Reviewed-by: Eugene Loh <eugene.loh at oracle.com>

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.)

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

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.

- 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.

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

- 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.

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