[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