gdb/doc/ChangeLog:
authorSergio Durigan Junior <sergiodj@redhat.com>
Fri, 27 Apr 2012 20:52:06 +0000 (20:52 +0000)
committerSergio Durigan Junior <sergiodj@redhat.com>
Fri, 27 Apr 2012 20:52:06 +0000 (20:52 +0000)
2012-04-27  Sergio Durigan Junior  <sergiodj@redhat.com>
    Tom Tromey  <tromey@redhat.com>

* gdb.texinfo (Static Probe Points): New entry, explaining SystemTap
and generic static probe support on GDB.

gdb/testsuite/ChangeLog:
2012-04-27  Sergio Durigan Junior  <sergiodj@redhat.com>
    Tom Tromey  <tromey@redhat.com>

* gdb.base/default.exp: Add `$_probe_arg*' convenience
variables.
* gdb.base/stap-probe.c: New file.
* gdb.base/stap-probe.exp: New file.
* gdb.trace/stap-trace.c: New file.
* gdb.trace/stap-trace.exp: New file.
* gdb.cp/nextoverthrow.exp: Add check for SystemTap probe in
libgcc's unwinder.

gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/default.exp
gdb/testsuite/gdb.base/stap-probe.c [new file with mode: 0644]
gdb/testsuite/gdb.base/stap-probe.exp [new file with mode: 0644]
gdb/testsuite/gdb.cp/nextoverthrow.exp
gdb/testsuite/gdb.trace/stap-trace.c [new file with mode: 0644]
gdb/testsuite/gdb.trace/stap-trace.exp [new file with mode: 0644]

index c8463834d0abd45513f6ae6b9b5d7efcb35d0e10..6f559260fb71f06f15415b4e63c53f8d2ba7cef5 100644 (file)
@@ -1,3 +1,9 @@
+2012-04-27  Sergio Durigan Junior  <sergiodj@redhat.com>
+           Tom Tromey  <tromey@redhat.com>
+
+       * gdb.texinfo (Static Probe Points): New entry, explaining SystemTap
+       and generic static probe support on GDB.
+
 2012-04-25  Doug Evans  <dje@google.com>
 
        * gdb.texinfo (Go): Fix thinko.
index 6175b0e11cbd62b71a719e48c762f73ae5f7c186..f41118f10830809aced3bbec3b05214de0cc6634 100644 (file)
@@ -3342,6 +3342,7 @@ all breakpoints in that range are operated on.
 * Conditions::                  Break conditions
 * Break Commands::              Breakpoint command lists
 * Save Breakpoints::            How to save breakpoints in a file
+* Static Probe Points::         Listing static probe points
 * Error in Breakpoints::        ``Cannot insert breakpoints''
 * Breakpoint-related Warnings:: ``Breakpoint address adjusted...''
 @end menu
@@ -4652,6 +4653,69 @@ and remove the breakpoint definitions you're not interested in, or
 that can no longer be recreated.
 @end table
 
+@node Static Probe Points
+@subsection Static Probe Points
+
+@cindex static probe point, SystemTap
+@value{GDBN} supports @dfn{SDT} probes in the code.  @acronym{SDT} stands
+for Statically Defined Tracing, and the probes are designed to have a tiny
+runtime code and data footprint, and no dynamic relocations.  They are
+usable from assembly, C and C@t{++} languages.  See
+@uref{http://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation}
+for a good reference on how the @acronym{SDT} probes are implemented.
+
+Currently, @code{SystemTap} (@uref{http://sourceware.org/systemtap/})
+@acronym{SDT} probes are supported on ELF-compatible systems.  See
+@uref{http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps}
+for more information on how to add @code{SystemTap} @acronym{SDT} probes
+in your applications.
+
+@cindex semaphores on static probe points
+Some probes have an associated semaphore variable; for instance, this
+happens automatically if you defined your probe using a DTrace-style
+@file{.d} file.  If your probe has a semaphore, @value{GDBN} will
+automatically enable it when you specify a breakpoint using the
+@samp{-probe-stap} notation.  But, if you put a breakpoint at a probe's
+location by some other method (e.g., @code{break file:line}), then
+@value{GDBN} will not automatically set the semaphore.
+
+You can examine the available static static probes using @code{info
+probes}, with optional arguments:
+
+@table @code
+@kindex info probes
+@item info probes stap @r{[}@var{provider} @r{[}@var{name} @r{[}@var{objfile}@r{]}@r{]}@r{]}
+If given, @var{provider} is a regular expression used to match against provider
+names when selecting which probes to list.  If omitted, probes by all
+probes from all providers are listed.
+
+If given, @var{name} is a regular expression to match against probe names
+when selecting which probes to list.  If omitted, probe names are not
+considered when deciding whether to display them.
+
+If given, @var{objfile} is a regular expression used to select which
+object files (executable or shared libraries) to examine.  If not
+given, all object files are considered.
+
+@item info probes all
+List the available static probes, from all types.
+@end table
+
+@vindex $_probe_arg@r{, convenience variable}
+A probe may specify up to twelve arguments.  These are available at the
+point at which the probe is defined---that is, when the current PC is
+at the probe's location.  The arguments are available using the
+convenience variables (@pxref{Convenience Vars})
+@code{$_probe_arg0}@dots{}@code{$_probe_arg11}.  Each probe argument is
+an integer of the appropriate size; types are not preserved.  The
+convenience variable @code{$_probe_argc} holds the number of arguments
+at the current probe point.
+
+These variables are always available, but attempts to access them at
+any location other than a probe point will cause @value{GDBN} to give
+an error message.
+
+
 @c  @ifclear BARETARGET
 @node Error in Breakpoints
 @subsection ``Cannot insert breakpoints''
@@ -6667,6 +6731,19 @@ specify the function unambiguously, e.g., if there are several
 functions with identical names in different source files.
 @end table
 
+@cindex breakpoint at static probe point
+@item -pstap|-probe-stap @r{[}@var{objfile}:@r{[}@var{provider}:@r{]}@r{]}@var{name}
+The @sc{gnu}/Linux tool @code{SystemTap} provides a way for
+applications to embed static probes.  @xref{Static Probe Points}, for more
+information on finding and using static probes.  This form of linespec
+specifies the location of such a static probe.
+
+If @var{objfile} is given, only probes coming from that shared library
+or executable matching @var{objfile} as a regular expression are considered.
+If @var{provider} is given, then only probes from that provider are considered.
+If several probes match the spec, @value{GDBN} will insert a breakpoint at
+each one of those probes.
+
 @end table
 
 
@@ -9071,6 +9148,10 @@ to match the format in which the data was printed.
 The variable @code{$_exitcode} is automatically set to the exit code when
 the program being debugged terminates.
 
+@item $_probe_argc
+@itemx $_probe_arg0@dots{}$_probe_arg11
+Arguments to a static probe.  @xref{Static Probe Points}.
+
 @item $_sdata
 @vindex $_sdata@r{, inspect, convenience variable}
 The variable @code{$_sdata} contains extra collected static tracepoint
@@ -11015,6 +11096,16 @@ Collect all local variables.
 Collect the return address.  This is helpful if you want to see more
 of a backtrace.
 
+@item $_probe_argc
+Collects the number of arguments from the static probe at which the
+tracepoint is located.
+@xref{Static Probe Points}.
+
+@item $_probe_arg@var{n}
+@var{n} is an integer between 0 and 11.  Collects the @var{n}th argument
+from the static probe at which the tracepoint is located.
+@xref{Static Probe Points}.
+
 @item $_sdata
 @vindex $_sdata@r{, collect}
 Collect static tracepoint marker specific data.  Only available for
index ba84133cd3e5acd3e8f93e981ea7c446936f5633..ba9d3391bc038ce8e8c991a13c4da5fc59399ada 100644 (file)
@@ -1,3 +1,15 @@
+2012-04-27  Sergio Durigan Junior  <sergiodj@redhat.com>
+           Tom Tromey  <tromey@redhat.com>
+
+       * gdb.base/default.exp: Add `$_probe_arg*' convenience
+       variables.
+       * gdb.base/stap-probe.c: New file.
+       * gdb.base/stap-probe.exp: New file.
+       * gdb.trace/stap-trace.c: New file.
+       * gdb.trace/stap-trace.exp: New file.
+       * gdb.cp/nextoverthrow.exp: Add check for SystemTap probe in
+       libgcc's unwinder.
+
 2012-04-26  Maciej W. Rozycki  <macro@codesourcery.com>
 
        * gdb.arch/mips16-thunks-inmain.c: New file.
