[DTrace-devel] [PATCH] usdt, stapsdt: fix arguument handling for multi-location probes

Eugene Loh eugene.loh at oracle.com
Tue Feb 3 23:53:57 UTC 2026


s/arguument/argument/ in subject line.

The commit message should include "Orabug:".

Since this is right up against a release, should this patch update the 
changelog and NEWS?  Or, a separate patch?

The tests define CC, but I thought we were getting away from that with 
commit aa63660a7cfc ("test: allow overriding CC, OBJCOPY, OBJDUMP, NM, 
...").  And, yes, there has been some slippage in that department.

Typically, CFLAGS picks up $test_cppflags.  I didn't bother to check if 
we want that here.

Not a big deal, but test/unittest/usdt/tst.multiloc.sh has an 
unnecessary blank line in the D script.

I quickly tried the test on one system (fwiw OL9 5.15 x86).  I didn't 
bother to investigate, but I got:

test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh: Running timeout 
--signal=TERM 41 test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh 
/home/euloh/z20240321-systemwide-usdt/zdir-src20240611/dtrace-user/build/dtrace
FAIL: expected results differ.

-- @@stderr --
dtrace: error in dt_clause_0 for probe ID 5067 
(test_prov2322957:test:main:args): invalid address (0x402010) at BPF pc 252
dtrace: error in dt_clause_0 for probe ID 5067 
(test_prov2322957:test:main:args): invalid address (0x402010) at BPF pc 252
Diff against expected:
--- test/unittest/usdt/tst.stapsdt-notes-bug38922360.r  2026-02-03 
15:07:41.656410179 -0800
+++ /tmp/runtest.18439/test.out 2026-02-03 15:41:13.250649966 -0800
@@ -1,3 +1,4 @@
-test:main:args main
-test:main:args main

+-- @@stderr --
+dtrace: error in dt_clause_0 for probe ID 5067 
(test_prov2322957:test:main:args): invalid address ({ptr}) at BPF pc NNN
+dtrace: error in dt_clause_0 for probe ID 5067 
(test_prov2322957:test:main:args): invalid address ({ptr}) at BPF pc NNN

On 2/3/26 17:31, Kris Van Hees wrote:
> When a USDT probe has multiple call sites in the same function, only one
> of the probe programs retrieves the argument values correctly.  The
> probe argument data is collected for the first underlying probe, and then
> skipped for any subsequent underlying probes.
>
> Since it is not guaranteed that the argument description is identical for
> all underlying probes (although it is almost always that way), we need to
> process the argument description string for each underlying probe.
>
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> ---
>   libdtrace/dt_pid.c                            |  9 ++-
>   libdtrace/dt_prov_uprobe.c                    | 10 +--
>   test/unittest/usdt/tst.multiloc.r             |  3 +
>   test/unittest/usdt/tst.multiloc.sh            | 67 +++++++++++++++++++
>   .../usdt/tst.stapsdt-notes-bug38922360.r      |  3 +
>   .../usdt/tst.stapsdt-notes-bug38922360.sh     | 52 ++++++++++++++
>   6 files changed, 134 insertions(+), 10 deletions(-)
>   create mode 100644 test/unittest/usdt/tst.multiloc.r
>   create mode 100755 test/unittest/usdt/tst.multiloc.sh
>   create mode 100644 test/unittest/usdt/tst.stapsdt-notes-bug38922360.r
>   create mode 100755 test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh
>
> diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
> index 6f93123f..a379a0fe 100644
> --- a/libdtrace/dt_pid.c
> +++ b/libdtrace/dt_pid.c
> @@ -1350,9 +1350,16 @@ dt_stapsdt_parse(dtrace_hdl_t *dtp, dt_proc_t *dpr, dtrace_probedesc_t *pdp,
>   		if (strcmp(pdp->prb, "*") != 0 &&
>   		    (strlen(pdp->prb) > 0 && strcmp(pdp->prb, prbname) != 0))
>   			continue;
> -		if (prb + strlen(prb) + 1 < dbuf + doff + nhdr.n_descsz)
> +		if (prb + strlen(prb) + 1 < dbuf + doff + nhdr.n_descsz) {
> +			char	*p;
> +
>   			psp.pps_sargv = prb + strlen(prb) + 1;
>   
> +			for (p = psp.pps_sargv; (p = strchr(p, '@')) != NULL;
> +			     p++)
> +				psp.pps_nargc++;
> +		}
> +
>   		psp.pps_type = DTPPT_STAPSDT;
>   		psp.pps_prv = prvname;
>   		psp.pps_mod = mod;
> diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
> index 6d1c0f65..e575b072 100644
> --- a/libdtrace/dt_prov_uprobe.c
> +++ b/libdtrace/dt_prov_uprobe.c
> @@ -1659,15 +1659,7 @@ static int probe_info_stap(dtrace_hdl_t *dtp, const dt_probe_t *prp,
>   	if (!upp || upp->sargv == NULL)
>   		goto done;
>   
> -	/* First count the arguments. */
> -	for (p = upp->sargv; p != NULL; argc++) {
> -		p = strchr(p, '@');
> -		if (p++ == NULL)
> -			break;
> -	}
> -
> -	/* Record number of arguments, and allocate descriptors. */
> -	upp->sargc = argc;
> +	argc = upp->sargc;
>   	if (argc == 0)
>   		goto done;
>   
> diff --git a/test/unittest/usdt/tst.multiloc.r b/test/unittest/usdt/tst.multiloc.r
> new file mode 100644
> index 00000000..06b0c94d
> --- /dev/null
> +++ b/test/unittest/usdt/tst.multiloc.r
> @@ -0,0 +1,3 @@
> +test:main:args main
> +test:main:args main
> +
> diff --git a/test/unittest/usdt/tst.multiloc.sh b/test/unittest/usdt/tst.multiloc.sh
> new file mode 100755
> index 00000000..aa8ea2e5
> --- /dev/null
> +++ b/test/unittest/usdt/tst.multiloc.sh
> @@ -0,0 +1,67 @@
> +#!/bin/bash
> +#
> +# Oracle Linux DTrace.
> +# Copyright (c) 2026, 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.
> +
> +# This test covers USDT probes firing from multiple locations in the same
> +# function, verifying that argument data is correct.
> +
> +if [ $# != 1 ]; then
> +	echo expected one argument: '<'dtrace-path'>'
> +	exit 2
> +fi
> +
> +dtrace=$1
> +CC=/usr/bin/gcc
> +CFLAGS="-I${PWD}/test/unittest/usdt"
> +
> +DIRNAME="$tmpdir/usdt-multiloc.$$.$RANDOM"
> +mkdir -p $DIRNAME
> +cd $DIRNAME
> +
> +cat > test.c <<EOF
> +#include <sys/sdt.h>
> +
> +int
> +main(int argc, char **argv)
> +{
> +	DTRACE_PROBE1(test_prov, args, __func__);
> +	DTRACE_PROBE1(test_prov, args, __func__);
> +}
> +EOF
> +
> +cat > prov.d <<EOF
> +provider test_prov {
> +	probe args(char *);
> +};
> +EOF
> +
> +${CC} ${CFLAGS} -c test.c
> +if [ $? -ne 0 ]; then
> +	echo "failed to compile test.c" >& 2
> +	exit 1
> +fi
> +$dtrace $dt_flags -G -s prov.d test.o
> +if [ $? -ne 0 ]; then
> +	echo "failed to create DOF" >& 2
> +	exit 1
> +fi
> +${CC} ${LDFLAGS} -o test test.o prov.o
> +if [ $? -ne 0 ]; then
> +	echo "failed to link final executable" >& 2
> +	exit 1
> +fi
> +
> +$dtrace $dt_flags -c './test arg1val' -qs /dev/stdin <<EOF
> +test_prov\$target:::args
> +{
> +	printf("%s:%s:%s %s\n", probemod, probefunc, probename,
> +	       copyinstr(arg0));
> +}
> +
> +EOF
> +status=$?
> +
> +exit $status
> diff --git a/test/unittest/usdt/tst.stapsdt-notes-bug38922360.r b/test/unittest/usdt/tst.stapsdt-notes-bug38922360.r
> new file mode 100644
> index 00000000..06b0c94d
> --- /dev/null
> +++ b/test/unittest/usdt/tst.stapsdt-notes-bug38922360.r
> @@ -0,0 +1,3 @@
> +test:main:args main
> +test:main:args main
> +
> diff --git a/test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh b/test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh
> new file mode 100755
> index 00000000..4678a415
> --- /dev/null
> +++ b/test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh
> @@ -0,0 +1,52 @@
> +#!/bin/bash
> +#
> +# Oracle Linux DTrace.
> +# Copyright (c) 2026, 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.
> +
> +# This test covers stapsdt probes fired by the STAP_PROBEn macros, verifying
> +# that argument data is processed correctly when the same probe is used in
> +# multiple locations.
> +
> +if [ $# != 1 ]; then
> +	echo expected one argument: '<'dtrace-path'>'
> +	exit 2
> +fi
> +
> +dtrace=$1
> +CC=/usr/bin/gcc
> +CFLAGS="-I${PWD}/test/unittest/usdt"
> +
> +DIRNAME="$tmpdir/usdt-notes-bug38922360.$$.$RANDOM"
> +mkdir -p $DIRNAME
> +cd $DIRNAME
> +
> +cat > test.c <<EOF
> +#include <sdt_notes.h>
> +
> +int
> +main(int argc, char **argv)
> +{
> +	STAP_PROBE1(test_prov, args, __func__);
> +	STAP_PROBE1(test_prov, args, __func__);
> +}
> +EOF
> +
> +${CC} ${CFLAGS} -o test test.c
> +if [ $? -ne 0 ]; then
> +	echo "failed to compile test.c" >& 2
> +	exit 1
> +fi
> +
> +$dtrace -c './test arg1val' -qs /dev/stdin <<EOF
> +test_prov\$target:::args
> +{
> +	printf("%s:%s:%s %s\n", probemod, probefunc, probename,
> +	       copyinstr(arg0));
> +}
> +
> +EOF
> +status=$?
> +
> +exit $status



More information about the DTrace-devel mailing list