[DTrace-devel] [PATCH v2 4/6] procfs: implement d_execargs() for pr_psargs translator support
Kris Van Hees
kris.van.hees at oracle.com
Thu Jan 30 16:07:23 UTC 2025
On Thu, Jan 30, 2025 at 11:03:29AM +0000, Alan Maguire wrote:
> On 29/01/2025 07:00, Kris Van Hees 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).
> >
>
> thanks for doing this! I was wondering; would there be a case for
> generalizing the d_execargs() to also capture environment variables
> (which can be retrieved from the task struct mm struct in a similar
> null-separated var=value list)?
>
> In other words, we pass in the start/end pointers (arg_start, arg_end
> for task args, env_start, env_end for env var=value strings). Then the
> function would be a more generic, taking a set of strings between these
> two start/end addresses and putting them into a single, space-seperated
> string (d_coalesce_strings() or something might make sense as a name).
Since there are only two cases for this, a generic function would be less
useful I think. And honestly, there isn't even a real use case for doing the
same for environment variables because those key value pairs, and thus getting
them in a single string is less useful.
Ideally, we will be able to support pr_argv and pr_envp arrays in the future,
but that is still a little uncertain because such pointer arrays do not exist
in the Linux task structure. Therefore, to support that part of the psinfo
translator we'd need to create it on demand, and that bring up memory mgmt
issues (data life time tracking etc). Not fun.
> > 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