[DTrace-devel] [PATCH v2 4/6] procfs: implement d_execargs() for pr_psargs translator support
Kris Van Hees
kris.van.hees at oracle.com
Fri Jan 31 16:37:32 UTC 2025
On Thu, Jan 30, 2025 at 02:22:44PM -0500, Eugene Loh wrote:
> Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
Thanks.
> For
> test/unittest/funcs/d_execargs/tst.d_execargs.d
> test/unittest/proc/tst.pr_psargs.d
> how about a few more arguments? E.g.,
> system("/bin/echo TEST abcde fghijkl");
> (I don't have anything particular in mind that this might catch. Just trying
> to poke a little harder.)
Sure, although it does not really improve the testing because we are looping
over all characters, changing '\0' into ' ', except for the last one. If it
works for one it works for all, but I also do not mind adding a few extra
arguments.
> For bpf/d_execargs.S, how about ' ' instead of 32 (in that substitution
> loop).
OK
> For bpf/d_execargs.S, a few more comments would be nice. Per your taste, of
> course. But for me, e.g.,
>
> - There should be a comment with the prototype of the function.
> I think most other bpf/*.S files do this.
Sure.
> - One input arg is referred to as "args"... Most other bpf/*.S functions
> refer to this as "dst" or something. To me that makes more sense
> since, as far as d_execargs() is concerned, this arg is the dest
> location.
I prefer using 'args' here because this is a less generic function. It is not
just a destination string but it is a destination string that has a particular
meaning/purpose. A more generic name list 'dst' seems to be less useful here,
I think.
> - Comments refer to T. This makes sense for the translators I
> guess, but maybe saying it's the task struct or something.
That will be clear from adding the prototype.
> - Maybe it'd be helpful to lay out the strategy for how the registers
> are being used? E.g., %r9 points to the dest location, but meanwhile
> used for scratch space. %r6 is the pointer to memory we're accessing
> so that, in case of probe_read() error, we know which address to report.
The code already includes comments showing what registers are for at the
places where they get assigned to. I think adding more would merely add
clutter at this point.
>
> On 1/29/25 02:00, Kris Van Hees via DTrace-devel wrote:
> > Implement d_execargs() to provide task argument string (pr_psargs)
> > for the psinfo translator. It takes a task (struct task_struct) as
> > argument and returns a string.
> >
> > psinfo->pr_psargs now simply calls d_execargs(T).
> >
> > Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> > ---
> > bpf/Build | 1 +
> > bpf/d_execargs.S | 91 +++++++++++++++++++
> > dlibs/aarch64/5.11/procfs.d | 4 +-
> > dlibs/aarch64/5.12/procfs.d | 4 +-
> > dlibs/aarch64/5.14/procfs.d | 4 +-
> > dlibs/aarch64/5.16/procfs.d | 4 +-
> > dlibs/aarch64/5.2/procfs.d | 4 +-
> > dlibs/aarch64/5.6/procfs.d | 4 +-
> > dlibs/aarch64/6.1/procfs.d | 4 +-
> > dlibs/aarch64/6.10/procfs.d | 4 +-
> > dlibs/x86_64/5.11/procfs.d | 4 +-
> > dlibs/x86_64/5.12/procfs.d | 4 +-
> > dlibs/x86_64/5.14/procfs.d | 4 +-
> > dlibs/x86_64/5.16/procfs.d | 4 +-
> > dlibs/x86_64/5.2/procfs.d | 4 +-
> > dlibs/x86_64/5.6/procfs.d | 4 +-
> > dlibs/x86_64/6.1/procfs.d | 4 +-
> > dlibs/x86_64/6.10/procfs.d | 4 +-
> > include/dtrace/dif_defines.h | 7 +-
> > libdtrace/dt_bpf.h | 21 +++--
> > libdtrace/dt_cc.c | 33 ++++++-
> > libdtrace/dt_cg.c | 9 +-
> > libdtrace/dt_dlibs.c | 3 +
> > libdtrace/dt_open.c | 2 +
> > libdtrace/procfs.d.in | 4 +-
> > .../d_execargs/err.D_PROTO_ARG.scalar_arg.d | 16 ++++
> > .../d_execargs/err.D_PROTO_ARG.scalar_arg.r | 4 +
> > .../d_execargs/err.D_PROTO_ARG.string_arg.d | 16 ++++
> > .../d_execargs/err.D_PROTO_ARG.string_arg.r | 4 +
> > .../d_execargs/err.D_PROTO_ARG.wrong_ptr.d | 16 ++++
> > .../d_execargs/err.D_PROTO_ARG.wrong_ptr.r | 4 +
> > .../d_execargs/err.D_PROTO_LEN.missing_arg.d | 16 ++++
> > .../d_execargs/err.D_PROTO_LEN.missing_arg.r | 2 +
> > .../err.D_PROTO_LEN.too_many_args.d | 16 ++++
> > .../err.D_PROTO_LEN.too_many_args.r | 2 +
> > .../funcs/d_execargs/tst.d_execargs.d | 31 +++++++
> > .../funcs/d_execargs/tst.d_execargs.r | 2 +
> > test/unittest/proc/tst.pr_psargs.d | 31 +++++++
> > test/unittest/proc/tst.pr_psargs.r | 9 ++
> > 39 files changed, 339 insertions(+), 65 deletions(-)
> > create mode 100644 bpf/d_execargs.S
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d
> > create mode 100644 test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r
> > create mode 100644 test/unittest/funcs/d_execargs/tst.d_execargs.d
> > create mode 100644 test/unittest/funcs/d_execargs/tst.d_execargs.r
> > create mode 100644 test/unittest/proc/tst.pr_psargs.d
> > create mode 100644 test/unittest/proc/tst.pr_psargs.r
> >
> > diff --git a/bpf/Build b/bpf/Build
> > index 3e43f4b6..9355326c 100644
> > --- a/bpf/Build
> > +++ b/bpf/Build
> > @@ -24,6 +24,7 @@ bpf_dlib_SOURCES = \
> > agg_lqbin.c agg_qbin.c \
> > basename.S \
> > cleanpath.S \
> > + d_execargs.S \
> > dirname.S \
> > get_agg.c \
> > get_bvar.c \
> > diff --git a/bpf/d_execargs.S b/bpf/d_execargs.S
> > new file mode 100644
> > index 00000000..3a5b1270
> > --- /dev/null
> > +++ b/bpf/d_execargs.S
> > @@ -0,0 +1,91 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2025, Oracle and/or its affiliates.
> > + */
> > +
> > +#include <bpf_asm_helpers.h>
> > +#include <dtrace/faults_defines.h>
> > +
> > + .text
> > + .align 4
> > + .global dt_d_execargs
> > +dt_d_execargs:
> > + stxdw [%fp+-8], %r1 /* save dctx to stack */
> > + mov %r9, %r3 /* %r9 = args */
> > +
> > + mov %r6, %r2 /* set %r6 in case of error */
> > + jeq %r6, 0, .Lerror
> > +
> > + add %r6, TASK_MM /* ptr = &(T->mm) */
> > +
> > + mov %r1, %r9
> > + mov %r2, 8
> > + mov %r3, %r6
> > + call BPF_FUNC_probe_read
> > + jne %r0, 0, .Lerror
> > +
> > + ldxdw %r8, [%r9+0] /* %r8 = T->mm */
> > + jeq %r8, 0, .Lempty
> > + mov %r6, %r8
> > + add %r6, TASK_MM_ARG_START /* ptr = &(T->mm->arg_start) */
> > +
> > + mov %r1, %r9
> > + mov %r2, 8
> > + mov %r3, %r6
> > + call BPF_FUNC_probe_read
> > + jne %r0, 0, .Lerror
> > +
> > + ldxdw %r7, [%r9+0] /* %r7 = T->mm->arg_start */
> > + mov %r6, %r8
> > + add %r6, TASK_MM_ARG_END /* ptr = &(T->mm->arg_end) */
> > +
> > + mov %r1, %r9
> > + mov %r2, 8
> > + mov %r3, %r6
> > + call BPF_FUNC_probe_read
> > + jne %r0, 0, .Lerror
> > +
> > + ldxdw %r6, [%r9+0] /* %r6 = T->mm->arg_end */
> > +
> > + mov %r8, %r6
> > + sub %r8, %r7 /* %r8 = len = arg_end - arg_start */
> > + jslt %r8, 2, .Lempty
> > + mov %r0, STRSZ
> > + jslt %r8, %r0, .Llen_ok
> > + mov %r8, %r0
> > +.Llen_ok:
> > +
> > + /* read data from arg_start to arg_end */
> > + mov %r1, %r9
> > + mov %r2, %r8
> > + mov %r3, %r7
> > + call BPF_FUNC_probe_read /* bpf_probe_read(&args, len + 1, arg_start) */
> > + jne %r0, 0, .Lerror
> > +
> > + /* loop over args and replace '\0' with ' ' */
> > + mov %r1, %r8
> > + sub %r1, 2
> > +.Lloop:
> > + mov %r2, %r9
> > + add %r2, %r1
> > + ldxb %r0, [%r2+0]
> > + jne %r0, 0, .Lnot_nil
> > + stb [%r2+0], 32
> > +.Lnot_nil:
> > + sub %r1, 1
> > + jsge %r1, 0, .Lloop
> > +
> > +.Ldone:
> > + mov %r0, %r9
> > + exit /* return args */
> > +.Lerror:
> > + ldxdw %r1, [%fp+-8]
> > + mov %r2, PC
> > + mov %r3, DTRACEFLT_BADADDR
> > + mov %r4, %r6
> > + call dt_probe_error
> > +.Lempty:
> > + mov %r0, %r9
> > + stb [%r9+0], 0 /* args[0] = 0 */
> > + exit /* return args */
> > + .size dt_d_execargs, .-dt_d_execargs
> > diff --git a/dlibs/aarch64/5.11/procfs.d b/dlibs/aarch64/5.11/procfs.d
> > index 44ec4280..70a43ddf 100644
> > --- a/dlibs/aarch64/5.11/procfs.d
> > +++ b/dlibs/aarch64/5.11/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.12/procfs.d b/dlibs/aarch64/5.12/procfs.d
> > index 44ec4280..70a43ddf 100644
> > --- a/dlibs/aarch64/5.12/procfs.d
> > +++ b/dlibs/aarch64/5.12/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.14/procfs.d b/dlibs/aarch64/5.14/procfs.d
> > index 584ac325..ef27bb70 100644
> > --- a/dlibs/aarch64/5.14/procfs.d
> > +++ b/dlibs/aarch64/5.14/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.16/procfs.d b/dlibs/aarch64/5.16/procfs.d
> > index 5aabc6f1..cad2d2c5 100644
> > --- a/dlibs/aarch64/5.16/procfs.d
> > +++ b/dlibs/aarch64/5.16/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.2/procfs.d b/dlibs/aarch64/5.2/procfs.d
> > index 683ff5a8..6b1b1b9c 100644
> > --- a/dlibs/aarch64/5.2/procfs.d
> > +++ b/dlibs/aarch64/5.2/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/5.6/procfs.d b/dlibs/aarch64/5.6/procfs.d
> > index 44ec4280..70a43ddf 100644
> > --- a/dlibs/aarch64/5.6/procfs.d
> > +++ b/dlibs/aarch64/5.6/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/6.1/procfs.d b/dlibs/aarch64/6.1/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/aarch64/6.1/procfs.d
> > +++ b/dlibs/aarch64/6.1/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/aarch64/6.10/procfs.d b/dlibs/aarch64/6.10/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/aarch64/6.10/procfs.d
> > +++ b/dlibs/aarch64/6.10/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.11/procfs.d b/dlibs/x86_64/5.11/procfs.d
> > index 7274554e..c2be76d8 100644
> > --- a/dlibs/x86_64/5.11/procfs.d
> > +++ b/dlibs/x86_64/5.11/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.12/procfs.d b/dlibs/x86_64/5.12/procfs.d
> > index 7274554e..c2be76d8 100644
> > --- a/dlibs/x86_64/5.12/procfs.d
> > +++ b/dlibs/x86_64/5.12/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.14/procfs.d b/dlibs/x86_64/5.14/procfs.d
> > index d1cf90d3..28fada6d 100644
> > --- a/dlibs/x86_64/5.14/procfs.d
> > +++ b/dlibs/x86_64/5.14/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.16/procfs.d b/dlibs/x86_64/5.16/procfs.d
> > index 5aabc6f1..cad2d2c5 100644
> > --- a/dlibs/x86_64/5.16/procfs.d
> > +++ b/dlibs/x86_64/5.16/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.2/procfs.d b/dlibs/x86_64/5.2/procfs.d
> > index 35538862..08696cf7 100644
> > --- a/dlibs/x86_64/5.2/procfs.d
> > +++ b/dlibs/x86_64/5.2/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/5.6/procfs.d b/dlibs/x86_64/5.6/procfs.d
> > index 7274554e..c2be76d8 100644
> > --- a/dlibs/x86_64/5.6/procfs.d
> > +++ b/dlibs/x86_64/5.6/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/6.1/procfs.d b/dlibs/x86_64/6.1/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/x86_64/6.1/procfs.d
> > +++ b/dlibs/x86_64/6.1/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/dlibs/x86_64/6.10/procfs.d b/dlibs/x86_64/6.10/procfs.d
> > index 5d7873b5..4cb7b77c 100644
> > --- a/dlibs/x86_64/6.10/procfs.d
> > +++ b/dlibs/x86_64/6.10/procfs.d
> > @@ -141,9 +141,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/include/dtrace/dif_defines.h b/include/dtrace/dif_defines.h
> > index c8c1d961..cd785723 100644
> > --- a/include/dtrace/dif_defines.h
> > +++ b/include/dtrace/dif_defines.h
> > @@ -207,10 +207,11 @@
> > #define DIF_SUBR_INET_NTOP 41
> > #define DIF_SUBR_INET_NTOA 42
> > #define DIF_SUBR_INET_NTOA6 43
> > -#define DIF_SUBR_D_PATH 44
> > -#define DIF_SUBR_LINK_NTOP 45
> > +#define DIF_SUBR_LINK_NTOP 44
> > +#define DIF_SUBR_D_PATH 45
> > +#define DIF_SUBR_D_EXECARGS 46
> > -#define DIF_SUBR_MAX 45
> > +#define DIF_SUBR_MAX 46
> > typedef uint32_t dif_instr_t;
> > diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
> > index 6518de66..85934d2d 100644
> > --- a/libdtrace/dt_bpf.h
> > +++ b/libdtrace/dt_bpf.h
> > @@ -47,15 +47,18 @@ extern "C" {
> > #define DT_CONST_TASK_TGID 12
> > #define DT_CONST_TASK_REAL_PARENT 13
> > #define DT_CONST_TASK_COMM 14
> > -#define DT_CONST_MUTEX_OWNER 15
> > -#define DT_CONST_RWLOCK_CNTS 16
> > -#define DT_CONST_DCTX_RODATA 17
> > -#define DT_CONST_RODATA_OFF 18
> > -#define DT_CONST_RODATA_SIZE 19
> > -#define DT_CONST_ZERO_OFF 20
> > -#define DT_CONST_STACK_OFF 21
> > -#define DT_CONST_STACK_SKIP 22
> > -#define DT_CONST_NPROBES 23
> > +#define DT_CONST_TASK_MM 15
> > +#define DT_CONST_TASK_MM_ARG_START 16
> > +#define DT_CONST_TASK_MM_ARG_END 17
> > +#define DT_CONST_MUTEX_OWNER 18
> > +#define DT_CONST_RWLOCK_CNTS 19
> > +#define DT_CONST_DCTX_RODATA 20
> > +#define DT_CONST_RODATA_OFF 21
> > +#define DT_CONST_RODATA_SIZE 22
> > +#define DT_CONST_ZERO_OFF 23
> > +#define DT_CONST_STACK_OFF 24
> > +#define DT_CONST_STACK_SKIP 25
> > +#define DT_CONST_NPROBES 26
> > #define DT_BPF_LOG_SIZE_DEFAULT (UINT32_MAX >> 8)
> > #define DT_BPF_LOG_SIZE_SMALL 4096
> > diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
> > index 29cfbd84..1dc119ea 100644
> > --- a/libdtrace/dt_cc.c
> > +++ b/libdtrace/dt_cc.c
> > @@ -1082,7 +1082,8 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
> > case DT_CONST_TASK_PID:
> > case DT_CONST_TASK_TGID:
> > case DT_CONST_TASK_REAL_PARENT:
> > - case DT_CONST_TASK_COMM: {
> > + case DT_CONST_TASK_COMM:
> > + case DT_CONST_TASK_MM: {
> > ctf_file_t *cfp = dtp->dt_shared_ctf;
> > ctf_id_t type;
> > ctf_membinfo_t ctm;
> > @@ -1108,6 +1109,36 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
> > case DT_CONST_TASK_COMM:
> > rc = ctf_member_info(cfp, type, "comm", &ctm);
> > break;
> > + case DT_CONST_TASK_MM:
> > + rc = ctf_member_info(cfp, type, "mm", &ctm);
> > + break;
> > + }
> > + if (rc == CTF_ERR)
> > + goto err_ctf;
> > + nrp->dofr_data = ctm.ctm_offset / NBBY;
> > + continue;
> > + }
> > + case DT_CONST_TASK_MM_ARG_START:
> > + case DT_CONST_TASK_MM_ARG_END: {
> > + ctf_file_t *cfp = dtp->dt_shared_ctf;
> > + ctf_id_t type;
> > + ctf_membinfo_t ctm;
> > + int rc = 0;
> > +
> > + if (!cfp)
> > + return dt_set_errno(dtp, EDT_NOCTF);
> > +
> > + type = ctf_lookup_by_name(cfp, "struct mm_struct");
> > + if (type == CTF_ERR)
> > + goto err_ctf;
> > +
> > + switch (idp->di_id) {
> > + case DT_CONST_TASK_MM_ARG_START:
> > + rc = ctf_member_info(cfp, type, "arg_start", &ctm);
> > + break;
> > + case DT_CONST_TASK_MM_ARG_END:
> > + rc = ctf_member_info(cfp, type, "arg_end", &ctm);
> > + break;
> > }
> > if (rc == CTF_ERR)
> > goto err_ctf;
> > diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> > index 6e74b4b0..a1a39f3f 100644
> > --- a/libdtrace/dt_cg.c
> > +++ b/libdtrace/dt_cg.c
> > @@ -3300,7 +3300,6 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > }
> > /* built-in variables (note: args[] is handled in dt_cg_array_op) */
> > - /* Special case for arg0 through arg9; encode as args[n] */
> > if (idp->di_id >= DIF_VAR_ARG0 && idp->di_id <= DIF_VAR_ARG9) {
> > fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_bvar_args");
> > idx = idp->di_id - DIF_VAR_ARG0;
> > @@ -6661,6 +6660,13 @@ dt_cg_subr_inet_ntop(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > tnp->dn_tstring = NULL;
> > }
> > +static void
> > +dt_cg_subr_d_execargs(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > +{
> > + dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_d_execargs", 0,
> > + DT_IGNOR, 0, DT_IGNOR, 0);
> > +}
> > +
> > static void
> > dt_cg_subr_d_path(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > {
> > @@ -6758,6 +6764,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
> > [DIF_SUBR_INET_NTOP] = &dt_cg_subr_inet_ntop,
> > [DIF_SUBR_INET_NTOA] = &dt_cg_subr_inet_ntoa,
> > [DIF_SUBR_INET_NTOA6] = &dt_cg_subr_inet_ntoa6,
> > + [DIF_SUBR_D_EXECARGS] = &dt_cg_subr_d_execargs,
> > [DIF_SUBR_D_PATH] = &dt_cg_subr_d_path,
> > [DIF_SUBR_LINK_NTOP] = &dt_cg_subr_link_ntop,
> > };
> > diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
> > index 07d22afd..9ad4f5e7 100644
> > --- a/libdtrace/dt_dlibs.c
> > +++ b/libdtrace/dt_dlibs.c
> > @@ -89,6 +89,9 @@ static const dt_ident_t dt_bpf_symbols[] = {
> > DT_BPF_SYMBOL_ID(TASK_TGID, DT_IDENT_SCALAR, DT_CONST_TASK_TGID),
> > DT_BPF_SYMBOL_ID(TASK_REAL_PARENT, DT_IDENT_SCALAR, DT_CONST_TASK_REAL_PARENT),
> > DT_BPF_SYMBOL_ID(TASK_COMM, DT_IDENT_SCALAR, DT_CONST_TASK_COMM),
> > + DT_BPF_SYMBOL_ID(TASK_MM, DT_IDENT_SCALAR, DT_CONST_TASK_MM),
> > + DT_BPF_SYMBOL_ID(TASK_MM_ARG_START, DT_IDENT_SCALAR, DT_CONST_TASK_MM_ARG_START),
> > + DT_BPF_SYMBOL_ID(TASK_MM_ARG_END, DT_IDENT_SCALAR, DT_CONST_TASK_MM_ARG_END),
> > DT_BPF_SYMBOL_ID(MUTEX_OWNER, DT_IDENT_SCALAR, DT_CONST_MUTEX_OWNER),
> > DT_BPF_SYMBOL_ID(RWLOCK_CNTS, DT_IDENT_SCALAR, DT_CONST_RWLOCK_CNTS),
> > DT_BPF_SYMBOL_ID(DCTX_RODATA, DT_IDENT_SCALAR, DT_CONST_DCTX_RODATA),
> > diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> > index a0205887..c8208de6 100644
> > --- a/libdtrace/dt_open.c
> > +++ b/libdtrace/dt_open.c
> > @@ -138,6 +138,8 @@ static const dt_ident_t _dtrace_globals[] = {
> > { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_PRIVATE,
> > DTRACE_CLASS_COMMON }, DT_VERS_1_0,
> > &dt_idops_type, "vmlinux`struct task_struct *" },
> > +{ "d_execargs", DT_IDENT_FUNC, 0, DIF_SUBR_D_EXECARGS, DT_ATTR_EVOLCMN,
> > + DT_VERS_2_0, &dt_idops_func, "string(vmlinux`struct task_struct *)" },
> > { "d_path", DT_IDENT_FUNC, DT_IDFLG_DPTR, DIF_SUBR_D_PATH, DT_ATTR_EVOLCMN,
> > DT_VERS_1_0, &dt_idops_func, "string(struct path *)" },
> > { "ddi_pathname", DT_IDENT_FUNC, 0, DIF_SUBR_DDI_PATHNAME,
> > diff --git a/libdtrace/procfs.d.in b/libdtrace/procfs.d.in
> > index 038cf69b..e9d50349 100644
> > --- a/libdtrace/procfs.d.in
> > +++ b/libdtrace/procfs.d.in
> > @@ -179,9 +179,7 @@ translator psinfo_t < struct task_struct *T > {
> > : (struct tty_struct *)-1;
> > pr_fname = T->comm;
> > -/*
> > - pr_psargs = stringof(get_psinfo(T)->__psinfo(psargs));
> > - */
> > + pr_psargs = d_execargs(T);
> > pr_wstat = 0;
> > /*
> > pr_argc = get_psinfo(T)->__psinfo(argc);
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d
> > new file mode 100644
> > index 00000000..c707184d
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The argument to d_execargs() should be a (struct task_struct *).
> > + */
> > +
> > +BEGIN
> > +{
> > + trace(d_execargs(1));
> > + exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r
> > new file mode 100644
> > index 00000000..0e9cda07
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.r
> > @@ -0,0 +1,4 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_ARG.scalar_arg.d: [D_PROTO_ARG] line 14: d_execargs( ) argument #1 is incompatible with prototype:
> > + prototype: struct task_struct *
> > + argument: int
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d
> > new file mode 100644
> > index 00000000..ba419689
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The argument to d_execargs() should be (struct task_struct *).
> > + */
> > +
> > +BEGIN
> > +{
> > + trace(d_execargs("a"));
> > + exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r
> > new file mode 100644
> > index 00000000..ac1c1401
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.r
> > @@ -0,0 +1,4 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_ARG.string_arg.d: [D_PROTO_ARG] line 14: d_execargs( ) argument #1 is incompatible with prototype:
> > + prototype: struct task_struct *
> > + argument: string
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d
> > new file mode 100644
> > index 00000000..473e35e4
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The argument to d_execargs() should be (struct task_struct *).
> > + */
> > +
> > +BEGIN
> > +{
> > + trace(d_execargs(curthread->mm));
> > + exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r
> > new file mode 100644
> > index 00000000..842371a3
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.r
> > @@ -0,0 +1,4 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_ARG.wrong_ptr.d: [D_PROTO_ARG] line 14: d_execargs( ) argument #1 is incompatible with prototype:
> > + prototype: struct task_struct *
> > + argument: struct mm_struct *
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d
> > new file mode 100644
> > index 00000000..86b1b237
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: d_execargs() requires an argument
> > + */
> > +
> > +BEGIN
> > +{
> > + trace(d_execargs());
> > + exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r
> > new file mode 100644
> > index 00000000..a4fcd162
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.r
> > @@ -0,0 +1,2 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_LEN.missing_arg.d: [D_PROTO_LEN] line 14: d_execargs( ) prototype mismatch: 0 args passed, 1 expected
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d
> > new file mode 100644
> > index 00000000..3add63f6
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d
> > @@ -0,0 +1,16 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: The d_execargs() subroutine accepts no more than one argument.
> > + */
> > +
> > +BEGIN
> > +{
> > + trace(d_execargs(curthread, 1));
> > + exit(0);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r
> > new file mode 100644
> > index 00000000..f5a982ff
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.r
> > @@ -0,0 +1,2 @@
> > +-- @@stderr --
> > +dtrace: failed to compile script test/unittest/funcs/d_execargs/err.D_PROTO_LEN.too_many_args.d: [D_PROTO_LEN] line 14: d_execargs( ) prototype mismatch: 2 args passed, 1 expected
> > diff --git a/test/unittest/funcs/d_execargs/tst.d_execargs.d b/test/unittest/funcs/d_execargs/tst.d_execargs.d
> > new file mode 100644
> > index 00000000..b8b141aa
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/tst.d_execargs.d
> > @@ -0,0 +1,31 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: d_execargs() provides correct results.
> > + */
> > +
> > +#pragma D option destructive
> > +#pragma D option quiet
> > +
> > +BEGIN
> > +{
> > + mypid = pid;
> > + system("/bin/echo TEST");
> > +}
> > +
> > +proc:::exec-success
> > +/progenyof(mypid) && d_execargs(curthread) == "/bin/echo TEST"/
> > +{
> > + trace(d_execargs(curthread));
> > + exit(0);
> > +}
> > +
> > +tick-1s
> > +{
> > + exit(1);
> > +}
> > diff --git a/test/unittest/funcs/d_execargs/tst.d_execargs.r b/test/unittest/funcs/d_execargs/tst.d_execargs.r
> > new file mode 100644
> > index 00000000..d8ff6689
> > --- /dev/null
> > +++ b/test/unittest/funcs/d_execargs/tst.d_execargs.r
> > @@ -0,0 +1,2 @@
> > +TEST
> > +/bin/echo TEST
> > diff --git a/test/unittest/proc/tst.pr_psargs.d b/test/unittest/proc/tst.pr_psargs.d
> > new file mode 100644
> > index 00000000..902ac1a3
> > --- /dev/null
> > +++ b/test/unittest/proc/tst.pr_psargs.d
> > @@ -0,0 +1,31 @@
> > +/*
> > + * Oracle Linux DTrace.
> > + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> > + * Licensed under the Universal Permissive License v 1.0 as shown at
> > + * http://oss.oracle.com/licenses/upl.
> > + */
> > +
> > +/*
> > + * ASSERTION: psinfo->pr_psargs provides correct results.
> > + */
> > +
> > +#pragma D option destructive
> > +#pragma D option quiet
> > +
> > +BEGIN
> > +{
> > + mypid = pid;
> > + system("/bin/echo TEST");
> > +}
> > +
> > +proc:::exec-success
> > +/progenyof(mypid) && curpsinfo->pr_psargs == "/bin/echo TEST"/
> > +{
> > + trace(curpsinfo->pr_psargs);
> > + exit(0);
> > +}
> > +
> > +tick-1s
> > +{
> > + exit(1);
> > +}
> > diff --git a/test/unittest/proc/tst.pr_psargs.r b/test/unittest/proc/tst.pr_psargs.r
> > new file mode 100644
> > index 00000000..397c8717
> > --- /dev/null
> > +++ b/test/unittest/proc/tst.pr_psargs.r
> > @@ -0,0 +1,9 @@
> > +TEST
> > +
> > + 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
> > + 0: 2f 62 69 6e 2f 65 63 68 6f 20 54 45 53 54 00 00 /bin/echo TEST..
> > + 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > + 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > + 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > + 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> > +
More information about the DTrace-devel
mailing list