[DTrace-devel] [PATCH v2] usdt, stapsdt: fix argument handling for multi-location probes
Eugene Loh
eugene.loh at oracle.com
Wed Feb 4 13:12:26 UTC 2026
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
On 2/4/26 08:10, Kris Van Hees wrote:
> On Wed, Feb 04, 2026 at 01:25:03AM -0500, Eugene Loh wrote:
>> Thanks. The tests pass on all platforms I tried.
>>
>> I did want to check something. The subject line says both usdt and
>> stapsdt. The commit message talks of usdt. The bug report indicts both
>> usdt and stapsdt.
>>
>> So, there is a problem with stapsdt; the patch fixes and tests that. That
>> much is great.
>>
>> However, the new multiloc usdt test seems to pass for me even without the
>> fix. So was there a usdt problem? Is the multiloc usdt test good enough to
>> show it?
> The problem does not occur with regula USDT but there is also nothing that
> actually tests for this, so I added it as a precaution for future regression.
>
>> On 2/3/26 21:06, 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.
>>>
>>> Orabug: 38922360
>>> 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 | 4 ++
>>> test/unittest/usdt/tst.multiloc.sh | 69 +++++++++++++++++++
>>> .../usdt/tst.stapsdt-notes-bug38922360.r | 4 ++
>>> .../usdt/tst.stapsdt-notes-bug38922360.sh | 54 +++++++++++++++
>>> 6 files changed, 140 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..a0bbc7a8
>>> --- /dev/null
>>> +++ b/test/unittest/usdt/tst.multiloc.r
>>> @@ -0,0 +1,4 @@
>>> +main
>>> +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..19d5d6c1
>>> --- /dev/null
>>> +++ b/test/unittest/usdt/tst.multiloc.sh
>>> @@ -0,0 +1,69 @@
>>> +#!/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
>>> +CFLAGS="-std=gnu89 $test_cppflags"
>>> +LDFLAGS="$test_ldflags"
>>> +
>>> +DIRNAME="$tmpdir/usdt-multiloc.$$.$RANDOM"
>>> +mkdir -p $DIRNAME
>>> +cd $DIRNAME
>>> +
>>> +cat > test.c <<EOF
>>> +#include <sys/sdt.h>
>>> +#include <stdio.h>
>>> +
>>> +int
>>> +main(int argc, char **argv)
>>> +{
>>> + printf("%s\n", __func__);
>>> + 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..a0bbc7a8
>>> --- /dev/null
>>> +++ b/test/unittest/usdt/tst.stapsdt-notes-bug38922360.r
>>> @@ -0,0 +1,4 @@
>>> +main
>>> +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..ea0d6880
>>> --- /dev/null
>>> +++ b/test/unittest/usdt/tst.stapsdt-notes-bug38922360.sh
>>> @@ -0,0 +1,54 @@
>>> +#!/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
>>> +CFLAGS="-std=gnu89 -I${PWD}/test/unittest/usdt $test_cppflags"
>>> +LDFLAGS="$test_ldflags"
>>> +
>>> +DIRNAME="$tmpdir/usdt-notes-bug38922360.$$.$RANDOM"
>>> +mkdir -p $DIRNAME
>>> +cd $DIRNAME
>>> +
>>> +cat > test.c <<EOF
>>> +#include <sdt_notes.h>
>>> +#include <stdio.h>
>>> +
>>> +int
>>> +main(int argc, char **argv)
>>> +{
>>> + printf("%s\n", __func__);
>>> + 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