index e2859d516b0c574ad8319e70214c9cbe8f543bec..73fbe98fb4940d7d96ccba58e48610a86dc068bc 100644 (file)
@@ -604,6 +604,19 @@ gdb_test_list_exact "show convenience" "show convenience" \
        {$_sdata = void} \
        {$_siginfo = void} \
        {$_thread = 0} \
+       {$_probe_argc = <error: No frame selected>} \
+       {$_probe_arg0 = <error: No frame selected>} \
+       {$_probe_arg1 = <error: No frame selected>} \
+       {$_probe_arg2 = <error: No frame selected>} \
+       {$_probe_arg3 = <error: No frame selected>} \
+       {$_probe_arg4 = <error: No frame selected>} \
+       {$_probe_arg5 = <error: No frame selected>} \
+       {$_probe_arg6 = <error: No frame selected>} \
+       {$_probe_arg7 = <error: No frame selected>} \
+       {$_probe_arg8 = <error: No frame selected>} \
+       {$_probe_arg9 = <error: No frame selected>} \
+       {$_probe_arg10 = <error: No frame selected>} \
+       {$_probe_arg11 = <error: No frame selected>} \
     }
 
 #test show directories
diff --git a/gdb/testsuite/gdb.base/stap-probe.c b/gdb/testsuite/gdb.base/stap-probe.c
new file mode 100644 (file)
index 0000000..1c7b05f
--- /dev/null
@@ -0,0 +1,108 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if USE_PROBES
+
+#define _SDT_HAS_SEMAPHORES
+__extension__ unsigned short test_user_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+#define TEST test_user_semaphore
+
+__extension__ unsigned short test_two_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+#define TEST2 test_two_semaphore
+
+__extension__ unsigned short test_m4_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+
+__extension__ unsigned short test_pstr_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+
+__extension__ unsigned short test_ps_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+#else
+
+#define TEST 1
+#define TEST2 1
+
+#endif
+
+#include <sys/sdt.h>
+
+/* We only support SystemTap and only the v3 form.  */
+#if _SDT_NOTE_TYPE != 3
+#error "not using SystemTap v3 probes"
+#endif
+
+struct funcs
+{
+  int val;
+
+  const char *(*ps) (int);
+};
+
+static void
+m1 (void)
+{
+  if (TEST2)
+    STAP_PROBE (test, two);
+}
+
+static void
+m2 (void)
+{
+  if (TEST2)
+    STAP_PROBE (test, two);
+}
+
+static int
+f (int x)
+{
+  if (TEST)
+    STAP_PROBE1 (test, user, x);
+  return x+5;
+}
+
+static const char *
+pstr (int val)
+{
+  const char *a = "This is a test message.";
+  const char *b = "This is another test message.";
+
+  STAP_PROBE3 (test, ps, a, b, val);
+
+  return val == 0 ? a : b;
+}
+
+static void
+m4 (const struct funcs *fs, int v)
+{
+  STAP_PROBE3 (test, m4, fs->val, fs->ps (v), v);
+}
+
+int
+main()
+{
+  struct funcs fs;
+
+  fs.val = 42;
+  fs.ps = pstr;
+
+  f (f (23));
+  m1 ();
+  m2 ();
+
+  m4 (&fs, 0);
+  m4 (&fs, 1);
+
+  return 0; /* last break here */
+}
diff --git a/gdb/testsuite/gdb.base/stap-probe.exp b/gdb/testsuite/gdb.base/stap-probe.exp
new file mode 100644 (file)
index 0000000..30ca427
--- /dev/null
@@ -0,0 +1,183 @@
+# Copyright (C) 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+set testfile stap-probe
+
+# Run the tests.  We run the tests two different ways: once with a
+# plain probe, and once with a probe that has an associated semaphore.
+# This returns -1 on failure to compile or start, 0 otherwise.
+proc stap_test {exec_name {arg ""}} {
+    global testfile hex
+
+    if {[prepare_for_testing ${testfile}.exp ${exec_name} ${testfile}.c \
+          [concat $arg debug]]} {
+       return -1
+    }
+
+    if ![runto_main] {
+       return -1
+    }
+
+    gdb_test "print \$_probe_argc" "No SystemTap probe at PC $hex" \
+       "check argument not at probe point"
+
+    gdb_test "info probes stap" \
+       "test *user *$hex .*" \
+       "info probes stap"
+    
+    if {[runto "-pstap test:user"]} {
+       pass "run to -pstap test:user"
+    } else {
+       fail "run to -pstap test:user"
+    }
+
+    # Test probe arguments.
+    gdb_test "print \$_probe_argc" " = 1" \
+    "print \$_probe_argc for probe user"
+    gdb_test "print \$_probe_arg0 == x" " = 1" \
+    "check \$_probe_arg0 for probe user"
+    gdb_test "print \$_probe_arg1" \
+       "Invalid probe argument 1 -- probe has 1 arguments available" \
+       "check \$_probe_arg1 for probe user"
+
+    # Set a breakpoint with multiple probe locations.
+    gdb_test "break -pstap test:two" \
+       "Breakpoint \[0-9\]+ at $hex.*2 locations.*" \
+       "set multi-location probe breakpoint (probe two)"
+
+    # Reinit GDB, set a breakpoint on probe m4.
+    delete_breakpoints
+    rerun_to_main
+    if {[runto "-pstap test:m4"]} {
+      pass "run to -pstap test:m4"
+    } else {
+      fail "run to -pstap test:m4"
+    }
+
+    # Testing probe arguments.
+    gdb_test "print \$_probe_argc" " = 3" \
+    "print \$_probe_argc for probe m4"
+    gdb_test "print \$_probe_arg0" " = 42" \
+    "check \$_probe_arg0 for probe m4"
+    gdb_test "print (const char *) \$_probe_arg1" \
+    " = $hex .This is a test message.*" \
+    "check \$_probe_arg1 for probe m4"
+    gdb_test "print \$_probe_arg2 == v" " = 1" \
+    "check \$_probe_arg2 for probe m4"
+
+    # Reinit GDB, set a breakpoint on probe ps.
+    delete_breakpoints
+    rerun_to_main
+    if {[runto "-pstap test:ps"]} {
+      pass "run to -pstap test:m4"
+    } else {
+      fail "run to -pstap test:m4"
+    }
+
+    gdb_test "print \$_probe_argc" " = 3" \
+    "print \$_probe_argc for probe ps"
+    gdb_test "print (const char *) \$_probe_arg1" \
+    " = $hex .This is another test message.*" \
+    "print \$_probe_arg1 for probe ps"
+
+    return 0
+}
+
+proc stap_test_no_debuginfo {exec_name {arg ""}} {
+    global testfile hex
+
+    if {[prepare_for_testing ${testfile}.exp ${exec_name} ${testfile}.c \
+          {$arg nodebug optimize=-O2}]} {
+       return -1
+    }
+
+    if {[runto "-pstap test:user"]} {
+       pass "run to -pstap test:user"
+    } else {
+       fail "run to -pstap test:user"
+    }
+
+    # Test probe arguments.
+    gdb_test "print \$_probe_argc" " = 1" \
+    "print \$_probe_argc for probe user"
+    gdb_test "print \$_probe_arg0 == 23" " = 1" \
+    "check \$_probe_arg0 for probe user"
+    gdb_test "print \$_probe_arg1" \
+       "Invalid probe argument 1 -- probe has 1 arguments available" \
+       "check \$_probe_arg1 for probe user"
+
+    # Set a breakpoint with multiple probe locations.
+    # In this scenario, we may expect more than 2 locations because of
+    # the optimizations (inlining, loop unrolling, etc).
+    gdb_test "break -pstap test:two" \
+       "Breakpoint .* at $hex.*\[0-9\]+ locations.*" \
+       "set multi-location probe breakpoint (probe two)"
+
+    # Reinit GDB, set a breakpoint on probe m4.
+    delete_breakpoints
+    rerun_to_main
+    if {[runto "-pstap test:m4"]} {
+      pass "run to -pstap test:m4"
+    } else {
+      fail "run to -pstap test:m4"
+    }
+
+    # Testing probe arguments.
+    gdb_test "print \$_probe_argc" " = 3" \
+    "print \$_probe_argc for probe m4"
+    gdb_test "print \$_probe_arg0" " = 42" \
+    "check \$_probe_arg0 for probe m4"
+    gdb_test "print (const char *) \$_probe_arg1" \
+    " = $hex .This is a test message.*" \
+    "check \$_probe_arg1 for probe m4"
+    gdb_test "print \$_probe_arg2 == 0" " = 1" \
+    "check \$_probe_arg2 for probe m4"
+
+    # Reinit GDB, set a breakpoint on probe ps.
+    delete_breakpoints
+    rerun_to_main
+    if {[runto "-pstap test:ps"]} {
+      pass "run to -pstap test:m4"
+    } else {
+      fail "run to -pstap test:m4"
+    }
+
+    gdb_test "print \$_probe_argc" " = 3" \
+    "print \$_probe_argc for probe ps"
+    gdb_test "print (const char *) \$_probe_arg1" \
+    " = $hex .This is another test message.*" \
+    "print \$_probe_arg1 for probe ps"
+
+    return 0
+}
+
+with_test_prefix "without semaphore, not optimized" {
+    if {[stap_test "stap-probe-nosem-noopt"] == -1} {
+       untested stap-probe.exp
+         return -1
+    }
+}
+
+with_test_prefix "with semaphore, not optimized" {
+    stap_test "stap-probe-sem-noopt" "-DUSE_PROBES"
+}
+
+with_test_prefix "without semaphore, optimized" {
+    stap_test_no_debuginfo "stap-probe-nosem-opt"
+}
+
+with_test_prefix "with semaphore, optimized" {
+    stap_test_no_debuginfo "stap-probe-sem-opt" "-DUSE_PROBES"
+}
index 7d4a0c57178f903261b10c2acfb3ef898e349529..2dafcab90e0c7b9bb7cb0149454d268ae5963719 100644 (file)
@@ -53,6 +53,17 @@ gdb_test_multiple "print _Unwind_DebugHook" "check for unwinder hook" {
        set ok 0
     }
 }
+if {!$ok} {
+    gdb_test_multiple "info probe" "check for stap probe in unwinder" {
+       -re ".*libgcc.*unwind.*\r\n$gdb_prompt $" {
+           pass "check for stap probe in unwinder"
+           set ok 1
+       }
+       -re "\r\n$gdb_prompt $" {
+       }
+    }
+}
+
 if {!$ok} {
     unsupported "nextoverthrow.exp could not find _Unwind_DebugHook"
     return -1
diff --git a/gdb/testsuite/gdb.trace/stap-trace.c b/gdb/testsuite/gdb.trace/stap-trace.c
new file mode 100644 (file)
index 0000000..7c638db
--- /dev/null
@@ -0,0 +1,71 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if USE_PROBES
+
+#define _SDT_HAS_SEMAPHORES
+__extension__ unsigned short test_user_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+#define TEST test_user_semaphore
+
+__extension__ unsigned short test_two_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes")));
+#define TEST2 test_two_semaphore
+
+#else
+
+#define TEST 1
+#define TEST2 1
+
+#endif /* USE_PROBES */
+
+#include <sys/sdt.h>
+
+/* We only support SystemTap and only the v3 form.  */
+#if _SDT_NOTE_TYPE != 3
+#error "not using SystemTap v3 probes"
+#endif
+
+void
+m1 (int x)
+{
+  if (TEST2)
+    STAP_PROBE1 (test, two, x);
+}
+
+int
+f (int x)
+{
+  if (TEST)
+    STAP_PROBE1(test, user, x);
+  return x+5;
+}
+
+void
+nothing (void)
+{
+  int a = 1 + 1;
+  return;
+}
+
+int
+main()
+{
+  f (f (23));
+  m1 (46);
+  nothing (); /* end-here */
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.trace/stap-trace.exp b/gdb/testsuite/gdb.trace/stap-trace.exp
new file mode 100644 (file)
index 0000000..562eec4
--- /dev/null
@@ -0,0 +1,128 @@
+# Copyright 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "trace-support.exp"
+
+set testfile "stap-trace"
+set srcfile ${testfile}.c
+set executable ""
+set binfile_dir $objdir/$subdir
+
+set ws "\[\r\n\t \]+"
+set cr "\[\r\n\]+"
+
+# Only x86 and x86_64 targets are supported for now.
+
+if { ![istarget "x86_64-*"] && ![istarget "i?86-*"] } {
+    continue
+}
+
+proc compile_stap_bin {exec_name {arg ""}} {
+    global srcfile
+    global binfile_dir
+    global srcdir
+    global subdir
+    global executable
+
+    if { $arg != "" } {
+       set arg "additional_flags=$arg"
+    }
+
+    set executable ${exec_name}
+
+    if { [gdb_compile "$srcdir/$subdir/$srcfile" \
+           "$binfile_dir/$exec_name" \
+           executable [concat $arg debug nowarnings]] != "" } {
+       untested "Could not compile ${srcfile}"
+       return -1
+    }
+}
+
+proc prepare_for_trace_test {} {
+    global executable
+
+    clean_restart $executable
+
+    if { ![runto_main] } {
+       perror "Could not run to `main'."
+       continue
+    }
+
+    gdb_breakpoint [gdb_get_line_number "end-here"]
+}
+
+proc run_trace_experiment { test_probe msg } {
+    global gdb_prompt
+
+    set test "collect $msg: start trace experiment"
+    gdb_test_multiple "tstart" "$test" {
+       -re "^tstart\r\n$gdb_prompt $" {
+           pass "$test"
+       }
+    }
+
+    gdb_test "continue" \
+           "Continuing.*Breakpoint \[0-9\]+.*" \
+           "collect $msg: run trace experiment"
+    gdb_test "tstop" \
+           "\[\r\n\]+" \
+           "collect $msg: stop trace experiment"
+    gdb_test "tfind start" \
+           "#0 .*" \
+           "collect $msg: tfind test frame"
+}
+
+proc gdb_collect_probe_arg { msg probe val_arg0 } {
+    global gdb_prompt
+    global cr
+
+    prepare_for_trace_test
+
+    gdb_test "trace $probe" \
+           "Tracepoint \[0-9\]+ at .*" \
+           "collect $msg: set tracepoint"
+    gdb_trace_setactions "collect $msg: define actions" \
+           "" \
+           "collect \$_probe_arg0" "^$"
+
+    # Begin the test.
+    run_trace_experiment $msg $probe
+
+    gdb_test "print \$_probe_arg0" \
+           "\\$\[0-9\]+ = $val_arg0$cr" \
+           "collect $msg: collected probe arg0"
+}
+
+compile_stap_bin "stap-probe-nosem"
+
+clean_restart $executable
+if { ![runto_main] } {
+    perror "Could not run to `main'."
+    continue
+}
+
+if { ![gdb_target_supports_trace] } {
+    # Test cannot run on this target.
+    return 1;
+}
+
+gdb_collect_probe_arg "probe args without semaphore" "-probe-stap user" "23"
+gdb_exit
+
+compile_stap_bin "stap-probe-sem" "-DUSE_PROBES"
+gdb_collect_probe_arg "probe args with semaphore" "-probe-stap two" "46"
+
+# Finished!
+gdb_test "tfind none" ".*" ""