This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Static tracepoints support


On Saturday 26 June 2010 11:35:57, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > Date: Fri, 25 Jun 2010 19:31:56 +0100
> > 
> > This patch adds static tracepoints support to GDB, and adds GDBserver
> > support for LTTng/UST based static tracepoints <http://lttng.org/ust>.
> > We worked activelly with the LTTng/UST maintainers to design
> > and implement this integration.
> 
> Thanks.  However, does it mean we will only support LTTng/UST on
> remote targets, not natively?  

Yes.  The whole tracepoint support in GDB only works on remote targets
presently.

> If so, what would it take to add native
> support as well?

You'd need to make the general tracing infrastruture work 
work on native targets first somehow.

> 
> > (NEWS and manual changes included.  Are those okay?)
> 
> See below.
> 
> > (gdb) info static-tracepoint-markers 
> > Enb Address            What
> > n   0x00007ffff7996692 
> >      String ID: metadata/core_marker_format
> >      Extra: channel %s name %s format %s
> 
> I'd suggest to have Address before Enb.

Any particular reason?  This is the same order of "info breakpoints" output.
It leaves Address and What alongside, wich IMO is better as they're ralated.


> The "String" part in "String ID" sounds redundant; why not just "ID"?.

Works for me.


> I cannot say I like the "Extra" thing.  How about "Data" or "Format"
> instead?

It's really a generic extra field.  In UST, gdbserver shoves the format
there, though for other engines, with could be anything else.  I went
with "Data".

> Also, what will be the actual layout of "String ID" and "Extra" lines?
> What I see in your mail breaks the table structure too much.  Did your
> mailer fold the long lines here?  If so, could you show what it will
> look like on the screen in GDB?  If this is the actual layout, can we
> do better in terms of readability?

That's the actual layout.  I couldn't think of how to make it better.
The issue is that to have a pretty table, you need fixed size columns.  The
"What" column width can vary easily between short and very long, hence
it is put last, just like in the "info breakpoints" output.  In general
it is a good idea to put such variable width field as last column.  The problem,
is that the "String ID" and the "Extra" fields can both also be very long
as well, so we can't really have them in proper columns, unless you cut
the string lengths to some artificial limit, which is undesirable.  I
did try having all the fields as columns early on.  It looked much
worse to me.

> 
> > The "What" column is similar to the "info breakpoints" output, and
> > shows the source location of the marker, if possible.
> 
> Why wouldn't it be possible?  Why some of the entries above don't have
> this data?

If you have no debug info for the locations, the "What" field is empty,
just like with "info breakpoints":

(gdb) b *0x11223344
Breakpoint 3 at 0x11223344
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x0000000011223344

> 
> > (gdb) info breakpoints 
> > Num     Type           Disp Enb Address            What
> > 1       breakpoint     keep y   0x0000000000400c30 in main at stexample.c:13
> > 2       static tracepoint keep y   0x0000000000400ddc in main at stexample.c:20
> >         static tracepoint id is ust/bar33
> >         collect $registers
> >         collect $_sdata
> 
> Suggest to use "stracepoint" instead of "static tracepoint", because
> the latter makes the table appear misaligned.  

We have other cases like that:

(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400c30 in main at stexample.c:15
        breakpoint already hit 1 time
2       hw watchpoint  keep y                      glob
3       read watchpoint keep y                      glob
4       fast tracepoint keep y   0x0000000000400ddc in main at stexample.c:18
5       static tracepoint keep y   0x0000000000400ddc in main at stexample.c:22
        static tracepoint id is ust/bar33

I like seeing the static spelled out, like read and fast.  Maybe we could
instead dynamically adjust the column width to the largest type string, similarly
to how we do for the "Address" column.  I'll leave that for a follow up.

> Correspondingly, "info
> stracepoint-markers" instead of "info static-tracepoint-markers".

I can make that an alias if you'd like.  I tend to just use <tab>, and
so I don't see a problem here.

> > +  if (!in_process_agent_loaded ())
> > +    {
> > +      warning ("In-process agent not loaded");
> > +      return 0;
> 
> There are many calls to `warning' in the patch where the message
> string is not in _().

Most of those are in files in gdb/gdbserver/ -- gdbserver doesn't do
i18n/gettext.  A couple did make it into gdb without _().  Thanks,
fixed those.

> 
> > +#define SOCK_DIR "/tmp"
> 
> This is unnecessarily platform-specific.  How about using P_tmpdir
> instead?

Agreed.  Fixed.

> 
> > +/* When symbols change, it probably means the sources changed as well,
> > +   and it might mean the static tracepoint markers are no longer at
> > +   the same address or line numbers they used to be at last we
> > +   checked.  Losing your static tracepoints whenever you rebuild is
> > +   undesirable.  This function tries to resync/rematch gdb static
> > +   tracepoints with the markers on the target.  The heuristic is:
> > +
> > +   1) look for a marker at the old PC.  If one is found there, assume
> > +   to be the same marker.  If the name / string id of the marker found
> > +   is different from the previous known name, assume that means the
> > +   user renamed the marker in the sources, and output a warning.
> > +
> > +   2) If a marker is no longer found at the same address, it may mean
> > +   the marker no longer exists.  But it may also just mean the code
> > +   changed a bit.  Maybe the user added a few lines of code that made
> > +   the marker move up or down (in line number terms).  Ask the target
> > +   for info about the marker with the string id as we knew it.  If
> > +   found, update line number and address in the matching static
> > +   tracepoint.  */
> 
> I would suggest to reverse the order of the steps: first to query the
> target about the marker with the old string ID, and only if it is not
> found, use the heuristics in step 1.  The rationale is that if the
> target can provide the info, it is always more reliable than any
> heuristics.
> 
> > +      init_sal (&sal);		/* initialize to zeroes */
>                                                          ^^^^^^
> "zeros"

Hmm, this is just a copy/paste.  We have that string attached to a lot
of instances of init_sal.  The online dictionaries I checked claim both
spellings are correct in American English.  I'll just remove the
string; this comment really adds no value (in all instances).

> 
> > +If a line number is specified, probe the marker at start of code \n\
> > +for that line. If a function is specified, probe the marker at start \n\
> 
> The blank before "\n\" is redundant (here and elsewhere), its only
> effect is to bloat the image of GDB.

:-) Fixed the new instances.

> Also, please use two spaces between sentences consistently.

Done.

> 
> > +with that name. With no LOCATION, uses current execution address of \n\
> > +selected stack frame.\n\
> 
> "of the selected stack frame"

Fixed.  Needs fixing in BREAK_ARGS_HELP; it's showing up in the help
strings of all breakpoint commands.

> 
> > +Static tracepoints accept an extra collect action --- ``collect $_sdata''.\n\
> 
> No need for 3 dashes in a row: this isn't Texinfo.  2 dashes will do.
> 
> > +tracing library.  You can inspect it when analysing the trace buffer, \n\
>                                              ^^^^^^^^^
> "analyzing" (US spelling).

Thanks.

> 
> > +Multiple tracepoints at one place are permitted, and useful if conditional.\n
> 
> This sentence is incomplete, you probably meant "if their conditionals
> are different" or some such.

Note that this whole help string was mostly copied from BREAK_ARGS_HELP and
adjusted for static tracepoints.  There, it reads:

 Multiple breakpoints at one place are permitted, and useful if conditional.

I don't think it is incomplete; it sounds correct to me.  A breakpoint can
be conditional or unconditional, so I read that as: it's useful to have more
than one breakpoint at the same place when they are conditional breakpoints.

> 
> > @@ -4223,6 +4488,7 @@ Also accepts the following special argum
> >      $regs   -- all registers.\n\
> >      $args   -- all function arguments.\n\
> >      $locals -- all variables local to the block/function scope.\n\
> > +    $_sdata  -- static tracepoint data (ignored for non-static tracepoints).\n\
> 
> The last line is misaligned.

Fixed.

> 
> > +* Static tracepoints
> > +
> > +  Static tracepoints are calls in the user program into a tracing
> > +  library.  One such library is a port of the LTTng kernel tracer to
> > +  userspace --- UST (LTTng Userspace Tracer).
> 
> A URL would be useful here.

Indeed.  Added.

> 
> >                                                  GDB, when debugging
> > +  with GDBserver, now supports combining the GDB tracepoint machinery
> 
> "When debugging with GDBserver, GDB now supports ..."
> 
> > +  information, see the "Tracepoints" chapter in GDB user manual.  New
> 
> "in the GDB User Manual"
> 
> > +strace FN / FILE:LINE / *ADDR / -m MARKER_ID
> 
> I think alternatives are separated by "|", not by "/".  (Yes, I know
> that the entry for "ftrace" used "/"; it also needs to be fixed.)

You're right.  Fixed.

> 
> The patch for NEWS is okay with these changes.

Thanks.

> > +@vindex $_sdata@r{, inspect, convenience variable}
> > +The variable @code{$_sdata} contains extra collected static tracepoint
> > +data.  (@pxref{Tracepoint Actions,,Tracepoint Action Lists}).  Note
> 
> @pxref is not appropriate here.  I would simply use @xref and drop the
> parentheses.

Indeed.  Done that.

> > +that @code{$_sdata} could be empty, if not inspecting a trace buffer,
> > +or extra static tracepoint data has not been collected.
> 
> "or if extra static tracepoint data has not been collected yet."

I don't think the "yet" makes sense here.  I've added the "if" though.

> 
> > +in the target.  Some targets may yet support controlling @dfn{static
> > +tracepoints} from @value{GDBN}.
> 
> Please replace "yet" with "also".

Done.

> 
> >                                   With static tracing, a set of
> > +instrumentation points, also known as @dfn{markers}, are embedded in
> 
> This section should have @cindex entries for every phrase you have in
> @dfn.

I see.  Makes sense.  Done.

> > +@cindex set static tracepoint
> 
> This index entry would be much more efficient if it did not start with
> "set".  For example,
> 
>   @cindex static tracepoint, setting

Agreed.  I see the same could be done to set fast tracepoint.  I'll
see about auditing that and others after this patch is in.

> 
> > +@kindex strace
> > +The @code{strace} command sets a static tracepoint.  For targets that
> > +support it, setting a static tracepoint probes a static
> > +instrumentation point, or marker, found at @var{location}.
> 
> The meaning of "probe an instrumentation point" was never explained.
> I think it should be; without it, much of the following material
> doesn't make much sense.

Okay.  I've explained it in the static tracepoints intro text.

> > +@value{GDBN} handles arguments to @code{strace} exactly as for
> > +@code{trace}, with the addition that the user can also specify
> > +@code{-m @var{marker}} as @var{location}.  This probes the marker
> > +identified by the @var{marker} string identifier.
> > +
> > +Static tracepoints accept an extra collect action --- @code{collect
> > +$_sdata}.  This collects arbitrary user data passed in the probe point
> > +call to the tracing library.
> 
> The "string identifier" and "user data" parts should also be
> explained.  Perhaps show a sample call to `trace_mark' in the
> instrumented source and explain the relationships between its
> arguments and the terminology you use in this section.

Done that.  Let me know what you think.

> 
> >                               You can inspect this data when analysing
> 
> "analyzing"

Fixed.

> 
> > +@item $_sdata
> > +@vindex $_sdata@r{, collect}
> > +Collect static tracepoint marker specific data.  Only available for
> > +static tracepoints.
> 
> An xref to where static tracepoints are described is missing here.

Added an xref.

> 
> >                      This usually consists of data formatted to a
> > +character string using the format provided by the programmer that
> > +instrumented the program.  E.g., on some systems, an instrumentation
> > +point resembles a printf function call:
> > +
> > +@smallexample
> > + TRACE(tp1, "hello %s", master_name)
> > +@end smallexample
> 
> How do you mean ``on some systems''?  This support is inherently
> platform-specific, and is extremely unlikely to be extended to
> any platform but GNU/Linux.  It doesn't seem a good idea to be vague
> about this issue here.

This was trying to not be platform specific on purpose.  The support in
GDB is not platform specific in any way.  The gdbserver
implementation only works on linux GNU/Linux presently, but it could
be made to work on other platforms.  UST runs entirely in userspace,
so it could be made to work on other systems as well.


> 
> > +Collecting @code{$_sdata} in this case collects the string @samp{hello
> > +$yourname}.
> 
> What is "$yourname"?  Did you mean "master_name"?

Yes, well, its contents.  I've added the master_name variable definition
to the example, which hopefully makes it more obvious.

> 
> > +@cindex information about static tracepoint markers in the target program.
> 
> This entry is too long.  Perhaps just
> 
>   @cindex information about static tracepoint markers
> 
> is enough.  (You don't need the period, either.)

Thanks.  Done that.

> 
> > +libraries.  The most simple way to do that is to run the program to
>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> "The simplest way to do that ..."

Thanks.  This one was already there, but it was my wrong doing.  :-)

> > +@item qTfSTM
> > +@itemx qTsSTM
> 
> The error responses don't seem to be documented here.  Should they be?

Added.

> 
> > +query), until the target responds with @samp{l} (lower-case el, for
> > +@dfn{last}).                                                ^^
> 
> "ell"

Thanks.  This was copied from elsewhere.  I'll audit those as well
after this is in.

> Thanks.

Thank you.

New version attached.  Okay?

-- 
Pedro Alves

2010-06-28  Pedro Alves  <pedro@codesourcery.com>

	gdb/gdbserver/
	* configure.ac: Handle --with-ust.  substitute ustlibs and ustinc.
	* mem-break.c (uninsert_all_breakpoints)
	(reinsert_all_breakpoints): New.
	* mem-break.h (reinsert_all_breakpoints, uninsert_all_breakpoints):
	* tracepoint.c (ust_loaded, helper_thread_id, cmd_buf): New.
	(gdb_agent_ust_loaded, helper_thread_id)
	(gdb_agent_helper_thread_id): New macros.
	(struct ipa_sym_addresses): Add addr_ust_loaded,
	addr_helper_thread_id, addr_cmd_buf.
	(symbol_list): Add ust_loaded, helper_thread_id, cmd_buf.
	(in_process_agent_loaded_ust): New.
	(write_e_ust_not_loaded): New.
	(maybe_write_ipa_ust_not_loaded): New.
	(struct collect_static_trace_data_action): New.
	(enum tracepoint_type) <static_tracepoint>: New.
	(struct tracepoint) <handle>: Mention static tracepoints.
	(struct static_tracepoint_ctx): New.
	(CMD_BUF_SIZE): New.
	(add_tracepoint_action): Handle static tracepoint actions.
	(unprobe_marker_at): New.
	(clear_installed_tracepoints): Handle static tracepoints.
	(cmd_qtdp): Handle static tracepoints.
	(probe_marker_at): New.
	(cmd_qtstart): Handle static tracepoints.
	(response_tracepoint): Handle static tracepoints.
	(cmd_qtfstm, cmd_qtsstm, cmd_qtstmat): New.
	(handle_tracepoint_query): Handle qTfSTM, qTsSTM and qTSTMat.
	(get_context_regcache): Handle static tracepoints.
	(do_action_at_tracepoint): Handle static tracepoint actions.
	(traceframe_find_block_type): Handle static trace data blocks.
	(traceframe_read_sdata): New.
	(download_tracepoints): Download static tracepoint actions.
	[HAVE_UST] Include ust/ust.h, dlfcn.h, sys/socket.h, and sys/un.h.
	(GDB_PROBE_NAME): New.
	(ust_ops): New.
	(GET_UST_SYM): New.
	(USTF): New.
	(dlsym_ust): New.
	(ust_marker_to_static_tracepoint): New.
	(gdb_probe): New.
	(collect_ust_data_at_tracepoint): New.
	(gdb_ust_probe): New.
	(UNIX_PATH_MAX, SOCK_DIR): New.
	(gdb_ust_connect_sync_socket): New.
	(resume_thread, stop_thread): New.
	(run_inferior_command): New.
	(init_named_socket): New.
	(gdb_ust_socket_init): New.
	(cstr_to_hexstr): New.
	(next_st): New.
	(first_marker, next_marker): New.
	(response_ust_marker): New.
	(cmd_qtfstm, cmd_qtsstm): New.
	(unprobe_marker_at, probe_marker_at): New.
	(cmd_qtstmat, gdb_ust_thread): New.
	(gdb_ust_init): New.
	(initialize_tracepoint_ftlib): Call gdb_ust_init.
	* linux-amd64-ipa.c [HAVE_UST]: Include ust/processor.h
	(ST_REGENTRY): New.
	(x86_64_st_collect_regmap): New.
	(X86_64_NUM_ST_COLLECT_GREGS): New.
	(AMD64_RIP_REGNUM): New.
	(supply_static_tracepoint_registers): New.
	* linux-i386-ipa.c [HAVE_UST]: Include ust/processor.h
	(ST_REGENTRY): New.
	(i386_st_collect_regmap): New.
	(i386_NUM_ST_COLLECT_GREGS): New.
	(supply_static_tracepoint_registers): New.
	* server.c (handle_query): Handle qXfer:statictrace:read.
	<qSupported>: Report support for StaticTracepoints, and
	qXfer:statictrace:read features.
	* server.h (traceframe_read_sdata)
	(supply_static_tracepoint_registers): Declare.
	* remote-utils.c (convert_int_to_ascii, hexchars, ishex, tohex)
	(unpack_varlen_hex): Include in IPA build.
	* Makefile.in (IPA_OBJS): Add remote-utils-ipa.o.
	* config.in, configure: Regenerate.
	
	gdb/
	* NEWS: Mention new support for static tracepoints.
	(New packets): Mention qTfSTM, qTsSTM, qTSTMat and
	qXfer:statictrace:read.
	(New features in the GDB remote stub, GDBserver): Mention static
	tracepoints support using an UST based backend.
	(New commands): Mention "info static-tracepoint-markers" and
	"strace".
	* breakpoint.c (is_tracepoint): Handle static tracepoints.
	(validate_commands_for_breakpoint): Static tracepoints can't do
	while-stepping.
	(static_tracepoints_here): New.
	(bpstat_what): Handle static tracepoints.
	(print_one_breakpoint_location, allocate_bp_location, mention):
	Ditto.
	(create_breakpoint_sal): Ditto.
	(decode_static_tracepoint_spec): New.
	(create_breakpoint): Replace `hardwareflag', and `traceflag' with
	`type_wanted'.  Adjust.  Handle static tracepoint marker
	locations.
	(break_command_1): Adjust.
	(update_static_tracepoint): New.
	(update_breakpoint_locations): Handle static tracepoints.
	(breakpoint_re_set_one): Handle static tracepoint marker
	locations.
	(disable_command, enable_command): Handle static tracepoints.
	(trace_command, ftrace_command): Adjust.
	(strace_command): New.
	(create_tracepoint_from_upload): Adjust.
	(save_breakpoints): Handle static tracepoints.
	(_initialize_breakpoint): Install the "strace" command.
	* breakpoint.h (enum bptype): New bp_static_tracepoint type.
	(struct breakpoint): New field static_trace_id.
	(breakpoints_here_p): Declare.
	(create_breakpoint): Adjust.
	(static_tracepoints_here): Declare.
	* remote.c (struct remote_state) <static_tracepoints>: New field.
	(PACKET_qXfer_statictrace_read, PACKET_StaticTracepoints): New.
	(remote_static_tracepoint_marker_at): New.
	(remote_static_tracepoint_marker_by_strid): New.
	(remote_list_static_tracepoint_markers): New.
	(remote_static_tracepoint_feature): New.
	(remote_disconnected_tracing_feature): Handle "StaticTracepoints".
	(remote_xfer_partial): Handle TARGET_OBJECT_STATIC_TRACE_DATA.
	(remote_supports_static_tracepoints): New.
	(remote_download_tracepoint): Download static tracepoints.
	(init_remote_ops): Install remote_list_static_tracepoint_markers,
	remote_static_tracepoint_marker_at and
	remote_static_tracepoint_marker_by_strid.
	(_initialize_remote): Install set|show remote static-tracepoints,
	and set|show remote read-static-trace-object commands.
	* target.c (update_current_target): Inherit and default
	to_list_static_tracepoint_markers, to_static_tracepoint_marker_at,
	to_static_tracepoint_marker_by_strid.
	* target.h (static_tracepoint_marker): Forward declare.
	(enum target_object): New object TARGET_OBJECT_STATIC_TRACE_DATA.
	(struct target_ops): New fields to_list_static_tracepoint_markers,
	to_static_tracepoint_marker_at,
	to_static_tracepoint_marker_by_strid.
	(target_list_static_tracepoint_markers)
	(target_static_tracepoint_marker_at)
	(target_static_tracepoint_marker_by_strid): New.
	* tracepoint.c: Include source.h.
	(validate_actionline): Handle $_sdata.
	(struct collection_list): New field strace_data.
	(add_static_trace_data): New.
	(clear_collection_list): Clear strace_data.
	(stringify_collection_list): Account for a possible static trace
	data collection.
	(encode_actions_1): Encode an $_sdata collection.
	(parse_tracepoint_definition): Handle static tracepoints.
	(parse_static_tracepoint_marker_definition): New.
	(release_static_tracepoint_marker): New.
	(print_one_static_tracepoint_marker): New.
	(info_static_tracepoint_markers_command): New.
	(sdata_make_value): New.
	(_initialize_tracepoint): Create the $_sdata convenience variable.
	Add the "info static-tracepoint-markers" command.
	Mention $_sdata in the "collect" command's help output.
	* tracepoint.h (struct static_tracepoint_marker): New.
	(parse_static_tracepoint_marker_definition)
	(print_one_static_tracepoint_marker)
	(release_static_tracepoint_marker): Declare.
	* mi/mi-cmd-break.c (mi_cmd_break_insert): Adjust.
	* python/py-breakpoint.c (bppy_new): Adjust.

	doc/
	* gdb.texinfo (Convenience Variables): Document $_sdata.
	(Commands to Set Tracepoints): Describe static tracepoints.  Add
	`Listing Static Tracepoint Markers' menu entry.  Document
	"strace".
	(Tracepoint Action Lists): Document collecting $_sdata.
	(Listing Static Tracepoint Markers): New subsection.
	(Tracepoints support in gdbserver): Mention static tracepoints.
	(remote packets, enabling and disabling): Mention
	read-sdata-object.
	(General Query Packets) <qSupported>: Document qXfer:sdata:read
	and StaticTracepoint.
	Mention qTfSTM, qTsSTM and qTSTMat as tracepoint packets.
	Document qXfer:sdata:read.
	(Tracepoint packets): Document qTfSTM, qTsSTM and qTSTMat.

---
 gdb/NEWS                        |   69 +-
 gdb/breakpoint.c                |  329 +++++++++-
 gdb/breakpoint.h                |   13 
 gdb/doc/gdb.texinfo             |  232 ++++++-
 gdb/gdbserver/Makefile.in       |    2 
 gdb/gdbserver/config.in         |    3 
 gdb/gdbserver/configure         |  104 +++
 gdb/gdbserver/configure.ac      |   48 +
 gdb/gdbserver/linux-amd64-ipa.c |   89 ++
 gdb/gdbserver/linux-i386-ipa.c  |   77 ++
 gdb/gdbserver/mem-break.c       |   22 
 gdb/gdbserver/mem-break.h       |   11 
 gdb/gdbserver/remote-utils.c    |   19 
 gdb/gdbserver/server.c          |   48 +
 gdb/gdbserver/server.h          |    7 
 gdb/gdbserver/tracepoint.c      | 1272 +++++++++++++++++++++++++++++++++++++++-
 gdb/mi/mi-cmd-break.c           |   15 
 gdb/python/py-breakpoint.c      |    2 
 gdb/remote.c                    |  160 +++++
 gdb/target.c                    |   12 
 gdb/target.h                    |   27 
 gdb/tracepoint.c                |  276 ++++++++
 gdb/tracepoint.h                |   20 
 23 files changed, 2788 insertions(+), 69 deletions(-)

Index: src/gdb/gdbserver/configure.ac
===================================================================
--- src.orig/gdb/gdbserver/configure.ac	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/configure.ac	2010-06-25 12:01:29.000000000 +0100
@@ -45,6 +45,54 @@ AC_CHECK_HEADERS(sgtty.h termio.h termio
 AC_CHECK_FUNCS(pread pwrite pread64)
 AC_REPLACE_FUNCS(memmem)
 
+# Check for UST
+ustlibs=""
+ustinc=""
+
+AC_ARG_WITH(ust, [  --with-ust=PATH       Specify prefix directory for the installed UST package
+                          Equivalent to --with-ust-include=PATH/include
+                          plus --with-ust-lib=PATH/lib])
+AC_ARG_WITH(ust_include, [  --with-ust-include=PATH Specify directory for installed UST include files])
+AC_ARG_WITH(ust_lib, [  --with-ust-lib=PATH   Specify the directory for the installed UST library])
+
+case $with_ust in
+  no)
+    ustlibs=
+    ustinc=
+    ;;
+  "" | yes)
+    ustlibs=" -lust "
+    ustinc=""
+    ;;
+  *)
+    ustlibs="-L$with_ust/lib -lust"
+    ustinc="-I$with_ust/include "
+    ;;
+esac
+if test "x$with_ust_include" != x; then
+  ustinc="-I$with_ust_include "
+fi
+if test "x$with_ust_lib" != x; then
+  ustlibs="-L$with_ust_lib -lust"
+fi
+
+if test "x$with_ust" != "xno"; then
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $ustinc"
+  AC_MSG_CHECKING([for ust])
+  AC_TRY_COMPILE([
+#define CONFIG_UST_GDB_INTEGRATION
+#include <ust/ust.h>
+  ],[],
+  [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_UST, 1, [Define if UST is available])],
+  [AC_MSG_RESULT([no]); ustlibs= ; ustinc= ])
+  CFLAGS="$saved_CFLAGS"
+fi
+
+# Flags needed for UST
+AC_SUBST(ustlibs)
+AC_SUBST(ustinc)
+
 dnl dladdr is glibc-specific.  It is used by thread-db.c but only for
 dnl debugging messages.  It lives in -ldl which is handled below so we don't
 dnl use AC_CHECK_LIB (or AC_SEARCH_LIBS) here.  Instead we just temporarily
Index: src/gdb/gdbserver/mem-break.c
===================================================================
--- src.orig/gdb/gdbserver/mem-break.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/mem-break.c	2010-06-25 12:01:29.000000000 +0100
@@ -777,6 +777,17 @@ uninsert_breakpoints_at (CORE_ADDR pc)
     uninsert_raw_breakpoint (bp);
 }
 
+void
+uninsert_all_breakpoints (void)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
+
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (bp->inserted)
+      uninsert_raw_breakpoint (bp);
+}
+
 static void
 reinsert_raw_breakpoint (struct raw_breakpoint *bp)
 {
@@ -817,6 +828,17 @@ reinsert_breakpoints_at (CORE_ADDR pc)
 }
 
 void
+reinsert_all_breakpoints (void)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
+
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (!bp->inserted)
+      reinsert_raw_breakpoint (bp);
+}
+
+void
 check_breakpoints (CORE_ADDR stop_pc)
 {
   struct process_info *proc = current_process ();
Index: src/gdb/gdbserver/mem-break.h
===================================================================
--- src.orig/gdb/gdbserver/mem-break.h	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/mem-break.h	2010-06-25 12:01:29.000000000 +0100
@@ -78,6 +78,17 @@ void reinsert_breakpoints_at (CORE_ADDR 
 
 void uninsert_breakpoints_at (CORE_ADDR where);
 
+/* Reinsert all breakpoints of the current process (and change their
+   status to inserted).  */
+
+void reinsert_all_breakpoints (void);
+
+/* Uninsert all breakpoints of the current process (and change their
+   status to uninserted).  This still leaves the breakpoints in the
+   table.  */
+
+void uninsert_all_breakpoints (void);
+
 /* See if any breakpoint claims ownership of STOP_PC.  Call the handler for
    the breakpoint, if found.  */
 
Index: src/gdb/gdbserver/tracepoint.c
===================================================================
--- src.orig/gdb/gdbserver/tracepoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/tracepoint.c	2010-06-28 13:23:58.000000000 +0100
@@ -135,6 +135,9 @@ trace_vdebug (const char *fmt, ...)
 # define get_raw_reg gdb_agent_get_raw_reg
 # define get_trace_state_variable_value gdb_agent_get_trace_state_variable_value
 # define set_trace_state_variable_value gdb_agent_set_trace_state_variable_value
+# define ust_loaded gdb_agent_ust_loaded
+# define helper_thread_id gdb_agent_helper_thread_id
+# define cmd_buf gdb_agent_cmd_buf
 #endif
 
 #ifndef IN_PROCESS_AGENT
@@ -168,6 +171,9 @@ struct ipa_sym_addresses
   CORE_ADDR addr_get_raw_reg;
   CORE_ADDR addr_get_trace_state_variable_value;
   CORE_ADDR addr_set_trace_state_variable_value;
+  CORE_ADDR addr_ust_loaded;
+  CORE_ADDR addr_helper_thread_id;
+  CORE_ADDR addr_cmd_buf;
 };
 
 #define STRINGIZE_1(STR) #STR
@@ -209,6 +215,9 @@ static struct
   IPA_SYM(get_raw_reg),
   IPA_SYM(get_trace_state_variable_value),
   IPA_SYM(set_trace_state_variable_value),
+  IPA_SYM(ust_loaded),
+  IPA_SYM(helper_thread_id),
+  IPA_SYM(cmd_buf),
 };
 
 struct ipa_sym_addresses ipa_sym_addrs;
@@ -223,6 +232,29 @@ in_process_agent_loaded (void)
 
 static int read_inferior_integer (CORE_ADDR symaddr, int *val);
 
+/* Returns true if both the in-process agent library and the static
+   tracepoints libraries are loaded in the inferior.  */
+
+static int
+in_process_agent_loaded_ust (void)
+{
+  int loaded = 0;
+
+  if (!in_process_agent_loaded ())
+    {
+      warning ("In-process agent not loaded");
+      return 0;
+    }
+
+  if (read_inferior_integer (ipa_sym_addrs.addr_ust_loaded, &loaded))
+    {
+      warning ("Error reading ust_loaded in lib");
+      return 0;
+    }
+
+  return loaded;
+}
+
 static void
 write_e_ipa_not_loaded (char *buffer)
 {
@@ -231,6 +263,24 @@ write_e_ipa_not_loaded (char *buffer)
 	   "Dynamic tracepoints unavailable.");
 }
 
+/* Write an error to BUFFER indicating that UST isn't loaded in the
+   inferior.  */
+
+static void
+write_e_ust_not_loaded (char *buffer)
+{
+#ifdef HAVE_UST
+  sprintf (buffer,
+	   "E.UST library not loaded in process.  "
+	   "Static tracepoints unavailable.");
+#else
+  sprintf (buffer, "E.GDBserver was built without static tracepoints support");
+#endif
+}
+
+/* If the in-process agent library isn't loaded in the inferior, write
+   an error to BUFFER, and return 1.  Otherwise, return 0.  */
+
 static int
 maybe_write_ipa_not_loaded (char *buffer)
 {
@@ -242,6 +292,26 @@ maybe_write_ipa_not_loaded (char *buffer
   return 0;
 }
 
+/* If the in-process agent library and the ust (static tracepoints)
+   library aren't loaded in the inferior, write an error to BUFFER,
+   and return 1.  Otherwise, return 0.  */
+
+static int
+maybe_write_ipa_ust_not_loaded (char *buffer)
+{
+  if (!in_process_agent_loaded ())
+    {
+      write_e_ipa_not_loaded (buffer);
+      return 1;
+    }
+  else if (!in_process_agent_loaded_ust ())
+    {
+      write_e_ust_not_loaded (buffer);
+      return 1;
+    }
+  return 0;
+}
+
 /* Cache all future symbols that the tracepoints module might request.
    We can not request symbols at arbitrary states in the remote
    protocol, only when the client tells us that new symbols are
@@ -347,6 +417,8 @@ static void download_tracepoints (void);
 static void download_trace_state_variables (void);
 static void upload_fast_traceframes (void);
 
+static int run_inferior_command (char *cmd);
+
 static int
 read_inferior_integer (CORE_ADDR symaddr, int *val)
 {
@@ -542,6 +614,12 @@ struct eval_expr_action
   struct agent_expr *expr;
 };
 
+/* An 'L' (collect static trace data) action.  */
+struct collect_static_trace_data_action
+{
+  struct tracepoint_action base;
+};
+
 /* This structure describes a piece of the source-level definition of
    the tracepoint.  The contents are not interpreted by the target,
    but preserved verbatim for uploading upon reconnection.  */
@@ -569,6 +647,10 @@ enum tracepoint_type
 
   /* A fast tracepoint implemented with a jump instead of a trap.  */
   fast_tracepoint,
+
+  /* A static tracepoint, implemented by a program call into a tracing
+     library.  */
+  static_tracepoint
 };
 
 struct tracepoint_hit_ctx;
@@ -667,8 +749,8 @@ struct tracepoint
   char **step_actions_str;
 
   /* Handle returned by the breakpoint or tracepoint module when we
-     inserted the trap or jump.  NULL if we haven't inserted it
-     yet.  */
+     inserted the trap or jump, or hooked into a static tracepoint.
+     NULL if we haven't inserted it yet.  */
   void *handle;
 #endif
 
@@ -1157,6 +1239,35 @@ struct fast_tracepoint_ctx
   struct tracepoint *tpoint;
 };
 
+/* Static tracepoint specific data to be passed down to
+   collect_data_at_tracepoint.  */
+struct static_tracepoint_ctx
+{
+  struct tracepoint_hit_ctx base;
+
+  /* The regcache corresponding to the registers state at the time of
+     the tracepoint hit.  Initialized lazily, from REGS.  */
+  struct regcache regcache;
+  int regcache_initted;
+
+  /* The buffer space REGCACHE above uses.  We use a separate buffer
+     instead of letting the regcache malloc for both signal safety and
+     performance reasons; this is allocated on the stack instead.  */
+  unsigned char *regspace;
+
+  /* The register buffer as passed on by lttng/ust.  */
+  struct registers *regs;
+
+  /* The "printf" formatter and the args the user passed to the marker
+     call.  We use this to be able to collect "static trace data"
+     ($_sdata).  */
+  const char *fmt;
+  va_list *args;
+
+  /* The GDB tracepoint matching the probed marker that was "hit".  */
+  struct tracepoint *tpoint;
+};
+
 #else
 
 /* Static tracepoint specific data to be passed down to
@@ -1228,6 +1339,10 @@ static struct tracepoint *fast_tracepoin
 #define cmpxchg(mem, oldval, newval) \
   __sync_val_compare_and_swap (mem, oldval, newval)
 
+/* The size in bytes of the buffer used to talk to the IPA helper
+   thread.  */
+#define CMD_BUF_SIZE 1024
+
 /* Record that an error occurred during expression evaluation.  */
 
 static void
@@ -1756,6 +1871,18 @@ add_tracepoint_action (struct tracepoint
 	      ++act;
 	    break;
 	  }
+	case 'L':
+	  {
+	    struct collect_static_trace_data_action *raction;
+
+	    raction = xmalloc (sizeof *raction);
+	    raction->base.type = *act;
+	    action = &raction->base;
+
+	    trace_debug ("Want to collect static trace data");
+	    ++act;
+	    break;
+	  }
 	case 'S':
 	  trace_debug ("Unexpected step action, ignoring");
 	  ++act;
@@ -2147,6 +2274,17 @@ cmd_qtinit (char *packet)
   write_ok (packet);
 }
 
+/* Unprobe the UST marker at ADDRESS.  */
+
+static void
+unprobe_marker_at (CORE_ADDR address)
+{
+  char cmd[CMD_BUF_SIZE];
+
+  sprintf (cmd, "unprobe_marker_at:%s", paddress (address));
+  run_inferior_command (cmd);
+}
+
 /* Restore the program to its pre-tracing state.  This routine may be called
    in error situations, so it needs to be careful about only restoring
    from known-valid bits.  */
@@ -2186,6 +2324,19 @@ clear_installed_tracepoints (void)
 	case fast_tracepoint:
 	  delete_fast_tracepoint_jump (tpoint->handle);
 	  break;
+	case static_tracepoint:
+	  if (prev_stpoint != NULL
+	      && prev_stpoint->address == tpoint->address)
+	    /* Nothing to do.  We already unprobed a tracepoint set at
+	       this marker address (and there can only be one probe
+	       per marker).  */
+	    ;
+	  else
+	    {
+	      unprobe_marker_at (tpoint->address);
+	      prev_stpoint = tpoint;
+	    }
+	  break;
 	}
 
       tpoint->handle = NULL;
@@ -2258,6 +2409,11 @@ cmd_qtdp (char *own_buf)
 	      packet = unpack_varlen_hex (packet, &count);
 	      tpoint->orig_size = count;
 	    }
+	  else if (*packet == 'S')
+	    {
+	      tpoint->type = static_tracepoint;
+	      ++packet;
+	    }
 	  else if (*packet == 'X')
 	    {
 	      actparm = (char *) packet;
@@ -2570,12 +2726,39 @@ sort_tracepoints (void)
       }
 }
 
+/* Ask the IPA to probe the marker at ADDRESS.  Returns -1 if running
+   the command fails, or 0 otherwise.  If the command ran
+   successfully, but probing the marker failed, ERROUT will be filled
+   with the error to reply to GDB, and -1 is also returned.  This
+   allows directly passing IPA errors to GDB.  */
+
+static int
+probe_marker_at (CORE_ADDR address, char *errout)
+{
+  char cmd[CMD_BUF_SIZE];
+  int err;
+
+  sprintf (cmd, "probe_marker_at:%s", paddress (address));
+  err = run_inferior_command (cmd);
+
+  if (err == 0)
+    {
+      if (*cmd == 'E')
+	{
+	  strcpy (errout, cmd);
+	  return -1;
+	}
+    }
+
+  return err;
+}
+
 #define MAX_JUMP_SIZE 20
 
 static void
 cmd_qtstart (char *packet)
 {
-  struct tracepoint *tpoint, *prev_ftpoint;
+  struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint;
   int slow_tracepoint_count, fast_count;
   CORE_ADDR jump_entry;
 
@@ -2614,6 +2797,9 @@ cmd_qtstart (char *packet)
   /* No previous fast tpoint yet.  */
   prev_ftpoint = NULL;
 
+  /* No previous static tpoint yet.  */
+  prev_stpoint = NULL;
+
   *packet = '\0';
 
   /* Install tracepoints.  */
@@ -2699,6 +2885,32 @@ cmd_qtstart (char *packet)
 		}
 	    }
 	}
+      else if (tpoint->type == static_tracepoint)
+	{
+	  if (maybe_write_ipa_ust_not_loaded (packet))
+	    {
+	      trace_debug ("Requested a static tracepoint, but static "
+			   "tracepoints are not supported.");
+	      break;
+	    }
+
+	  /* Can only probe a given marker once.  */
+	  if (prev_stpoint != NULL && prev_stpoint->address == tpoint->address)
+	    {
+	      tpoint->handle = (void *) -1;
+	    }
+	  else
+	    {
+	      if (probe_marker_at (tpoint->address, packet) == 0)
+		{
+		  tpoint->handle = (void *) -1;
+
+		  /* So that we can handle multiple static tracepoints
+		     at the same address easily.  */
+		  prev_stpoint = tpoint;
+		}
+	    }
+	}
 
       /* Any failure in the inner loop is sufficient cause to give
 	 up.  */
@@ -3039,6 +3251,8 @@ response_tracepoint (char *packet, struc
 	   tpoint->pass_count);
   if (tpoint->type == fast_tracepoint)
     sprintf (packet + strlen (packet), ":F%x", tpoint->orig_size);
+  else if (tpoint->type == static_tracepoint)
+    sprintf (packet + strlen (packet), ":S");
 
   if (tpoint->cond)
     {
@@ -3213,6 +3427,36 @@ cmd_qtsv (char *packet)
     strcpy (packet, "l");
 }
 
+/* Return the first static tracepoint marker, and initialize the state
+   machine that will iterate through all the static tracepoints
+   markers.  */
+
+static void
+cmd_qtfstm (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet);
+}
+
+/* Return additional static tracepoints markers.  */
+
+static void
+cmd_qtsstm (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet);
+}
+
+/* Return the definition of the static tracepoint at a given address.
+   Result packet is the same as qTsST's.  */
+
+static void
+cmd_qtstmat (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet);
+}
+
 /* Respond to qTBuffer packet with a block of raw data from the trace
    buffer.  GDB may ask for a lot, but we are allowed to reply with
    only as much as will fit within packet limits or whatever.  */
@@ -3384,6 +3628,21 @@ handle_tracepoint_query (char *packet)
       cmd_qtbuffer (packet);
       return 1;
     }
+  else if (strcmp ("qTfSTM", packet) == 0)
+    {
+      cmd_qtfstm (packet);
+      return 1;
+    }
+  else if (strcmp ("qTsSTM", packet) == 0)
+    {
+      cmd_qtsstm (packet);
+      return 1;
+    }
+  else if (strncmp ("qTSTMat:", packet, strlen ("qTSTMat:")) == 0)
+    {
+      cmd_qtstmat (packet);
+      return 1;
+    }
 
   return 0;
 }
@@ -3697,6 +3956,14 @@ tracepoint_was_hit (struct thread_info *
 
 #endif
 
+#if defined IN_PROCESS_AGENT && defined HAVE_UST
+struct ust_marker_data;
+static void collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
+					    CORE_ADDR stop_pc,
+					    struct tracepoint *tpoint,
+					    struct traceframe *tframe);
+#endif
+
 /* Create a trace frame for the hit of the given tracepoint in the
    given thread.  */
 
@@ -3803,6 +4070,25 @@ get_context_regcache (struct tracepoint_
 	}
       regcache = &fctx->regcache;
     }
+#ifdef HAVE_UST
+  if (ctx->type == static_tracepoint)
+    {
+      struct static_tracepoint_ctx *sctx = (struct static_tracepoint_ctx *) ctx;
+      if (!sctx->regcache_initted)
+	{
+	  sctx->regcache_initted = 1;
+	  init_register_cache (&sctx->regcache, sctx->regspace);
+	  supply_regblock (&sctx->regcache, NULL);
+	  /* Pass down the tracepoint address, because REGS doesn't
+	     include the PC, but we know what it must have been.  */
+	  supply_static_tracepoint_registers (&sctx->regcache,
+					      (const unsigned char *)
+					      sctx->regs,
+					      sctx->tpoint->address);
+	}
+      regcache = &sctx->regcache;
+    }
+#endif
 #else
   if (ctx->type == trap_tracepoint)
     {
@@ -3910,6 +4196,18 @@ do_action_at_tracepoint (struct tracepoi
 	  }
       }
       break;
+    case 'L':
+      {
+#if defined IN_PROCESS_AGENT && defined HAVE_UST
+	trace_debug ("Want to collect static trace data");
+	collect_ust_data_at_tracepoint (ctx, stop_pc,
+					tpoint, tframe);
+#else
+	trace_debug ("warning: collecting static trace data, "
+		     "but static tracepoints are not supported");
+#endif
+      }
+      break;
     default:
       trace_debug ("unknown trace action '%c', ignoring", taction->type);
       break;
@@ -4494,6 +4792,11 @@ traceframe_find_block_type (unsigned cha
 	  /* Skip over the TSV block.  */
 	  dataptr += (sizeof (int) + sizeof (LONGEST));
 	  break;
+	case 'S':
+	  /* Skip over the static trace data block.  */
+	  memcpy (&mlen, dataptr, sizeof (mlen));
+	  dataptr += (sizeof (mlen) + mlen);
+	  break;
 	default:
 	  trace_debug ("traceframe %d has unknown block type 0x%x",
 		       tfnum, blocktype);
@@ -4684,6 +4987,59 @@ traceframe_read_tsv (int tsvnum, LONGEST
   return 1;
 }
 
+/* Read a requested block of static tracepoint data from a trace
+   frame.  */
+
+int
+traceframe_read_sdata (int tfnum, ULONGEST offset,
+		       unsigned char *buf, ULONGEST length,
+		       ULONGEST *nbytes)
+{
+  struct traceframe *tframe;
+  unsigned char *database, *dataptr;
+  unsigned int datasize;
+  unsigned short mlen;
+
+  trace_debug ("traceframe_read_sdata");
+
+  tframe = find_traceframe (tfnum);
+
+  if (!tframe)
+    {
+      trace_debug ("traceframe %d not found", tfnum);
+      return 1;
+    }
+
+  datasize = tframe->data_size;
+  database = &tframe->data[0];
+
+  /* Iterate through a traceframe's blocks, looking for static
+     tracepoint data.  */
+  dataptr = traceframe_find_block_type (database, datasize,
+					tfnum, 'S');
+  if (dataptr != NULL)
+    {
+      memcpy (&mlen, dataptr, sizeof (mlen));
+      dataptr += sizeof (mlen);
+      if (offset < mlen)
+	{
+	  if (offset + length > mlen)
+	    length = mlen - offset;
+
+	  memcpy (buf, dataptr, length);
+	  *nbytes = length;
+	}
+      else
+	*nbytes = 0;
+      return 0;
+    }
+
+  trace_debug ("traceframe %d has no static trace data", tfnum);
+
+  *nbytes = 0;
+  return 0;
+}
+
 /* Return the first fast tracepoint whose jump pad contains PC.  */
 
 static struct tracepoint *
@@ -5631,7 +5987,8 @@ download_tracepoints (void)
     {
       struct tracepoint target_tracepoint;
 
-      if (tpoint->type != fast_tracepoint)
+      if (tpoint->type != fast_tracepoint
+	  && tpoint->type != static_tracepoint)
 	continue;
 
       /* Maybe download a compiled condition.  */
@@ -5742,6 +6099,14 @@ download_tracepoints (void)
 		       expr);
 		    break;
 		  }
+		case 'L':
+		  ipa_action = target_malloc
+		    (sizeof (struct collect_static_trace_data_action));
+		  write_inferior_memory
+		    (ipa_action,
+		     (unsigned char *) action,
+		     sizeof (struct collect_static_trace_data_action));
+		  break;
 		default:
 		  trace_debug ("unknown trace action '%c', ignoring",
 			       action->type);
@@ -6087,20 +6452,901 @@ upload_fast_traceframes (void)
 
 #ifdef IN_PROCESS_AGENT
 
-#include <sys/mman.h>
-#include <fcntl.h>
+IP_AGENT_EXPORT int ust_loaded;
+IP_AGENT_EXPORT char cmd_buf[CMD_BUF_SIZE];
 
-IP_AGENT_EXPORT char *gdb_tp_heap_buffer;
-IP_AGENT_EXPORT char *gdb_jump_pad_buffer;
-IP_AGENT_EXPORT char *gdb_jump_pad_buffer_end;
+#ifdef HAVE_UST
 
-static void __attribute__ ((constructor))
-initialize_tracepoint_ftlib (void)
+/* Static tracepoints.  */
+
+/* UST puts a "struct tracepoint" in the global namespace, which
+   conflicts with our tracepoint.  Arguably, being a library, it
+   shouldn't take ownership of such a generic name.  We work around it
+   here.  */
+#define tracepoint ust_tracepoint
+#include <ust/ust.h>
+#undef tracepoint
+
+extern int serialize_to_text (char *outbuf, int bufsize,
+			      const char *fmt, va_list ap);
+
+#define GDB_PROBE_NAME "gdb"
+
+/* We dynamically search for the UST symbols instead of linking them
+   in.  This lets the user decide if the application uses static
+   tracepoints, instead of always pulling libust.so in.  This vector
+   holds pointers to all functions we care about.  */
+
+static struct
 {
-  initialize_tracepoint ();
+  int (*serialize_to_text) (char *outbuf, int bufsize,
+			    const char *fmt, va_list ap);
+
+  int (*ltt_probe_register) (struct ltt_available_probe *pdata);
+  int (*ltt_probe_unregister) (struct ltt_available_probe *pdata);
+
+  int (*ltt_marker_connect) (const char *channel, const char *mname,
+			     const char *pname);
+  int (*ltt_marker_disconnect) (const char *channel, const char *mname,
+				const char *pname);
+
+  void (*marker_iter_start) (struct marker_iter *iter);
+  void (*marker_iter_next) (struct marker_iter *iter);
+  void (*marker_iter_stop) (struct marker_iter *iter);
+  void (*marker_iter_reset) (struct marker_iter *iter);
+} ust_ops;
+
+#include <dlfcn.h>
+
+/* Cast through typeof to catch incompatible API changes.  Since UST
+   only builds with gcc, we can freely use gcc extensions here
+   too.  */
+#define GET_UST_SYM(SYM)					\
+  do								\
+    {								\
+      if (ust_ops.SYM == NULL)					\
+	ust_ops.SYM = (typeof (&SYM)) dlsym (RTLD_DEFAULT, #SYM);	\
+      if (ust_ops.SYM == NULL)					\
+	return 0;						\
+    } while (0)
+
+#define USTF(SYM) ust_ops.SYM
+
+/* Get pointers to all libust.so functions we care about.  */
+
+static int
+dlsym_ust (void)
+{
+  GET_UST_SYM (serialize_to_text);
+
+  GET_UST_SYM (ltt_probe_register);
+  GET_UST_SYM (ltt_probe_unregister);
+  GET_UST_SYM (ltt_marker_connect);
+  GET_UST_SYM (ltt_marker_disconnect);
+
+  GET_UST_SYM (marker_iter_start);
+  GET_UST_SYM (marker_iter_next);
+  GET_UST_SYM (marker_iter_stop);
+  GET_UST_SYM (marker_iter_reset);
+
+  ust_loaded = 1;
+  return 1;
 }
 
-#endif
+/* Given an UST marker, return the matching gdb static tracepoint.
+   The match is done by address.  */
+
+static struct tracepoint *
+ust_marker_to_static_tracepoint (const struct marker *mdata)
+{
+  struct tracepoint *tpoint;
+
+  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
+    {
+      if (!tpoint->enabled || tpoint->type != static_tracepoint)
+	continue;
+
+      if (tpoint->address == (uintptr_t) mdata->location)
+	return tpoint;
+    }
+
+  return NULL;
+}
+
+/* The probe function we install on lttng/ust markers.  Whenever a
+   probed ust marker is hit, this function is called.  This is similar
+   to gdb_collect, only for static tracepoints, instead of fast
+   tracepoints.  */
+
+static void
+gdb_probe (const struct marker *mdata, void *probe_private,
+	   struct registers *regs, void *call_private,
+	   const char *fmt, va_list *args)
+{
+  struct tracepoint *tpoint;
+  struct static_tracepoint_ctx ctx;
+
+  /* Don't do anything until the trace run is completely set up.  */
+  if (!tracing)
+    {
+      trace_debug ("gdb_probe: not tracing\n");
+      return;
+    }
+
+  ctx.base.type = static_tracepoint;
+  ctx.regcache_initted = 0;
+  ctx.regs = regs;
+  ctx.fmt = fmt;
+  ctx.args = args;
+
+  /* Wrap the regblock in a register cache (in the stack, we don't
+     want to malloc here).  */
+  ctx.regspace = alloca (register_cache_size ());
+  if (ctx.regspace == NULL)
+    {
+      trace_debug ("Trace buffer block allocation failed, skipping");
+      return;
+    }
+
+  tpoint = ust_marker_to_static_tracepoint (mdata);
+  if (tpoint == NULL)
+    {
+      trace_debug ("gdb_probe: marker not known: "
+		   "loc:0x%p, ch:\"%s\",n:\"%s\",f:\"%s\"",
+		   mdata->location, mdata->channel,
+		   mdata->name, mdata->format);
+      return;
+    }
+
+  ctx.tpoint = tpoint;
+
+  trace_debug ("gdb_probe: collecting marker: "
+	       "loc:0x%p, ch:\"%s\",n:\"%s\",f:\"%s\"",
+	       mdata->location, mdata->channel,
+	       mdata->name, mdata->format);
+
+  /* Test the condition if present, and collect if true.  */
+  if (tpoint->cond == NULL
+      || condition_true_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
+				       tpoint))
+    {
+      collect_data_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
+				  tpoint->address, tpoint);
+
+      if (stopping_tracepoint
+	  || trace_buffer_is_full
+	  || expr_eval_result != expr_eval_no_error)
+	stop_tracing ();
+    }
+  else
+    {
+      /* If there was a condition and it evaluated to false, the only
+	 way we would stop tracing is if there was an error during
+	 condition expression evaluation.  */
+      if (expr_eval_result != expr_eval_no_error)
+	stop_tracing ();
+    }
+}
+
+/* Called if the gdb static tracepoint requested collecting "$_sdata",
+   static tracepoint string data.  This is a string passed to the
+   tracing library by the user, at the time of the tracepoint marker
+   call.  E.g., in the UST marker call:
+
+     trace_mark (ust, bar33, "str %s", "FOOBAZ");
+
+   the collected data is "str FOOBAZ".
+*/
+
+static void
+collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
+				CORE_ADDR stop_pc,
+				struct tracepoint *tpoint,
+				struct traceframe *tframe)
+{
+  struct static_tracepoint_ctx *umd = (struct static_tracepoint_ctx *) ctx;
+  unsigned char *bufspace;
+  int size;
+  va_list copy;
+  unsigned short blocklen;
+
+  if (umd == NULL)
+    {
+      trace_debug ("Wanted to collect static trace data, "
+		   "but there's no static trace data");
+      return;
+    }
+
+  va_copy (copy, *umd->args);
+  size = USTF(serialize_to_text) (NULL, 0, umd->fmt, copy);
+  va_end (copy);
+
+  trace_debug ("Want to collect ust data");
+
+  /* 'S' + size + string */
+  bufspace = add_traceframe_block (tframe,
+				   1 + sizeof (blocklen) + size + 1);
+  if (bufspace == NULL)
+    {
+      trace_debug ("Trace buffer block allocation failed, skipping");
+      return;
+    }
+
+  /* Identify a static trace data block.  */
+  *bufspace = 'S';
+
+  blocklen = size + 1;
+  memcpy (bufspace + 1, &blocklen, sizeof (blocklen));
+
+  va_copy (copy, *umd->args);
+  USTF(serialize_to_text) ((char *) bufspace + 1 + sizeof (blocklen),
+			   size + 1, umd->fmt, copy);
+  va_end (copy);
+
+  trace_debug ("Storing static tracepoint data in regblock: %s",
+	       bufspace + 1 + sizeof (blocklen));
+}
+
+/* The probe to register with lttng/ust.  */
+static struct ltt_available_probe gdb_ust_probe =
+  {
+    GDB_PROBE_NAME,
+    NULL,
+    gdb_probe,
+  };
+
+#endif /* HAVE_UST */
+#endif /* IN_PROCESS_AGENT */
+
+#ifdef HAVE_UST
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
+#endif
+
+/* Where we put the socked used for synchronization.  */
+#define SOCK_DIR P_tmpdir
+
+#endif /* HAVE_UST */
+
+#ifndef IN_PROCESS_AGENT
+
+#ifdef HAVE_UST
+
+static int
+gdb_ust_connect_sync_socket (int pid)
+{
+  struct sockaddr_un addr;
+  int res, fd;
+  char path[UNIX_PATH_MAX];
+
+  res = snprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", SOCK_DIR, pid);
+  if (res >= UNIX_PATH_MAX)
+    {
+      trace_debug ("string overflow allocating socket name");
+      return -1;
+    }
+
+  res = fd = socket (PF_UNIX, SOCK_STREAM, 0);
+  if (res == -1)
+    {
+      warning ("error opening sync socket: %s\n", strerror (errno));
+      return -1;
+    }
+
+  addr.sun_family = AF_UNIX;
+
+  res = snprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
+  if (res >= UNIX_PATH_MAX)
+    {
+      warning ("string overflow allocating socket name\n");
+      close (fd);
+      return -1;
+    }
+
+  res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
+  if (res == -1)
+    {
+      warning ("error connecting sync socket (%s): %s. "
+	       "Make sure the directory exists and that it is writable.",
+	       path, strerror (errno));
+      close (fd);
+      return -1;
+    }
+
+  return fd;
+}
+
+/* Resume thread PTID.  */
+
+static void
+resume_thread (ptid_t ptid)
+{
+  struct thread_resume resume_info;
+
+  resume_info.thread = ptid;
+  resume_info.kind = resume_continue;
+  resume_info.sig = TARGET_SIGNAL_0;
+  (*the_target->resume) (&resume_info, 1);
+}
+
+/* Stop thread PTID.  */
+
+static void
+stop_thread (ptid_t ptid)
+{
+  struct thread_resume resume_info;
+
+  resume_info.thread = ptid;
+  resume_info.kind = resume_stop;
+  resume_info.sig = TARGET_SIGNAL_0;
+  (*the_target->resume) (&resume_info, 1);
+}
+
+/* Ask the in-process agent to run a command.  Since we don't want to
+   have to handle the IPA hitting breakpoints while running the
+   command, we pause all threads, remove all breakpoints, and then set
+   the helper thread re-running.  We communicate with the helper
+   thread by means of direct memory xfering, and a socket for
+   synchronization.  */
+
+static int
+run_inferior_command (char *cmd)
+{
+  int err = -1;
+  int fd = -1;
+  int pid = ptid_get_pid (current_inferior->entry.id);
+  int tid;
+  ptid_t ptid = null_ptid;
+
+  trace_debug ("run_inferior_command: running: %s", cmd);
+
+  pause_all (0);
+  uninsert_all_breakpoints ();
+
+  if (read_inferior_integer (ipa_sym_addrs.addr_helper_thread_id, &tid))
+    {
+      warning ("Error reading helper thread's id in lib");
+      goto out;
+    }
+
+  if (tid == 0)
+    {
+      warning ("helper thread not initialized yet");
+      goto out;
+    }
+
+  if (write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
+			     (unsigned char *) cmd, strlen (cmd) + 1))
+    {
+      warning ("Error writing command");
+      goto out;
+    }
+
+  ptid = ptid_build (pid, tid, 0);
+
+  resume_thread (ptid);
+
+  fd = gdb_ust_connect_sync_socket (pid);
+  if (fd >= 0)
+    {
+      char buf[1] = "";
+      int ret;
+
+      trace_debug ("signalling helper thread");
+
+      do
+	{
+	  ret = write (fd, buf, 1);
+	} while (ret == -1 && errno == EINTR);
+
+      trace_debug ("waiting for helper thread's response");
+
+      do
+	{
+	  ret = read (fd, buf, 1);
+	} while (ret == -1 && errno == EINTR);
+
+      close (fd);
+
+      trace_debug ("helper thread's response received");
+    }
+
+ out:
+
+  /* Need to read response with the inferior stopped.  */
+  if (!ptid_equal (ptid, null_ptid))
+    {
+      int was_non_stop = non_stop;
+      struct target_waitstatus status;
+
+      stop_thread (ptid);
+      non_stop = 1;
+      mywait (ptid, &status, 0, 0);
+      non_stop = was_non_stop;
+    }
+
+  if (fd >= 0)
+    {
+      if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
+				(unsigned char *) cmd, CMD_BUF_SIZE))
+	{
+	  warning ("Error reading command response");
+	}
+      else
+	{
+	  err = 0;
+	  trace_debug ("run_inferior_command: response: %s", cmd);
+	}
+    }
+
+  reinsert_all_breakpoints ();
+  unpause_all (0);
+
+  return err;
+}
+
+#else /* HAVE_UST */
+
+static int
+run_inferior_command (char *cmd)
+{
+  return -1;
+}
+
+#endif /* HAVE_UST */
+
+#else /* !IN_PROCESS_AGENT */
+
+/* Thread ID of the helper thread.  GDBserver reads this to know which
+   is the help thread.  This is an LWP id on Linux.  */
+int helper_thread_id;
+
+#ifdef HAVE_UST
+
+static int
+init_named_socket (const char *name)
+{
+  int result, fd;
+  struct sockaddr_un addr;
+
+  result = fd = socket (PF_UNIX, SOCK_STREAM, 0);
+  if (result == -1)
+    {
+      warning ("socket creation failed: %s", strerror (errno));
+      return -1;
+    }
+
+  addr.sun_family = AF_UNIX;
+
+  strncpy (addr.sun_path, name, UNIX_PATH_MAX);
+  addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
+
+  result = access (name, F_OK);
+  if (result == 0)
+    {
+      /* File exists.  */
+      result = unlink (name);
+      if (result == -1)
+	{
+	  warning ("unlink failed: %s", strerror (errno));
+	  close (fd);
+	  return -1;
+	}
+      warning ("socket %s already exists; overwriting", name);
+    }
+
+  result = bind (fd, (struct sockaddr *) &addr, sizeof (addr));
+  if (result == -1)
+    {
+      warning ("bind failed: %s", strerror (errno));
+      close (fd);
+      return -1;
+    }
+
+  result = listen (fd, 1);
+  if (result == -1)
+    {
+      warning ("listen: %s", strerror (errno));
+      close (fd);
+      return -1;
+    }
+
+  return fd;
+}
+
+static int
+gdb_ust_socket_init (void)
+{
+  int result, fd;
+  char name[UNIX_PATH_MAX];
+
+  result = snprintf (name, UNIX_PATH_MAX, "%s/gdb_ust%d",
+		     SOCK_DIR, getpid ());
+  if (result >= UNIX_PATH_MAX)
+    {
+      trace_debug ("string overflow allocating socket name");
+      return -1;
+    }
+
+  fd = init_named_socket (name);
+  if (fd < 0)
+    warning ("Error initializing named socket (%s) for communication with the "
+	     "ust helper thread. Check that directory exists and that it "
+	     "is writable.", name);
+
+  return fd;
+}
+
+/* Return an hexstr version of the STR C string, fit for sending to
+   GDB.  */
+
+static char *
+cstr_to_hexstr (const char *str)
+{
+  int len = strlen (str);
+  char *hexstr = xmalloc (len * 2 + 1);
+  convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
+  return hexstr;
+}
+
+/* The next marker to be returned on a qTsST command.  */
+static const struct marker *next_st;
+
+/* Returns the first known marker.  */
+
+struct marker *
+first_marker (void)
+{
+  struct marker_iter iter;
+
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
+
+  return iter.marker;
+}
+
+/* Returns the marker following M.  */
+
+const struct marker *
+next_marker (const struct marker *m)
+{
+  struct marker_iter iter;
+
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
+
+  for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
+    {
+      if (iter.marker == m)
+	{
+	  USTF(marker_iter_next) (&iter);
+	  return iter.marker;
+	}
+    }
+
+  return NULL;
+}
+
+/* Compose packet that is the response to the qTsSTM/qTfSTM/qTST;at
+   packets.  */
+
+static void
+response_ust_marker (char *packet, const struct marker *st)
+{
+  char *strid, *format, *tmp;
+
+  next_st = next_marker (st);
+
+  tmp = xmalloc (strlen (st->channel) + 1 +
+		 strlen (st->name) + 1);
+  sprintf (tmp, "%s/%s", st->channel, st->name);
+
+  strid = cstr_to_hexstr (tmp);
+  free (tmp);
+
+  format = cstr_to_hexstr (st->format);
+
+  sprintf (packet, "m%s:%s:%s",
+	   paddress ((uintptr_t) st->location),
+	   strid,
+	   format);
+
+  free (strid);
+  free (format);
+}
+
+/* Return the first static tracepoint, and initialize the state
+   machine that will iterate through all the static tracepoints.  */
+
+static void
+cmd_qtfstm (char *packet)
+{
+  trace_debug ("Returning first trace state variable definition");
+
+  if (first_marker ())
+    response_ust_marker (packet, first_marker ());
+  else
+    strcpy (packet, "l");
+}
+
+/* Return additional trace state variable definitions. */
+
+static void
+cmd_qtsstm (char *packet)
+{
+  trace_debug ("Returning static tracepoint");
+
+  if (next_st)
+    response_ust_marker (packet, next_st);
+  else
+    strcpy (packet, "l");
+}
+
+/* Disconnect the GDB probe from a marker at a given address.  */
+
+static void
+unprobe_marker_at (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+
+  p += sizeof ("unprobe_marker_at:") - 1;
+
+  p = unpack_varlen_hex (p, &address);
+
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
+  for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
+    if ((uintptr_t ) iter.marker->location == address)
+      {
+	int result;
+
+	result = USTF(ltt_marker_disconnect) (iter.marker->channel,
+					      iter.marker->name,
+					      GDB_PROBE_NAME);
+	if (result < 0)
+	  warning ("could not disable marker %s/%s",
+		   iter.marker->channel, iter.marker->name);
+	break;
+      }
+}
+
+/* Connect the GDB probe to a marker at a given address.  */
+
+static int
+probe_marker_at (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+  struct marker *m;
+
+  p += sizeof ("probe_marker_at:") - 1;
+
+  p = unpack_varlen_hex (p, &address);
+
+  USTF(marker_iter_reset) (&iter);
+
+  for (USTF(marker_iter_start) (&iter), m = iter.marker;
+       m != NULL;
+       USTF(marker_iter_next) (&iter), m = iter.marker)
+    if ((uintptr_t ) m->location == address)
+      {
+	int result;
+
+	trace_debug ("found marker for address.  "
+		     "ltt_marker_connect (marker = %s/%s)",
+		     m->channel, m->name);
+
+	result = USTF(ltt_marker_connect) (m->channel, m->name, GDB_PROBE_NAME);
+	if (result && result != -EEXIST)
+	  trace_debug ("ltt_marker_connect (marker = %s/%s, errno = %d)",
+		       m->channel, m->name, -result);
+
+	if (result < 0)
+	  {
+	    sprintf (packet, "E.could not connect marker: channel=%s, name=%s",
+		     m->channel, m->name);
+	    return -1;
+	  }
+
+	strcpy (packet, "OK");
+	return 0;
+      }
+
+  sprintf (packet, "E.no marker found at 0x%s", paddress (address));
+  return -1;
+}
+
+static int
+cmd_qtstmat (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+  struct marker *m;
+
+  p += sizeof ("qTSTMat:") - 1;
+
+  p = unpack_varlen_hex (p, &address);
+
+  USTF(marker_iter_reset) (&iter);
+
+  for (USTF(marker_iter_start) (&iter), m = iter.marker;
+       m != NULL;
+       USTF(marker_iter_next) (&iter), m = iter.marker)
+    if ((uintptr_t ) m->location == address)
+      {
+	response_ust_marker (packet, m);
+	return 0;
+      }
+
+  strcpy (packet, "l");
+  return -1;
+}
+
+static void *
+gdb_ust_thread (void *arg)
+{
+  int listen_fd;
+
+  while (1)
+    {
+      listen_fd = gdb_ust_socket_init ();
+
+#ifdef SYS_gettid
+      if (helper_thread_id == 0)
+	helper_thread_id = syscall (SYS_gettid);
+#endif
+
+      if (listen_fd == -1)
+	{
+	  warning ("could not create sync socket\n");
+	  break;
+	}
+
+      while (1)
+	{
+	  socklen_t tmp;
+	  struct sockaddr_un sockaddr;
+	  int fd;
+	  char buf[1];
+	  int ret;
+
+	  tmp = sizeof (sockaddr);
+
+	  do
+	    {
+	      fd = accept (listen_fd, &sockaddr, &tmp);
+	    }
+	  /* It seems an ERESTARTSYS can escape out of accept.  */
+	  while (fd == -512 || (fd == -1 && errno == EINTR));
+
+	  if (fd < 0)
+	    {
+	      warning ("Accept returned %d, error: %s\n",
+		       fd, strerror (errno));
+	      break;
+	    }
+
+	  do
+	    {
+	      ret = read (fd, buf, 1);
+	    } while (ret == -1 && errno == EINTR);
+
+	  if (ret == -1)
+	    {
+	      warning ("reading socket (fd=%d) failed with %s",
+		       fd, strerror (errno));
+	      close (fd);
+	      break;
+	    }
+
+	  if (cmd_buf[0])
+	    {
+	      if (strcmp ("qTfSTM", cmd_buf) == 0)
+		{
+		  cmd_qtfstm (cmd_buf);
+		}
+	      else if (strcmp ("qTsSTM", cmd_buf) == 0)
+		{
+		  cmd_qtsstm (cmd_buf);
+		}
+	      else if (strncmp ("unprobe_marker_at:",
+				cmd_buf,
+				sizeof ("unprobe_marker_at:") - 1) == 0)
+		{
+		  unprobe_marker_at (cmd_buf);
+		}
+	      else if (strncmp ("probe_marker_at:",
+				cmd_buf,
+				sizeof ("probe_marker_at:") - 1) == 0)
+		{
+		  probe_marker_at (cmd_buf);
+		}
+	      else if (strncmp ("qTSTMat:",
+				cmd_buf,
+				sizeof ("qTSTMat:") - 1) == 0)
+		{
+		  cmd_qtstmat (cmd_buf);
+		}
+	      else if (strcmp (cmd_buf, "help") == 0)
+		{
+		  strcpy (cmd_buf, "for help, press F1\n");
+		}
+	      else
+		strcpy (cmd_buf, "");
+	    }
+
+	  write (fd, buf, 1);
+	  close (fd);
+	}
+    }
+
+  return NULL;
+}
+
+#include <signal.h>
+
+static void
+gdb_ust_init (void)
+{
+  int res;
+  pthread_t thread;
+  sigset_t new_mask;
+  sigset_t orig_mask;
+
+  if (!dlsym_ust ())
+    return;
+
+  /* We want the helper thread to be as transparent as possible, so
+     have it inherit an all-signals-blocked mask.  */
+
+  sigfillset (&new_mask);
+  res = pthread_sigmask (SIG_SETMASK, &new_mask, &orig_mask);
+  if (res)
+    fatal ("pthread_sigmask (1) failed: %s", strerror (res));
+
+  res = pthread_create (&thread,
+			NULL,
+			gdb_ust_thread,
+			NULL);
+
+  res = pthread_sigmask (SIG_SETMASK, &orig_mask, NULL);
+  if (res)
+    fatal ("pthread_sigmask (2) failed: %s", strerror (res));
+
+  while (helper_thread_id == 0)
+    usleep (1);
+
+  USTF(ltt_probe_register) (&gdb_ust_probe);
+}
+
+#endif /* HAVE_UST */
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+IP_AGENT_EXPORT char *gdb_tp_heap_buffer;
+IP_AGENT_EXPORT char *gdb_jump_pad_buffer;
+IP_AGENT_EXPORT char *gdb_jump_pad_buffer_end;
+
+static void __attribute__ ((constructor))
+initialize_tracepoint_ftlib (void)
+{
+  initialize_tracepoint ();
+
+#ifdef HAVE_UST
+  gdb_ust_init ();
+#endif
+}
+
+#endif /* IN_PROCESS_AGENT */
 
 static LONGEST
 tsv_get_timestamp (void)
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/breakpoint.c	2010-06-28 13:23:58.000000000 +0100
@@ -837,7 +837,9 @@ check_no_tracepoint_commands (struct com
 int
 is_tracepoint (const struct breakpoint *b)
 {
-  return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
+  return (b->type == bp_tracepoint
+	  || b->type == bp_fast_tracepoint
+	  || b->type == bp_static_tracepoint);
 }
   
 /* A helper function that validsates that COMMANDS are valid for a
@@ -861,7 +863,11 @@ validate_commands_for_breakpoint (struct
 	  if (c->control_type == while_stepping_control)
 	    {
 	      if (b->type == bp_fast_tracepoint)
-		error (_("The 'while-stepping' command cannot be used for fast tracepoint"));
+		error (_("\
+The 'while-stepping' command cannot be used for fast tracepoint"));
+	      else if (b->type == bp_static_tracepoint)
+		error (_("\
+The 'while-stepping' command cannot be used for static tracepoint"));
 
 	      if (while_stepping)
 		error (_("The 'while-stepping' command can be used only once"));
@@ -888,6 +894,27 @@ validate_commands_for_breakpoint (struct
     }
 }
 
+/* Return a vector of all the static tracepoints set at ADDR.  The
+   caller is responsible for releasing the vector.  */
+
+VEC(breakpoint_p) *
+static_tracepoints_here (CORE_ADDR addr)
+{
+  struct breakpoint *b;
+  VEC(breakpoint_p) *found = 0;
+  struct bp_location *loc;
+
+  ALL_BREAKPOINTS (b)
+    if (b->type == bp_static_tracepoint)
+      {
+	for (loc = b->loc; loc; loc = loc->next)
+	  if (loc->address == addr)
+	    VEC_safe_push(breakpoint_p, found, b);
+      }
+
+  return found;
+}
+
 /* Set the command list of B to COMMANDS.  If breakpoint is tracepoint,
    validate that only allowed commands are included.
 */
@@ -4420,6 +4447,7 @@ bpstat_what (bpstat bs)
 	  break;
 	case bp_tracepoint:
 	case bp_fast_tracepoint:
+	case bp_static_tracepoint:
 	  /* Tracepoint hits should not be reported back to GDB, and
 	     if one got through somehow, it should have been filtered
 	     out already.  */
@@ -4553,6 +4581,7 @@ print_one_breakpoint_location (struct br
     {bp_catchpoint, "catchpoint"},
     {bp_tracepoint, "tracepoint"},
     {bp_fast_tracepoint, "fast tracepoint"},
+    {bp_static_tracepoint, "static tracepoint"},
     {bp_jit_event, "jit events"},
   };
   
@@ -4685,6 +4714,7 @@ print_one_breakpoint_location (struct br
       case bp_std_terminate_master:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_jit_event:
 	if (opts.addressprint)
 	  {
@@ -4755,6 +4785,16 @@ print_one_breakpoint_location (struct br
   
   ui_out_text (uiout, "\n");
   
+  if (!part_of_multiple && b->static_trace_id)
+    {
+      gdb_assert (b->type == bp_static_tracepoint);
+
+      ui_out_text (uiout, "\tstatic tracepoint marker id is ");
+      ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
+			   b->static_trace_id);
+      ui_out_text (uiout, "\n");
+    }
+
   if (part_of_multiple && frame_id_p (b->frame_id))
     {
       annotate_field (6);
@@ -5411,6 +5451,7 @@ allocate_bp_location (struct breakpoint 
     case bp_catchpoint:
     case bp_tracepoint:
     case bp_fast_tracepoint:
+    case bp_static_tracepoint:
       loc->loc_type = bp_loc_other;
       break;
     default:
@@ -6787,6 +6828,16 @@ mention (struct breakpoint *b)
 	printf_filtered (_(" %d"), b->number);
 	say_where = 1;
 	break;
+      case bp_static_tracepoint:
+	if (ui_out_is_mi_like_p (uiout))
+	  {
+	    say_where = 0;
+	    break;
+	  }
+	printf_filtered (_("Static tracepoint"));
+	printf_filtered (_(" %d"), b->number);
+	say_where = 1;
+	break;
 
       case bp_until:
       case bp_finish:
@@ -6966,9 +7017,25 @@ create_breakpoint_sal (struct gdbarch *g
 	  b->ignore_count = ignore_count;
 	  b->enable_state = enabled ? bp_enabled : bp_disabled;
 	  b->disposition = disposition;
-
 	  b->pspace = sals.sals[0].pspace;
 
+	  if (type == bp_static_tracepoint)
+	    {
+	      struct static_tracepoint_marker marker;
+
+	      if (target_static_tracepoint_marker_at (sal.pc, &marker))
+		{
+		  b->static_trace_id = xstrdup (marker.str_id);
+		  release_static_tracepoint_marker (&marker);
+
+		  printf_filtered (_("Probed static tracepoint marker \"%s\"\n"),
+				   b->static_trace_id);
+		}
+	      else
+		warning (_("\
+Couldn't determine the static tracepoint marker to probe"));
+	    }
+
 	  if (enabled && b->pspace->executing_startup
 	      && (b->type == bp_breakpoint
 		  || b->type == bp_hardware_breakpoint))
@@ -7381,6 +7448,49 @@ find_condition_and_thread (char *tok, CO
     }
 }
 
+/* Decode a static tracepoint marker spec.  */
+
+static struct symtabs_and_lines
+decode_static_tracepoint_spec (char **arg_p)
+{
+  struct static_tracepoint_marker stmarker;
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  struct symbol *sym;
+  struct cleanup *old_chain;
+  char *p = &(*arg_p)[3];
+  char *endp;
+  char *marker;
+
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  endp = p;
+  while (*endp != ' ' && *endp != '\t' && *endp != '\0')
+    endp++;
+
+  marker = savestring (p, endp - p);
+  old_chain = make_cleanup (xfree, marker);
+
+  if (!target_static_tracepoint_marker_by_strid (marker, &stmarker))
+    error (_("No known static tracepoint marker named %s"), p);
+
+  init_sal (&sal);
+
+  sal.pc = stmarker.address;
+  sal = find_pc_line (stmarker.address, 0);
+
+  sals.nelts = 1;
+  sals.sals = xmalloc (sizeof *sals.sals);
+  sals.sals[0] = sal;
+
+  release_static_tracepoint_marker (&stmarker);
+  do_cleanups (old_chain);
+
+  *arg_p = endp;
+  return sals;
+}
+
 /* Set a breakpoint.  This function is shared between CLI and MI
    functions for setting a breakpoint.  This function has two major
    modes of operations, selected by the PARSE_CONDITION_AND_THREAD
@@ -7394,7 +7504,7 @@ int
 create_breakpoint (struct gdbarch *gdbarch,
 		   char *arg, char *cond_string, int thread,
 		   int parse_condition_and_thread,
-		   int tempflag, int hardwareflag, int traceflag,
+		   int tempflag, enum bptype type_wanted,
 		   int ignore_count,
 		   enum auto_boolean pending_break_support,
 		   struct breakpoint_ops *ops,
@@ -7413,7 +7523,6 @@ create_breakpoint (struct gdbarch *gdbar
   int i;
   int pending = 0;
   int not_found = 0;
-  enum bptype type_wanted;
   int task = 0;
   int prev_bkpt_count = breakpoint_count;
 
@@ -7426,6 +7535,18 @@ create_breakpoint (struct gdbarch *gdbar
   parse_args.addr_string_p = &addr_string;
   parse_args.not_found_ptr = &not_found;
 
+  if (type_wanted == bp_static_tracepoint
+      && (strncmp (arg, "-m", 2) == 0
+	  && (arg[2] == ' ' || arg[2] == '\t')))
+    {
+      sals = decode_static_tracepoint_spec (&arg);
+
+      copy_arg = savestring (addr_start, arg - addr_start);
+      addr_string = xmalloc (sizeof (char **));
+      addr_string[0] = copy_arg;
+      goto done;
+    }
+
   e = catch_exception (uiout, do_captured_parse_breakpoint, 
 		       &parse_args, RETURN_MASK_ALL);
 
@@ -7472,6 +7593,8 @@ create_breakpoint (struct gdbarch *gdbar
 	return 0;
     }
 
+  done:
+
   /* Create a chain of things that always need to be cleaned up. */
   old_chain = make_cleanup (null_cleanup, 0);
 
@@ -7503,10 +7626,6 @@ create_breakpoint (struct gdbarch *gdbar
   if (!pending)
     breakpoint_sals_to_pc (&sals, addr_start);
 
-  type_wanted = (traceflag
-		 ? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint)
-		 : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
-
   /* Fast tracepoints may have additional restrictions on location.  */
   if (type_wanted == bp_fast_tracepoint)
     check_fast_tracepoint_sals (gdbarch, &sals);
@@ -7599,13 +7718,15 @@ create_breakpoint (struct gdbarch *gdbar
 static void
 break_command_1 (char *arg, int flag, int from_tty)
 {
-  int hardwareflag = flag & BP_HARDWAREFLAG;
   int tempflag = flag & BP_TEMPFLAG;
+  enum bptype type_wanted = (flag & BP_HARDWAREFLAG
+			     ? bp_hardware_breakpoint
+			     : bp_breakpoint);
 
   create_breakpoint (get_current_arch (),
 		     arg,
 		     NULL, 0, 1 /* parse arg */,
-		     tempflag, hardwareflag, 0 /* traceflag */,
+		     tempflag, type_wanted,
 		     0 /* Ignore count */,
 		     pending_break_support,
 		     NULL /* breakpoint_ops */,
@@ -8578,7 +8699,7 @@ handle_gnu_v3_exceptions (int tempflag, 
   create_breakpoint (get_current_arch (),
 		     trigger_func_name, cond_string, -1,
 		     0 /* condition and thread are valid.  */,
-		     tempflag, 0, 0,
+		     tempflag, bp_breakpoint,
 		     0,
 		     AUTO_BOOLEAN_TRUE /* pending */,
 		     &gnu_v3_exception_catchpoint_ops, from_tty,
@@ -9630,6 +9751,119 @@ ambiguous_names_p (struct bp_location *l
   return 0;
 }
 
+/* When symbols change, it probably means the sources changed as well,
+   and it might mean the static tracepoint markers are no longer at
+   the same address or line numbers they used to be at last we
+   checked.  Losing your static tracepoints whenever you rebuild is
+   undesirable.  This function tries to resync/rematch gdb static
+   tracepoints with the markers on the target.  The heuristic is:
+
+   1) look for a marker at the old PC.  If one is found there, assume
+   to be the same marker.  If the name / string id of the marker found
+   is different from the previous known name, assume that means the
+   user renamed the marker in the sources, and output a warning.
+
+   2) If a marker is no longer found at the same address, it may mean
+   the marker no longer exists.  But it may also just mean the code
+   changed a bit.  Maybe the user added a few lines of code that made
+   the marker move up or down (in line number terms).  Ask the target
+   for info about the marker with the string id as we knew it.  If
+   found, update line number and address in the matching static
+   tracepoint.  */
+
+static struct symtab_and_line
+update_static_tracepoint (struct breakpoint *b,
+			  struct symtab_and_line sal)
+{
+  struct static_tracepoint_marker marker;
+  int i;
+
+  CORE_ADDR pc;
+
+  pc = sal.pc;
+  if (sal.line)
+    find_line_pc (sal.symtab, sal.line, &pc);
+
+  if (target_static_tracepoint_marker_at (pc, &marker))
+    {
+      if (strcmp (b->static_trace_id, marker.str_id) != 0)
+	warning (_("static tracepoint %d changed probed marker from %s to %s"),
+		 b->number,
+		 b->static_trace_id, marker.str_id);
+
+      xfree (b->static_trace_id);
+      b->static_trace_id = xstrdup (marker.str_id);
+      release_static_tracepoint_marker (&marker);
+
+      return sal;
+    }
+
+  /* Old marker wasn't found on target at lineno.  Try looking it up
+     by string ID.  */
+  if (!sal.explicit_pc
+      && sal.line != 0
+      && sal.symtab != NULL
+      && b->static_trace_id != NULL
+      && target_static_tracepoint_marker_by_strid (b->static_trace_id,
+						   &marker))
+    {
+      struct symtab_and_line sal;
+      struct symbol *sym;
+
+      xfree (b->static_trace_id);
+      b->static_trace_id = xstrdup (marker.str_id);
+
+      warning (_("marker for static tracepoint %d (%s) not "
+		 "found at previous line number"),
+	       b->number, b->static_trace_id);
+
+      init_sal (&sal);
+
+      sal.pc = marker.address;
+
+      sal = find_pc_line (marker.address, 0);
+      sym = find_pc_sect_function (marker.address, NULL);
+      ui_out_text (uiout, "Now in ");
+      if (sym)
+	{
+	  ui_out_field_string (uiout, "func",
+			       SYMBOL_PRINT_NAME (sym));
+	  ui_out_text (uiout, " at ");
+	}
+      ui_out_field_string (uiout, "file", sal.symtab->filename);
+      ui_out_text (uiout, ":");
+
+      if (ui_out_is_mi_like_p (uiout))
+	{
+	  char *fullname = symtab_to_fullname (sal.symtab);
+
+	  if (fullname)
+	    ui_out_field_string (uiout, "fullname", fullname);
+	}
+
+      ui_out_field_int (uiout, "line", sal.line);
+      ui_out_text (uiout, "\n");
+
+      b->line_number = sal.line;
+
+      xfree (b->source_file);
+      if (sym)
+	b->source_file = xstrdup (sal.symtab->filename);
+      else
+	b->source_file = NULL;
+
+      xfree (b->addr_string);
+      b->addr_string = xstrprintf ("%s:%d",
+				   sal.symtab->filename, b->line_number);
+
+      /* Might be nice to check if function changed, and warn if
+	 so.  */
+
+      release_static_tracepoint_marker (&marker);
+    }
+  return sal;
+}
+
 static void
 update_breakpoint_locations (struct breakpoint *b,
 			     struct symtabs_and_lines sals)
@@ -9760,6 +9994,7 @@ breakpoint_re_set_one (void *bint)
     case bp_hardware_breakpoint:
     case bp_tracepoint:
     case bp_fast_tracepoint:
+    case bp_static_tracepoint:
       /* Do not attempt to re-set breakpoints disabled during startup.  */
       if (b->enable_state == bp_startup_disabled)
 	return 0;
@@ -9780,8 +10015,13 @@ breakpoint_re_set_one (void *bint)
 
       TRY_CATCH (e, RETURN_MASK_ERROR)
 	{
-	  sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
-				not_found_ptr);
+	  if (b->type == bp_static_tracepoint
+	      && (strncmp (s, "-m", 2) == 0
+		  && (s[2] == ' ' || s[2] == '\t')))
+	    sals = decode_static_tracepoint_spec (&s);
+	  else
+	    sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
+				  not_found_ptr);
 	}
       if (e.reason < 0)
 	{
@@ -9831,6 +10071,9 @@ breakpoint_re_set_one (void *bint)
 	      b->condition_not_parsed = 0;
 	    }
 
+	  if (b->type == bp_static_tracepoint)
+	    sals.sals[0] = update_static_tracepoint (b, sals.sals[0]);
+
 	  expanded = expand_line_sal_maybe (sals.sals[0]);
 	}
 
@@ -10183,6 +10426,7 @@ disable_command (char *args, int from_tt
       case bp_breakpoint:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -10283,6 +10527,7 @@ enable_command (char *args, int from_tty
       case bp_breakpoint:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -10583,8 +10828,8 @@ trace_command (char *arg, int from_tty)
   if (create_breakpoint (get_current_arch (),
 			 arg,
 			 NULL, 0, 1 /* parse arg */,
-			 0 /* tempflag */, 0 /* hardwareflag */,
-			 1 /* traceflag */,
+			 0 /* tempflag */,
+			 bp_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
 			 NULL,
@@ -10599,8 +10844,26 @@ ftrace_command (char *arg, int from_tty)
   if (create_breakpoint (get_current_arch (),
 			 arg,
 			 NULL, 0, 1 /* parse arg */,
-			 0 /* tempflag */, 1 /* hardwareflag */,
-			 1 /* traceflag */,
+			 0 /* tempflag */,
+			 bp_fast_tracepoint /* type_wanted */,
+			 0 /* Ignore count */,
+			 pending_break_support,
+			 NULL,
+			 from_tty,
+			 1 /* enabled */))
+    set_tracepoint_count (breakpoint_count);
+}
+
+/* strace command implementation.  Creates a static tracepoint.  */
+
+void
+strace_command (char *arg, int from_tty)
+{
+  if (create_breakpoint (get_current_arch (),
+			 arg,
+			 NULL, 0, 1 /* parse arg */,
+			 0 /* tempflag */,
+			 bp_static_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
 			 NULL,
@@ -10662,8 +10925,7 @@ create_tracepoint_from_upload (struct up
 			  addr_str,
 			  utp->cond_string, -1, 0 /* parse cond/thread */,
 			  0 /* tempflag */,
-			  (utp->type == bp_fast_tracepoint) /* hardwareflag */,
-			  1 /* traceflag */,
+			  utp->type /* type_wanted */,
 			  0 /* Ignore count */,
 			  pending_break_support,
 			  NULL,
@@ -10985,6 +11247,8 @@ save_breakpoints (char *filename, int fr
       {
 	if (tp->type == bp_fast_tracepoint)
 	  fprintf_unfiltered (fp, "ftrace");
+	if (tp->type == bp_static_tracepoint)
+	  fprintf_unfiltered (fp, "strace");
 	else if (tp->type == bp_tracepoint)
 	  fprintf_unfiltered (fp, "trace");
 	else if (tp->type == bp_breakpoint && tp->disposition == disp_del)
@@ -11569,6 +11833,31 @@ BREAK_ARGS_HELP ("ftrace") "\n\
 Do \"help tracepoints\" for info on other tracepoint commands."));
   set_cmd_completer (c, location_completer);
 
+  c = add_com ("strace", class_breakpoint, strace_command, _("\
+Set a static tracepoint at specified line, function or marker.\n\
+\n\
+strace [LOCATION] [if CONDITION]\n\
+LOCATION may be a line number, function name, \"*\" and an address,\n\
+or -m MARKER_ID.\n\
+If a line number is specified, probe the marker at start of code\n\
+for that line.  If a function is specified, probe the marker at start\n\
+of code for that function.  If an address is specified, probe the marker\n\
+at that exact address.  If a marker id is specified, probe the marker\n\
+with that name.  With no LOCATION, uses current execution address of\n\
+the selected stack frame.\n\
+Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
+This collects arbitrary user data passed in the probe point call to the\n\
+tracing library.  You can inspect it when analyzing the trace buffer,\n\
+by printing the $_sdata variable like any other convenience variable.\n\
+\n\
+CONDITION is a boolean expression.\n\
+\n\
+Multiple tracepoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.\n\
+Do \"help tracepoints\" for info on other tracepoint commands."));
+  set_cmd_completer (c, location_completer);
+
   add_info ("tracepoints", tracepoints_info, _("\
 Status of tracepoints, or tracepoint number NUMBER.\n\
 Convenience variable \"$tpnum\" contains the number of the\n\
Index: src/gdb/breakpoint.h
===================================================================
--- src.orig/gdb/breakpoint.h	2010-06-25 12:01:15.000000000 +0100
+++ src/gdb/breakpoint.h	2010-06-25 12:01:29.000000000 +0100
@@ -129,6 +129,7 @@ enum bptype
 
     bp_tracepoint,
     bp_fast_tracepoint,
+    bp_static_tracepoint,
 
     /* Event for JIT compiled code generation or deletion.  */
     bp_jit_event,
@@ -536,6 +537,9 @@ struct breakpoint
 
     /* The number of the tracepoint on the target.  */
     int number_on_target;
+
+    /* The static tracepoint string id, if known.  */
+    char *static_trace_id;
   };
 
 typedef struct breakpoint *breakpoint_p;
@@ -780,6 +784,8 @@ extern void breakpoint_re_set (void);
 
 extern void breakpoint_re_set_thread (struct breakpoint *);
 
+extern struct breakpoint *breakpoints_here_p (CORE_ADDR);
+
 extern struct breakpoint *set_momentary_breakpoint
   (struct gdbarch *, struct symtab_and_line, struct frame_id, enum bptype);
 
@@ -818,7 +824,7 @@ extern void tbreak_command (char *, int)
 extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
 			      char *cond_string, int thread,
 			      int parse_condition_and_thread,
-			      int tempflag, int hardwareflag, int traceflag,
+			      int tempflag, enum bptype wanted_type,
 			      int ignore_count,
 			      enum auto_boolean pending_break_support,
 			      struct breakpoint_ops *ops,
@@ -1040,6 +1046,11 @@ extern VEC(breakpoint_p) *all_tracepoint
 
 extern int is_tracepoint (const struct breakpoint *b);
 
+/* Return a vector of all static tracepoints defined at ADDR.  The
+   vector is newly allocated; the caller should free when done with
+   it.  */
+extern VEC(breakpoint_p) *static_tracepoints_here (CORE_ADDR addr);
+
 /* Function that can be passed to read_command_line to validate
    that each command is suitable for tracepoint command list.  */
 extern void check_tracepoint_command (char *line, void *closure);
Index: src/gdb/gdbserver/config.in
===================================================================
--- src.orig/gdb/gdbserver/config.in	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/config.in	2010-06-25 12:01:29.000000000 +0100
@@ -154,6 +154,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define if UST is available */
+#undef HAVE_UST
+
 /* Checking if errno must be defined */
 #undef MUST_DEFINE_ERRNO
 
Index: src/gdb/gdbserver/configure
===================================================================
--- src.orig/gdb/gdbserver/configure	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/configure	2010-06-25 12:01:29.000000000 +0100
@@ -601,6 +601,8 @@ RDYNAMIC
 REPORT_BUGS_TEXI
 REPORT_BUGS_TO
 PKGVERSION
+ustinc
+ustlibs
 LIBOBJS
 INSTALL_DATA
 INSTALL_SCRIPT
@@ -668,6 +670,9 @@ SHELL'
 ac_subst_files=''
 ac_user_opts='
 enable_option_checking
+with_ust
+with_ust_include
+with_ust_lib
 with_pkgversion
 with_bugurl
 with_libthread_db
@@ -1298,6 +1303,11 @@ if test -n "$ac_init_help"; then
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-ust=PATH       Specify prefix directory for the installed UST package
+                          Equivalent to --with-ust-include=PATH/include
+                          plus --with-ust-lib=PATH/lib
+  --with-ust-include=PATH Specify directory for installed UST include files
+  --with-ust-lib=PATH   Specify the directory for the installed UST library
   --with-pkgversion=PKG   Use PKG in the version string in place of "GDB"
   --with-bugurl=URL       Direct users to URL to report a bug
   --with-libthread-db=PATH
@@ -1747,8 +1757,10 @@ $as_echo "$ac_res" >&6; }
 ac_fn_c_check_decl ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
-$as_echo_n "checking whether $2 is declared... " >&6; }
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
 if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
   $as_echo_n "(cached) " >&6
 else
@@ -1758,8 +1770,12 @@ $4
 int
 main ()
 {
-#ifndef $2
-  (void) $2;
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
 #endif
 
   ;
@@ -3818,6 +3834,86 @@ done
 
 
 
+# Check for UST
+ustlibs=""
+ustinc=""
+
+
+# Check whether --with-ust was given.
+if test "${with_ust+set}" = set; then :
+  withval=$with_ust;
+fi
+
+
+# Check whether --with-ust_include was given.
+if test "${with_ust_include+set}" = set; then :
+  withval=$with_ust_include;
+fi
+
+
+# Check whether --with-ust_lib was given.
+if test "${with_ust_lib+set}" = set; then :
+  withval=$with_ust_lib;
+fi
+
+
+case $with_ust in
+  no)
+    ustlibs=
+    ustinc=
+    ;;
+  "" | yes)
+    ustlibs=" -lust "
+    ustinc=""
+    ;;
+  *)
+    ustlibs="-L$with_ust/lib -lust"
+    ustinc="-I$with_ust/include "
+    ;;
+esac
+if test "x$with_ust_include" != x; then
+  ustinc="-I$with_ust_include "
+fi
+if test "x$with_ust_lib" != x; then
+  ustlibs="-L$with_ust_lib -lust"
+fi
+
+if test "x$with_ust" != "xno"; then
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $ustinc"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ust" >&5
+$as_echo_n "checking for ust... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#define CONFIG_UST_GDB_INTEGRATION
+#include <ust/ust.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; };
+$as_echo "#define HAVE_UST 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }; ustlibs= ; ustinc=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS="$saved_CFLAGS"
+fi
+
+# Flags needed for UST
+
+
+
 old_LIBS="$LIBS"
 LIBS="$LIBS -ldl"
 for ac_func in dladdr
Index: src/gdb/gdbserver/linux-amd64-ipa.c
===================================================================
--- src.orig/gdb/gdbserver/linux-amd64-ipa.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/linux-amd64-ipa.c	2010-06-25 12:34:11.000000000 +0100
@@ -75,6 +75,95 @@ gdb_agent_get_raw_reg (const unsigned ch
   return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
 }
 
+#ifdef HAVE_UST
+
+#include <ust/processor.h>
+
+/* "struct registers" is the UST object type holding the registers at
+   the time of the static tracepoint marker call.  This doesn't
+   contain RIP, but we know what it must have been (the marker
+   address).  */
+
+#define ST_REGENTRY(REG)			\
+  {						\
+    offsetof (struct registers, REG),		\
+    sizeof (((struct registers *) NULL)->REG)	\
+  }
+
+static struct
+{
+  int offset;
+  int size;
+} x86_64_st_collect_regmap[] =
+  {
+    ST_REGENTRY(rax),
+    ST_REGENTRY(rbx),
+    ST_REGENTRY(rcx),
+    ST_REGENTRY(rdx),
+    ST_REGENTRY(rsi),
+    ST_REGENTRY(rdi),
+    ST_REGENTRY(rbp),
+    ST_REGENTRY(rsp),
+    ST_REGENTRY(r8),
+    ST_REGENTRY(r9),
+    ST_REGENTRY(r10),
+    ST_REGENTRY(r11),
+    ST_REGENTRY(r12),
+    ST_REGENTRY(r13),
+    ST_REGENTRY(r14),
+    ST_REGENTRY(r15),
+    { -1, 0 },
+    ST_REGENTRY(rflags),
+    ST_REGENTRY(cs),
+    ST_REGENTRY(ss),
+  };
+
+#define X86_64_NUM_ST_COLLECT_GREGS \
+  (sizeof (x86_64_st_collect_regmap) / sizeof (x86_64_st_collect_regmap[0]))
+
+/* GDB's RIP register number.  */
+#define AMD64_RIP_REGNUM 16
+
+void
+supply_static_tracepoint_registers (struct regcache *regcache,
+				    const unsigned char *buf,
+				    CORE_ADDR pc)
+{
+  int i;
+  unsigned long newpc = pc;
+
+  supply_register (regcache, AMD64_RIP_REGNUM, &newpc);
+
+  for (i = 0; i < X86_64_NUM_ST_COLLECT_GREGS; i++)
+    if (x86_64_st_collect_regmap[i].offset != -1)
+      {
+	switch (x86_64_st_collect_regmap[i].size)
+	  {
+	  case 8:
+	    supply_register (regcache, i,
+			     ((char *) buf)
+			     + x86_64_st_collect_regmap[i].offset);
+	    break;
+	  case 2:
+	    {
+	      unsigned long reg
+		= * (short *) (((char *) buf)
+			       + x86_64_st_collect_regmap[i].offset);
+	      reg &= 0xffff;
+	      supply_register (regcache, i, &reg);
+	    }
+	    break;
+	  default:
+	    internal_error (__FILE__, __LINE__,
+			    "unhandled register size: %d",
+			    x86_64_st_collect_regmap[i].size);
+	    break;
+	  }
+      }
+}
+
+#endif /* HAVE_UST */
+
 /* This is only needed because reg-i386-linux-lib.o references it.  We
    may use it proper at some point.  */
 const char *gdbserver_xmltarget;
Index: src/gdb/gdbserver/linux-i386-ipa.c
===================================================================
--- src.orig/gdb/gdbserver/linux-i386-ipa.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/linux-i386-ipa.c	2010-06-25 12:33:50.000000000 +0100
@@ -110,6 +110,83 @@ gdb_agent_get_raw_reg (unsigned char *ra
     return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
 }
 
+#ifdef HAVE_UST
+
+#include <ust/processor.h>
+
+/* "struct registers" is the UST object type holding the registers at
+   the time of the static tracepoint marker call.  This doesn't
+   contain EIP, but we know what it must have been (the marker
+   address).  */
+
+#define ST_REGENTRY(REG)			\
+  {						\
+    offsetof (struct registers, REG),		\
+    sizeof (((struct registers *) NULL)->REG)	\
+  }
+
+static struct
+{
+  int offset;
+  int size;
+} i386_st_collect_regmap[] =
+  {
+    ST_REGENTRY(eax),
+    ST_REGENTRY(ecx),
+    ST_REGENTRY(edx),
+    ST_REGENTRY(ebx),
+    ST_REGENTRY(esp),
+    ST_REGENTRY(ebp),
+    ST_REGENTRY(esi),
+    ST_REGENTRY(edi),
+    { -1, 0 }, /* eip */
+    ST_REGENTRY(eflags),
+    ST_REGENTRY(cs),
+    ST_REGENTRY(ss),
+  };
+
+#define i386_NUM_ST_COLLECT_GREGS \
+  (sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
+
+void
+supply_static_tracepoint_registers (struct regcache *regcache,
+				    const unsigned char *buf,
+				    CORE_ADDR pc)
+{
+  int i;
+  unsigned int newpc = pc;
+
+  supply_register (regcache, I386_EIP_REGNUM, &newpc);
+
+  for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
+    if (i386_st_collect_regmap[i].offset != -1)
+      {
+	switch (i386_st_collect_regmap[i].size)
+	  {
+	  case 4:
+	    supply_register (regcache, i,
+			     ((char *) buf)
+			     + i386_st_collect_regmap[i].offset);
+	    break;
+	  case 2:
+	    {
+	      unsigned long reg
+		= * (short *) (((char *) buf)
+			       + i386_st_collect_regmap[i].offset);
+	      reg &= 0xffff;
+	      supply_register (regcache, i, &reg);
+	    }
+	    break;
+	  default:
+	    internal_error ("unhandled register size: %d",
+			    i386_st_collect_regmap[i].size);
+	  }
+      }
+}
+
+#endif /* HAVE_UST */
+
+
 /* This is only needed because reg-i386-linux-lib.o references it.  We
    may use it proper at some point.  */
 const char *gdbserver_xmltarget;
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/server.c	2010-06-25 16:36:16.000000000 +0100
@@ -1336,6 +1336,52 @@ handle_query (char *own_buf, int packet_
       return;
     }
 
+  if (strncmp ("qXfer:statictrace:read:", own_buf,
+	       sizeof ("qXfer:statictrace:read:") -1) == 0)
+    {
+      unsigned char *data;
+      CORE_ADDR ofs;
+      unsigned int len;
+      char *annex;
+      ULONGEST nbytes;
+
+      require_running (own_buf);
+
+      if (current_traceframe == -1)
+	{
+	  write_enn (own_buf);
+	  return;
+	}
+
+      /* Reject any annex; grab the offset and length.  */
+      if (decode_xfer_read (own_buf + sizeof ("qXfer:statictrace:read:") -1,
+			    &annex, &ofs, &len) < 0
+	  || annex[0] != '\0')
+	{
+	  strcpy (own_buf, "E00");
+	  return;
+	}
+
+      /* Read one extra byte, as an indicator of whether there is
+	 more.  */
+      if (len > PBUFSIZ - 2)
+	len = PBUFSIZ - 2;
+      data = malloc (len + 1);
+      if (!data)
+	return;
+
+      if (traceframe_read_sdata (current_traceframe, ofs,
+				 data, len + 1, &nbytes))
+	write_enn (own_buf);
+      else if (nbytes > len)
+	*new_packet_len_p = write_qxfer_response (own_buf, data, len, 1);
+      else
+	*new_packet_len_p = write_qxfer_response (own_buf, data, nbytes, 0);
+
+      free (data);
+      return;
+    }
+
   /* Protocol features query.  */
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
@@ -1433,6 +1479,8 @@ handle_query (char *own_buf, int packet_
 	  strcat (own_buf, ";DisconnectedTracing+");
 	  if (gdb_supports_qRelocInsn && target_supports_fast_tracepoints ())
 	    strcat (own_buf, ";FastTracepoints+");
+	  strcat (own_buf, ";StaticTracepoints+");
+	  strcat (own_buf, ";qXfer:statictrace:read+");
 	}
 
       return;
Index: src/gdb/mi/mi-cmd-break.c
===================================================================
--- src.orig/gdb/mi/mi-cmd-break.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/mi/mi-cmd-break.c	2010-06-25 12:01:29.000000000 +0100
@@ -75,6 +75,7 @@ mi_cmd_break_insert (char *command, char
   int enabled = 1;
   int tracepoint = 0;
   struct cleanup *back_to;
+  enum bptype type_wanted;
 
   enum opt
     {
@@ -151,9 +152,21 @@ mi_cmd_break_insert (char *command, char
 
   back_to = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
   mi_can_breakpoint_notify = 1;
+
+  /* Note that to request a fast tracepoint, the client uses the
+     "hardware" flag, although there's nothing of hardware related to
+     fast tracepoints -- one can implement slow tracepoints with
+     hardware breakpoints, but fast tracepoints are always software.
+     "fast" is a misnomer, actually, "jump" would be more appropriate.
+     A simulator or an emulator could conceivably implement fast
+     regular non-jump based tracepoints.  */
+  type_wanted = (tracepoint
+		 ? (hardware ? bp_fast_tracepoint : bp_tracepoint)
+		 : (hardware ? bp_hardware_breakpoint : bp_breakpoint));
+
   create_breakpoint (get_current_arch (), address, condition, thread,
 		     0 /* condition and thread are valid.  */,
-		     temp_p, hardware, tracepoint,
+		     temp_p, type_wanted,
 		     ignore_count,
 		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
 		     NULL, 0, enabled);
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/remote.c	2010-06-26 10:27:30.000000000 +0100
@@ -322,6 +322,9 @@ struct remote_state
   /* True if the stub reports support for fast tracepoints.  */
   int fast_tracepoints;
 
+  /* True if the stub reports support for static tracepoints.  */
+  int static_tracepoints;
+
   /* True if the stub can continue running a trace while GDB is
      disconnected.  */
   int disconnected_tracing;
@@ -1198,6 +1201,7 @@ enum {
   PACKET_qXfer_spu_write,
   PACKET_qXfer_osdata,
   PACKET_qXfer_threads,
+  PACKET_qXfer_statictrace_read,
   PACKET_qGetTIBAddr,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
@@ -1212,6 +1216,7 @@ enum {
   PACKET_qAttached,
   PACKET_ConditionalTracepoints,
   PACKET_FastTracepoints,
+  PACKET_StaticTracepoints,
   PACKET_bc,
   PACKET_bs,
   PACKET_TracepointSource,
@@ -2772,6 +2777,100 @@ remote_threads_extra_info (struct thread
 }
 
 
+static int
+remote_static_tracepoint_marker_at (CORE_ADDR addr,
+				    struct static_tracepoint_marker *marker)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p = rs->buf;
+
+  sprintf (p, "qTSTMat:");
+  p += strlen (p);
+  p += hexnumstr (p, addr);
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  if (*p++ == 'm')
+    {
+      parse_static_tracepoint_marker_definition (p, &p, marker);
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+remote_static_tracepoint_marker_by_strid (const char *strid,
+					  struct static_tracepoint_marker *marker)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p;
+
+  /* Ask for a first packet of static tracepoint marker
+     definition.  */
+  putpkt ("qTfSTM");
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  while (*p++ == 'm')
+    {
+      do
+	{
+	  parse_static_tracepoint_marker_definition (p, &p, marker);
+
+	  if (strcmp (strid, marker->str_id) == 0)
+	    return 1;
+
+	  release_static_tracepoint_marker (marker);
+	}
+      while (*p++ == ',');	/* comma-separated list */
+      /* Ask for another packet of static tracepoint definition.  */
+      putpkt ("qTsSTM");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      p = rs->buf;
+    }
+
+  return 0;
+}
+
+static void
+remote_list_static_tracepoint_markers (void)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p;
+
+  /* Ask for a first packet of static tracepoint definition.  */
+  putpkt ("qTfSTM");
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  while (*p++ == 'm')
+    {
+      do
+	{
+	  struct static_tracepoint_marker marker;
+
+	  parse_static_tracepoint_marker_definition (p, &p, &marker);
+	  print_one_static_tracepoint_marker (&marker);
+	  release_static_tracepoint_marker (&marker);
+	}
+      while (*p++ == ',');	/* comma-separated list */
+      /* Ask for another packet of static tracepoint definition.  */
+      putpkt ("qTsSTM");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      p = rs->buf;
+    }
+}
+
+
 /* Implement the to_get_ada_task_ptid function for the remote targets.  */
 
 static ptid_t
@@ -3552,6 +3651,16 @@ remote_fast_tracepoint_feature (const st
 }
 
 static void
+remote_static_tracepoint_feature (const struct protocol_feature *feature,
+				  enum packet_support support,
+				  const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  rs->static_tracepoints = (support == PACKET_ENABLE);
+}
+
+static void
 remote_disconnected_tracing_feature (const struct protocol_feature *feature,
 				     enum packet_support support,
 				     const char *value)
@@ -3593,6 +3702,8 @@ static struct protocol_feature remote_pr
     PACKET_ConditionalTracepoints },
   { "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
     PACKET_FastTracepoints },
+  { "StaticTracepoints", PACKET_DISABLE, remote_static_tracepoint_feature,
+    PACKET_StaticTracepoints },
   { "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature,
     -1 },
   { "ReverseContinue", PACKET_DISABLE, remote_supported_packet,
@@ -8046,6 +8157,16 @@ remote_xfer_partial (struct target_ops *
 				   [PACKET_qXfer_siginfo_write]);
     }
 
+  if (object == TARGET_OBJECT_STATIC_TRACE_DATA)
+    {
+      if (readbuf)
+	return remote_read_qxfer (ops, "statictrace", annex, readbuf, offset, len,
+				  &remote_protocol_packets
+				  [PACKET_qXfer_statictrace_read]);
+      else
+	return -1;
+    }
+
   /* Only handle flash writes.  */
   if (writebuf != NULL)
     {
@@ -9478,6 +9599,14 @@ remote_supports_fast_tracepoints (void)
   return rs->fast_tracepoints;
 }
 
+static int
+remote_supports_static_tracepoints (void)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return rs->static_tracepoints;
+}
+
 static void
 remote_trace_init (void)
 {
@@ -9606,6 +9735,25 @@ remote_download_tracepoint (struct break
 	       give up on the trace run.  */
 	    warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
 	}
+      else if (t->type == bp_static_tracepoint)
+	{
+	  /* Only test for support at download time; we may not know
+	     target capabilities at definition time.  */
+	  if (remote_supports_static_tracepoints ())
+	    {
+	      struct static_tracepoint_marker marker;
+
+	      if (target_static_tracepoint_marker_at (tpaddr, &marker))
+		strcat (buf, ":S");
+	      else
+		error ("Static tracepoint not valid during download");
+	    }
+	  else
+	    /* Fast tracepoints are functionally identical to regular
+	       tracepoints, so don't take lack of support as a reason
+	       to give up on the trace run.  */
+	    error (_("Target does not support static tracepoints"));
+	}
       /* If the tracepoint has a conditional, make it into an agent
 	 expression and append to the definition.  */
       if (loc->cond)
@@ -10101,6 +10249,12 @@ Specify the serial device it is connecte
   remote_ops.to_verify_memory = remote_verify_memory;
   remote_ops.to_get_tib_address = remote_get_tib_address;
   remote_ops.to_set_permissions = remote_set_permissions;
+  remote_ops.to_list_static_tracepoint_markers
+    = remote_list_static_tracepoint_markers;
+  remote_ops.to_static_tracepoint_marker_at
+    = remote_static_tracepoint_marker_at;
+  remote_ops.to_static_tracepoint_marker_by_strid
+    = remote_static_tracepoint_marker_by_strid;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -10579,6 +10733,12 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QAllow],
 			 "QAllow", "allow", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_StaticTracepoints],
+			 "StaticTracepoints", "static-tracepoints", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_statictrace_read],
+                         "qXfer:statictrace:read", "read-sdata-object", 0);
+
   /* Keep the old ``set remote Z-packet ...'' working.  Each individual
      Z sub-packet has its own set and show commands, but users may
      have sets to this variable in their .gdbinit files (or in their
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/target.c	2010-06-25 12:01:29.000000000 +0100
@@ -679,6 +679,9 @@ update_current_target (void)
       INHERIT (to_set_circular_trace_buffer, t);
       INHERIT (to_get_tib_address, t);
       INHERIT (to_set_permissions, t);
+      INHERIT (to_list_static_tracepoint_markers, t);
+      INHERIT (to_static_tracepoint_marker_at, t);
+      INHERIT (to_static_tracepoint_marker_by_strid, t);
       INHERIT (to_magic, t);
       /* Do not inherit to_memory_map.  */
       /* Do not inherit to_flash_erase.  */
@@ -878,6 +881,15 @@ update_current_target (void)
   de_fault (to_set_permissions,
 	    (void (*) (void))
 	    target_ignore);
+  de_fault (to_list_static_tracepoint_markers,
+	    (void (*) (void))
+	    target_ignore);
+  de_fault (to_static_tracepoint_marker_at,
+	    (int (*) (CORE_ADDR, struct static_tracepoint_marker *))
+	    return_zero);
+  de_fault (to_static_tracepoint_marker_by_strid,
+	    (int (*) (const char *, struct static_tracepoint_marker *))
+	    return_zero);
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/target.h	2010-06-25 12:01:29.000000000 +0100
@@ -35,6 +35,7 @@ struct trace_state_variable;
 struct trace_status;
 struct uploaded_tsv;
 struct uploaded_tp;
+struct static_tracepoint_marker;
 
 /* This include file defines the interface between the main part
    of the debugger, and the part which is target-specific, or
@@ -261,6 +262,8 @@ enum target_object
   TARGET_OBJECT_SIGNAL_INFO,
   /* The list of threads that are being debugged.  */
   TARGET_OBJECT_THREADS,
+  /* Collected static trace data.  */
+  TARGET_OBJECT_STATIC_TRACE_DATA,
   /* Possible future objects: TARGET_OBJECT_FILE, ... */
 };
 
@@ -689,6 +692,21 @@ struct target_ops
     /* Send the new settings of write permission variables.  */
     void (*to_set_permissions) (void);
 
+    /* List static tracepoint markers in the target.  Should call
+       print_one_static_tracepoint_marker for each marker.  */
+    void (*to_list_static_tracepoint_markers) (void);
+
+    /* Look for a static tracepoint marker at ADDR, and fill in MARKER
+       with its details.  Return 1 on success, 0 on failure.  */
+    int (*to_static_tracepoint_marker_at) (CORE_ADDR,
+					   struct static_tracepoint_marker *marker);
+
+    /* Look for a static tracepoint marker with string id ID, and fill
+       in MARKER with its details.  Return 1 on success, 0 on
+       failure.  */
+    int (*to_static_tracepoint_marker_by_strid) (const char *id,
+						 struct static_tracepoint_marker *marker);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -1384,6 +1402,15 @@ extern int target_search_memory (CORE_AD
 #define target_set_permissions() \
   (*current_target.to_set_permissions) ()
 
+#define target_list_static_tracepoint_markers() \
+  (*current_target.to_list_static_tracepoint_markers) ()
+
+#define target_static_tracepoint_marker_at(addr, marker) \
+  (*current_target.to_static_tracepoint_marker_at) (addr, marker)
+
+#define target_static_tracepoint_marker_by_strid(marker_id, marker) \
+  (*current_target.to_static_tracepoint_marker_by_strid) (marker_id, marker)
+
 /* Command logging facility.  */
 
 #define target_log_command(p)						\
Index: src/gdb/tracepoint.c
===================================================================
--- src.orig/gdb/tracepoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/tracepoint.c	2010-06-28 13:23:58.000000000 +0100
@@ -47,7 +47,7 @@
 #include "stack.h"
 #include "gdbcore.h"
 #include "remote.h"
-
+#include "source.h"
 #include "ax.h"
 #include "ax-gdb.h"
 
@@ -622,9 +622,10 @@ validate_actionline (char **line, struct
 
 	  if (*p == '$')	/* look for special pseudo-symbols */
 	    {
-	      if ((0 == strncasecmp ("reg", p + 1, 3)) ||
-		  (0 == strncasecmp ("arg", p + 1, 3)) ||
-		  (0 == strncasecmp ("loc", p + 1, 3)))
+	      if (0 == strncasecmp ("reg", p + 1, 3)
+		  || 0 == strncasecmp ("arg", p + 1, 3)
+		  || 0 == strncasecmp ("loc", p + 1, 3)
+		  || 0 == strncasecmp ("_sdata", p + 1, 6))
 		{
 		  p = strchr (p, ',');
 		  continue;
@@ -747,6 +748,9 @@ struct collection_list
     long next_aexpr_elt;
     struct agent_expr **aexpr_list;
 
+    /* True is the user requested a collection of "$_sdata", "static
+       tracepoint data".  */
+    int strace_data;
   }
 tracepoint_list, stepping_list;
 
@@ -1086,6 +1090,14 @@ add_local_symbols (struct collection_lis
     }
 }
 
+static void
+add_static_trace_data (struct collection_list *collection)
+{
+  if (info_verbose)
+    printf_filtered ("collect static trace data\n");
+  collection->strace_data = 1;
+}
+
 /* worker function */
 static void
 clear_collection_list (struct collection_list *list)
@@ -1100,6 +1112,7 @@ clear_collection_list (struct collection
     }
   list->next_aexpr_elt = 0;
   memset (list->regs_mask, 0, sizeof (list->regs_mask));
+  list->strace_data = 0;
 }
 
 /* reduce a collection list to string form (for gdb protocol) */
@@ -1114,9 +1127,19 @@ stringify_collection_list (struct collec
   char *end;
   long i;
 
-  count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
+  count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
   str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
 
+  if (list->strace_data)
+    {
+      if (info_verbose)
+	printf_filtered ("\nCollecting static trace data\n");
+      end = temp_buf;
+      *end++ = 'L';
+      (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
+      ndx++;
+    }
+
   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
     if (list->regs_mask[i] != 0)	/* skip leading zeroes in regs_mask */
       break;
@@ -1276,6 +1299,11 @@ encode_actions_1 (struct command_line *a
 				     'L');
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
+	      else if (0 == strncasecmp ("$_sdata", action_exp, 7))
+		{
+		  add_static_trace_data (collect);
+		  action_exp = strchr (action_exp, ',');	/* more? */
+		}
 	      else
 		{
 		  unsigned long addr, len;
@@ -3476,6 +3504,11 @@ parse_tracepoint_definition (char *line,
 	      p++;
 	      p = unpack_varlen_hex (p, &orig_size);
 	    }
+	  else if (*p == 'S')
+	    {
+	      type = bp_static_tracepoint;
+	      p++;
+	    }
 	  else if (*p == 'X')
 	    {
 	      p++;
@@ -4075,12 +4108,239 @@ init_tfile_ops (void)
   tfile_ops.to_magic = OPS_MAGIC;
 }
 
+/* Given a line of text defining a static tracepoint marker, parse it
+   into a "static tracepoint marker" object.  Throws an error is
+   parsing fails.  If PP is non-null, it points to one past the end of
+   the parsed marker definition.  */
+
+void
+parse_static_tracepoint_marker_definition (char *line, char **pp,
+					   struct static_tracepoint_marker *marker)
+{
+  char *p, *endp;
+  ULONGEST addr;
+  int end;
+
+  p = line;
+  p = unpack_varlen_hex (p, &addr);
+  p++;  /* skip a colon */
+
+  marker->gdbarch = target_gdbarch;
+  marker->address = (CORE_ADDR) addr;
+
+  endp = strchr (p, ':');
+  if (endp == NULL)
+    error ("bad marker definition: %s", line);
+
+  marker->str_id = xmalloc (endp - p + 1);
+  end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2);
+  marker->str_id[end] = '\0';
+
+  p += 2 * end;
+  p++;  /* skip a colon */
+
+  marker->extra = xmalloc (strlen (p) + 1);
+  end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2);
+  marker->extra[end] = '\0';
+
+  if (pp)
+    *pp = p;
+}
+
+/* Release a static tracepoint marker's contents.  Note that the
+   object itself isn't released here.  There objects are usually on
+   the stack.  */
+
+void
+release_static_tracepoint_marker (struct static_tracepoint_marker *marker)
+{
+  xfree (marker->str_id);
+  marker->str_id = NULL;
+}
+
+/* Print MARKER to gdb_stdout.  */
+
+void
+print_one_static_tracepoint_marker (struct static_tracepoint_marker *marker)
+{
+  struct command_line *l;
+  struct symbol *sym;
+
+  char wrap_indent[80];
+  struct ui_stream *stb = ui_out_stream_new (uiout);
+  struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
+  struct cleanup *bkpt_chain;
+  VEC(breakpoint_p) *tracepoints;
+
+  struct symtab_and_line sal;
+
+  init_sal (&sal);
+
+  sal.pc = marker->address;
+
+  tracepoints = static_tracepoints_here (marker->address);
+
+  bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker");
+
+  ui_out_field_fmt (uiout, "enabled", "%c",
+		    !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
+  ui_out_spaces (uiout, 2);
+
+  strcpy (wrap_indent, "                           ");
+  if (gdbarch_addr_bit (marker->gdbarch) <= 32)
+    strcat (wrap_indent, "           ");
+  else
+    strcat (wrap_indent, "                   ");
+
+  ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address);
+
+  sal = find_pc_line (marker->address, 0);
+  sym = find_pc_sect_function (marker->address, NULL);
+  if (sym)
+    {
+      ui_out_text (uiout, "in ");
+      ui_out_field_string (uiout, "func",
+			   SYMBOL_PRINT_NAME (sym));
+      ui_out_wrap_hint (uiout, wrap_indent);
+      ui_out_text (uiout, " at ");
+    }
+  else
+    ui_out_field_skip (uiout, "func");
+
+  if (sal.symtab != NULL)
+    {
+      ui_out_field_string (uiout, "file", sal.symtab->filename);
+      ui_out_text (uiout, ":");
+
+      if (ui_out_is_mi_like_p (uiout))
+	{
+	  char *fullname = symtab_to_fullname (sal.symtab);
+
+	  if (fullname)
+	    ui_out_field_string (uiout, "fullname", fullname);
+	}
+      else
+	ui_out_field_skip (uiout, "fullname");
+
+      ui_out_field_int (uiout, "line", sal.line);
+    }
+  else
+    {
+      ui_out_field_skip (uiout, "fullname");
+      ui_out_field_skip (uiout, "line");
+    }
+  ui_out_text (uiout, "\n");
+
+  ui_out_text (uiout, _("     ID: "));
+  ui_out_field_string (uiout, "string-id", marker->str_id);
+  ui_out_text (uiout, "\n");
+
+  ui_out_text (uiout, _("     Data: "));
+  ui_out_field_string (uiout, "extra-data", marker->extra);
+  ui_out_text (uiout, "\n");
+
+  if (!VEC_empty (breakpoint_p, tracepoints))
+    {
+      struct cleanup *cleanup_chain;
+      int ix;
+      struct breakpoint *b;
+
+      cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout,
+							   "tracepoints-at");
+
+      ui_out_text (uiout, _("     Probed by static tracepoints: "));
+      for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
+	{
+	  if (ix > 0)
+	    ui_out_text (uiout, ", ");
+	  ui_out_text (uiout, "#");
+	  ui_out_field_int (uiout, "tracepoint-id", b->number);
+	}
+
+      do_cleanups (cleanup_chain);
+
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_int (uiout, "number-of-tracepoints",
+			  VEC_length(breakpoint_p, tracepoints));
+      else
+	ui_out_text (uiout, "\n");
+    }
+  VEC_free (breakpoint_p, tracepoints);
+
+  do_cleanups (bkpt_chain);
+  do_cleanups (old_chain);
+}
+
+static void
+info_static_tracepoint_markers_command (char *arg, int from_tty)
+{
+  struct cleanup *bkpttbl_chain;
+
+  bkpttbl_chain
+    = make_cleanup_ui_out_table_begin_end (uiout, 3, -1,
+					   "StaticTracepointMarkersTable");
+
+  ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");
+  if (gdbarch_addr_bit (target_gdbarch) <= 32)
+    ui_out_table_header (uiout, 10, ui_left, "addr", "Address");
+  else
+    ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
+  ui_out_table_header (uiout, 40, ui_noalign, "what", "What");
+  ui_out_table_body (uiout);
+
+  target_list_static_tracepoint_markers ();
+
+  do_cleanups (bkpttbl_chain);
+}
+
+/* The $_sdata convenience variable is a bit special.  We don't know
+   for sure type of the value until we actually have a chance to fetch
+   the data --- the size of the object depends on what has been
+   collected.  We solve this by making $_sdata be an internalvar that
+   creates a new value on access.  */
+
+/* Return a new value with the correct type for the sdata object of
+   the current trace frame.  Return a void value if there's no object
+   available.  */
+
+static struct value *
+sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+{
+  LONGEST size;
+  gdb_byte *buf;
+
+  /* We need to read the whole object before we know its size.  */
+  size = target_read_alloc (&current_target,
+			    TARGET_OBJECT_STATIC_TRACE_DATA,
+			    NULL, &buf);
+  if (size >= 0)
+    {
+      struct value *v;
+      struct type *type;
+
+      type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
+			       size);
+      v = allocate_value (type);
+      memcpy (value_contents_raw (v), buf, size);
+      xfree (buf);
+      return v;
+    }
+  else
+    return allocate_value (builtin_type (gdbarch)->builtin_void);
+}
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
 {
   struct cmd_list_element *c;
 
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_sdata", sdata_make_value);
+
   traceframe_number = -1;
   tracepoint_number = -1;
 
@@ -4143,6 +4403,11 @@ If no arguments are supplied, delete all
 Status of trace state variables and their values.\n\
 "));
 
+  add_info ("static-tracepoint-markers",
+	    info_static_tracepoint_markers_command, _("\
+List target static tracepoints markers.\n\
+"));
+
   add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\
 Select a trace frame;\n\
 No argument means forward by one frame; '-' means backward by one frame."),
@@ -4223,6 +4488,7 @@ Also accepts the following special argum
     $regs   -- all registers.\n\
     $args   -- all function arguments.\n\
     $locals -- all variables local to the block/function scope.\n\
+    $_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\
 Note: this command can only be used in a tracepoint \"actions\" list."));
 
   add_com ("teval", class_trace, teval_pseudocommand, _("\
Index: src/gdb/tracepoint.h
===================================================================
--- src.orig/gdb/tracepoint.h	2010-06-25 12:01:15.000000000 +0100
+++ src/gdb/tracepoint.h	2010-06-25 12:01:29.000000000 +0100
@@ -166,6 +166,26 @@ struct uploaded_tsv
   struct uploaded_tsv *next;
 };
 
+/* Struct recording info about a target static tracepoint marker.  */
+
+struct static_tracepoint_marker
+{
+  struct gdbarch *gdbarch;
+  CORE_ADDR address;
+
+  /* The string ID of the marker.  */
+  char *str_id;
+
+  /* Extra target reported info associated with the marker.  */
+  char *extra;
+};
+
+extern void parse_static_tracepoint_marker_definition
+  (char *line, char **pp,
+   struct static_tracepoint_marker *marker);
+extern void print_one_static_tracepoint_marker (struct static_tracepoint_marker *);
+extern void release_static_tracepoint_marker (struct static_tracepoint_marker *);
+
 /* A hook used to notify the UI of tracepoint operations.  */
 
 extern void (*deprecated_trace_find_hook) (char *arg, int from_tty);
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/server.h	2010-06-25 12:01:29.000000000 +0100
@@ -542,6 +542,10 @@ int fetch_traceframe_registers (int tfnu
 				struct regcache *regcache,
 				int regnum);
 
+int traceframe_read_sdata (int tfnum, ULONGEST offset,
+			   unsigned char *buf, ULONGEST length,
+			   ULONGEST *nbytes);
+
 /* If a thread is determined to be collecting a fast tracepoint, this
    structure holds the collect status.  */
 
@@ -569,6 +573,9 @@ int handle_tracepoint_bkpts (struct thre
 void initialize_low_tracepoint (void);
 void supply_fast_tracepoint_registers (struct regcache *regcache,
 				       const unsigned char *regs);
+void supply_static_tracepoint_registers (struct regcache *regcache,
+					 const unsigned char *regs,
+					 CORE_ADDR pc);
 #else
 void stop_tracing (void);
 #endif
Index: src/gdb/python/py-breakpoint.c
===================================================================
--- src.orig/gdb/python/py-breakpoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/python/py-breakpoint.c	2010-06-25 12:01:29.000000000 +0100
@@ -592,7 +592,7 @@ bppy_new (PyTypeObject *subtype, PyObjec
 	    create_breakpoint (python_gdbarch,
 			       spec, NULL, -1,
 			       0,
-			       0, 0, 0,
+			       0, bp_breakpoint,
 			       0,
 			       AUTO_BOOLEAN_TRUE,
 			       NULL, 0, 1);
Index: src/gdb/gdbserver/Makefile.in
===================================================================
--- src.orig/gdb/gdbserver/Makefile.in	2010-06-25 12:01:13.000000000 +0100
+++ src/gdb/gdbserver/Makefile.in	2010-06-25 12:01:29.000000000 +0100
@@ -197,7 +197,7 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS)
 	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
 	  $(XM_CLIBS)
 
-IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o ${IPA_DEPFILES}
+IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o ${IPA_DEPFILES}
 
 IPA_LIB=libinproctrace.so
 
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2010-06-25 12:01:13.000000000 +0100
+++ src/gdb/gdbserver/remote-utils.c	2010-06-25 12:01:29.000000000 +0100
@@ -74,6 +74,8 @@
 typedef int socklen_t;
 #endif
 
+#ifndef IN_PROCESS_AGENT
+
 #if USE_WIN32API
 # define INVALID_DESCRIPTOR INVALID_SOCKET
 #else
@@ -371,6 +373,8 @@ fromhex (int a)
   return 0;
 }
 
+#endif
+
 static const char hexchars[] = "0123456789abcdef";
 
 static int
@@ -394,6 +398,8 @@ ishex (int ch, int *val)
   return 0;
 }
 
+#ifndef IN_PROCESS_AGENT
+
 int
 unhexify (char *bin, const char *hex, int count)
 {
@@ -446,6 +452,8 @@ decode_address_to_semicolon (CORE_ADDR *
   return end;
 }
 
+#endif
+
 /* Convert number NIB to a hex digit.  */
 
 static int
@@ -457,6 +465,8 @@ tohex (int nib)
     return 'a' + nib - 10;
 }
 
+#ifndef IN_PROCESS_AGENT
+
 int
 hexify (char *hex, const char *bin, int count)
 {
@@ -600,6 +610,8 @@ try_rle (char *buf, int remaining, unsig
   return n + 1;
 }
 
+#endif
+
 char *
 unpack_varlen_hex (char *buff,	/* packet to parse */
 		   ULONGEST *result)
@@ -617,6 +629,8 @@ unpack_varlen_hex (char *buff,	/* packet
   return buff;
 }
 
+#ifndef IN_PROCESS_AGENT
+
 /* Write a PTID to BUF.  Returns BUF+CHARACTERS_WRITTEN.  */
 
 char *
@@ -1126,6 +1140,8 @@ write_enn (char *buf)
   buf[3] = '\0';
 }
 
+#endif
+
 void
 convert_int_to_ascii (const unsigned char *from, char *to, int n)
 {
@@ -1142,6 +1158,7 @@ convert_int_to_ascii (const unsigned cha
   *to++ = 0;
 }
 
+#ifndef IN_PROCESS_AGENT
 
 void
 convert_ascii_to_int (const char *from, unsigned char *to, int n)
@@ -1841,3 +1858,5 @@ buffer_xml_printf (struct buffer *buffer
   buffer_grow_str (buffer, prev);
   va_end (ap);
 }
+
+#endif
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2010-06-25 12:34:56.000000000 +0100
+++ src/gdb/NEWS	2010-06-28 13:23:58.000000000 +0100
@@ -12,6 +12,27 @@
   thread-specific pointer to the TIB.  This feature is also supported
   when remote debugging using GDBserver.
 
+* Static tracepoints
+
+  Static tracepoints are calls in the user program into a tracing
+  library.  One such library is a port of the LTTng kernel tracer to
+  userspace --- UST (LTTng Userspace Tracer, http://lttng.org/ust).
+  When debugging with GDBserver, GDB now supports combining the GDB
+  tracepoint machinery with such libraries.  For example: the user can
+  use GDB to probe a static tracepoint marker (a call from the user
+  program into the tracing library) with the new "strace" command (see
+  "New commands" below).  This creates a "static tracepoint" in the
+  breakpoint list, that can be manipulated with the same feature set
+  as fast and regular tracepoints.  E.g., collect registers, local and
+  global variables, collect trace state variables, and define
+  tracepoint conditions.  In addition, the user can collect extra
+  static tracepoint marker specific data, by collecting the new
+  $_sdata internal variable.  When analying the trace buffer, you can
+  inspect $_sdata like any other variable available to GDB.  For more
+  information, see the "Tracepoints" chapter in GDB user manual.  New
+  remote packets have been defined to support static tracepoints, see
+  the "New remote packets" section below.
+
 * New remote packets
 
 qGetTIBAddr
@@ -27,23 +48,42 @@ qRelocInsn
   is particularly useful for stubs that support fast tracepoints.  GDB
   reports support for this feature in the qSupported packet.
 
+qTfSTM, qTsSTM
+
+  List static tracepoint markers in the target program.
+
+qTSTMat
+
+  List static tracepoint markers at a given address in the target
+  program.
+
+qXfer:statictrace:read
+
+  Read the static trace data collected (by a `collect $_sdata'
+  tracepoint action).  The remote stub reports support for this packet
+  to gdb's qSupported query.
+
 * The source command now accepts a -s option to force searching for the
   script in the source search path even if the script name specifies
   a directory.
 
 * New features in the GDB remote stub, GDBserver
 
-  - GDBserver now support tracepoints (including fast tracepoints).
-    The feature is currently supported by the i386-linux and
-    amd64-linux builds.  See the "Tracepoints support in gdbserver"
-    section in the manual for more information.  GDBserver JIT
-    compiles the tracepoint's conditional agent expression bytecode
-    into native code whenever possible for low overhead dynamic
-    tracepoints conditionals.  For such tracepoints, an expression
-    that examines program state is evaluated when the tracepoint is
-    reached, in order to determine whether to capture trace data.  If
-    the condition is simple and false, processing the tracepoint
-    finishes very quickly and no data is gathered.
+  - GDBserver now support tracepoints (including fast tracepoints, and
+    static tracepoints).  The feature is currently supported by the
+    i386-linux and amd64-linux builds.  See the "Tracepoints support
+    in gdbserver" section in the manual for more information.
+
+    GDBserver JIT compiles the tracepoint's conditional agent
+    expression bytecode into native code whenever possible for low
+    overhead dynamic tracepoints conditionals.  For such tracepoints,
+    an expression that examines program state is evaluated when the
+    tracepoint is reached, in order to determine whether to capture
+    trace data.  If the condition is simple and false, processing the
+    tracepoint finishes very quickly and no data is gathered.
+
+    GDBserver interfaces with the UST (LTTng Userspace Tracer) library
+    for static tracepoints support.
 
   - GDBserver now supports x86_64 Windows 64-bit debugging.
 
@@ -97,6 +137,13 @@ save breakpoints <filename>
 `save tracepoints' is a new alias for `save-tracepoints'.  The latter
 is now deprecated.
 
+info static-tracepoint-markers
+  Display information about static tracepoint markers in the target.
+
+strace FN | FILE:LINE | *ADDR | -m MARKER_ID
+  Define a static tracepoint by probing a marker at the given
+  function, line, address, or MARKER_ID.
+
 * Python scripting
 
 ** The GDB Python API now has access to breakpoints, symbols, symbol
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2010-06-25 13:11:25.000000000 +0100
+++ src/gdb/doc/gdb.texinfo	2010-06-28 13:23:58.000000000 +0100
@@ -8279,6 +8279,13 @@ to match the format in which the data wa
 The variable @code{$_exitcode} is automatically set to the exit code when
 the program being debugged terminates.
 
+@item $_sdata
+@vindex $_sdata@r{, inspect, convenience variable}
+The variable @code{$_sdata} contains extra collected static tracepoint
+data.  @xref{Tracepoint Actions,,Tracepoint Action Lists}.  Note that
+@code{$_sdata} could be empty, if not inspecting a trace buffer, or
+if extra static tracepoint data has not been collected.
+
 @item $_siginfo
 @vindex $_siginfo@r{, convenience variable}
 The variable @code{$_siginfo} contains extra signal information
@@ -9590,6 +9597,27 @@ Some targets may support @dfn{fast trace
 a different way (such as with a jump instead of a trap), that is
 faster but possibly restricted in where they may be installed.
 
+@cindex static tracepoints
+@cindex markers, static tracepoints
+@cindex probing markers, static tracepoints
+Regular and fast tracepoints are dynamic tracing facilities, meaning
+that they can be used to insert tracepoints at (almost) any location
+in the target.  Some targets may also support controlling @dfn{static
+tracepoints} from @value{GDBN}.  With static tracing, a set of
+instrumentation points, also known as @dfn{markers}, are embedded in
+the target program, and can be activated or deactivated by name or
+address.  These are usually placed at locations which facilitate
+investigating what the target is actually doing.  @value{GDBN}'s
+support for static tracing includes being able to list instrumentation
+points, and attach them with @value{GDBN} defined high level
+tracepoints that expose the whole range of convenience of
+@value{GDBN}'s tracepoints support.  Namelly, support for collecting
+registers values and values of global or local (to the instrumentation
+point) variables; tracepoint conditions and trace state variables.
+The act of installing a @value{GDBN} static tracepoint on an
+instrumentation point, or marker, is referred to as @dfn{probing} a
+static tracepoint marker.
+
 @code{gdbserver} supports tracepoints on some target systems.
 @xref{Server,,Tracepoints support in @code{gdbserver}}.
 
@@ -9604,6 +9632,7 @@ conditions and actions.
 * Trace State Variables::
 * Tracepoint Actions::
 * Listing Tracepoints::
+* Listing Static Tracepoint Markers::
 * Starting and Stopping Trace Experiments::
 * Tracepoint Restrictions::
 @end menu
@@ -9663,6 +9692,64 @@ message.
 @value{GDBN} handles arguments to @code{ftrace} exactly as for
 @code{trace}.
 
+@item strace @var{location} [ if @var{cond} ]
+@cindex static tracepoint, setting
+@kindex strace
+The @code{strace} command sets a static tracepoint.  For targets that
+support it, setting a static tracepoint probes a static
+instrumentation point, or marker, found at @var{location}.  It may not
+be possible to set a static tracepoint at the desired location, in
+which case the command will exit with an explanatory message.
+
+@value{GDBN} handles arguments to @code{strace} exactly as for
+@code{trace}, with the addition that the user can also specify
+@code{-m @var{marker}} as @var{location}.  This probes the marker
+identified by the @var{marker} string identifier.  This identifier
+depends on the static tracepoint backend library your program is
+using.  You can find all the marker identifiers in the @samp{ID} field
+of the @code{info static-tracepoint-markers} command output.
+@xref{Listing Static Tracepoint Markers,,Listing Static Tracepoint
+Markers}.  For example, in the following small program using the UST
+tracing engine:
+
+@smallexample
+main ()
+@{
+  trace_mark(ust, bar33, "str %s", "FOOBAZ");
+@}
+@end smallexample
+
+The marker id is composed of joining the first two arguments to the
+@code{trace_mark} call with a slash, which translates to:
+
+@smallexample
+(@value{GDBP}) info static-tracepoint-markers
+Enb Address            What
+n   0x0000000000400ddc in main at stexample.c:22
+     ID: ust/bar33
+     Data: str %s
+[etc...]
+@end smallexample
+
+You can probe that marker with:
+
+@smallexample
+(@value{GDBP}) strace -m ust/bar33
+@end smallexample
+
+Static tracepoints accept an extra collect action --- @code{collect
+$_sdata}.  This collects arbitrary user data passed in the probe point
+call to the tracing library.  In the UST example above, you'll see
+that the third argument to @code{trace_mark} is a printf-like format
+string.  The user data is then the result of running that formating
+string against the following arguments.  Note that @code{info
+static-tracepoint-markers} command output lists that format string in
+the @samp{Data:} field.
+
+You can inspect this data when analyzing the trace buffer, by printing
+the $_sdata variable like any other variable available to
+@value{GDBN}.  @xref{Tracepoint Actions,,Tracepoint Action Lists}.
+
 @vindex $tpnum
 @cindex last tracepoint number
 @cindex recent tracepoint number
@@ -9899,13 +9986,32 @@ special arguments are supported:
 
 @table @code
 @item $regs
-collect all registers
+Collect all registers.
 
 @item $args
-collect all function arguments
+Collect all function arguments.
 
 @item $locals
-collect all local variables.
+Collect all local variables.
+
+@item $_sdata
+@vindex $_sdata@r{, collect}
+Collect static tracepoint marker specific data.  Only available for
+static tracepoints.  @xref{Tracepoint Actions,,Tracepoint Action
+Lists}.  This usually consists of data formatted to a character string
+using the format provided by the programmer that instrumented the
+program.  E.g., on some systems, an instrumentation point resembles a
+printf function call:
+
+@smallexample
+ const char master_name[] = "$your_name";
+ TRACE(tp1, "hello %s", master_name)
+@end smallexample
+
+In this case, collecting @code{$_sdata} collects the string
+@samp{hello $yourname}.  When analying the trace buffer, you can
+inspect @samp{$_sdata} like any other variable available to
+@value{GDBN}.
 @end table
 
 You can give several consecutive @code{collect} commands, each one
@@ -10000,6 +10106,30 @@ Num     Type           Disp Enb Address 
 This command can be abbreviated @code{info tp}.
 @end table
 
+@node Listing Static Tracepoint Markers
+@subsection Listing Static Tracepoint Markers
+
+@table @code
+@kindex info static-tracepoint-markers
+@cindex information about static tracepoint markers
+@item info static-tracepoint-markers
+Display information about all static tracepoint markers defined in the
+program.
+
+@smallexample
+(@value{GDBP}) info static-tracepoint-markers
+Enb Address            What
+y   0x0000000000400e1a in main at stexample.c:25
+     ID: ust/bar2
+     Data: number1 %d number2 %d
+     Probed by static tracepoints: #2
+n   0x0000000000400c87 in main at stexample.c:24
+     ID: ust/bar33
+     Data: str %s
+(@value{GDBP})
+@end smallexample
+@end table
+
 @node Starting and Stopping Trace Experiments
 @subsection Starting and Stopping Trace Experiments
 
@@ -15848,13 +15978,21 @@ of a multi-process mode debug session.
 @subsection Tracepoints support in @code{gdbserver}
 @cindex tracepoints support in @code{gdbserver}
 
-On some targets, @code{gdbserver} supports tracepoints and fast
-tracepoints.
+On some targets, @code{gdbserver} supports tracepoints, fast
+tracepoints and static tracepoints.
 
-For fast tracepoints to work, a special library called the
+For fast or static tracepoints to work, a special library called the
 @dfn{in-process agent} (IPA), must be loaded in the inferior process.
 This library is built and distributed as an integral part of
-@code{gdbserver}.
+@code{gdbserver}.  In addition, support for static tracepoints
+requires building the in-process agent library with static tracepoints
+support.  At present, the UST (LTTng Userspace Tracer,
+@url{http://lttng.org/ust}) tracing engine is supported.  This support
+is automatically available if UST development headers are found in the
+standard include path when @code{gdbserver} is built, or if
+@code{gdbserver} was explicitly configured using @option{--with-ust}
+to point at such headers.  You can explicitly disable the support
+using @option{--with-ust=no}.
 
 There are several ways to load the in-process agent in your program:
 
@@ -15895,10 +16033,10 @@ systems, when you connect to @code{gdbse
 remote}, you'll find that the program is stopped at the dynamic
 loader's entry point, and no shared library has been loaded in the
 program's address space yet, including the in-process agent.  In that
-case, before being able to use any of the fast tracepoints features,
-you need to let the loader run and load the shared libraries.  The
-most simple way to do that is to run the program to the main
-procedure.  E.g., if debugging a C or C@t{++} program, start
+case, before being able to use any of the fast or static tracepoints
+features, you need to let the loader run and load the shared
+libraries.  The simplest way to do that is to run the program to the
+main procedure.  E.g., if debugging a C or C@t{++} program, start
 @code{gdbserver} like so:
 
 @smallexample
@@ -15918,7 +16056,8 @@ $ gdb myprogram
 The in-process tracing agent library should now be loaded into the
 process; you can confirm it with the @code{info sharedlibrary}
 command, which will list @file{libinproctrace.so} as loaded in the
-process.  You are now ready to install fast tracepoints and start
+process.  You are now ready to install fast tracepoints, list static
+tracepoint markers, probe static tracepoints markers, and start
 tracing.
 
 @node Remote Configuration
@@ -16170,6 +16309,10 @@ are:
 @tab @code{qXfer:memory-map:read}
 @tab @code{info mem}
 
+@item @code{read-sdata-object}
+@tab @code{qXfer:sdata:read}
+@tab @code{print $_sdata}
+
 @item @code{read-spu-object}
 @tab @code{qXfer:spu:read}
 @tab @code{info spu}
@@ -31807,6 +31950,11 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:sdata:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{qXfer:spu:read}
 @tab No
 @tab @samp{-}
@@ -31910,6 +32058,10 @@ The remote stub understands the @samp{qX
 The remote stub understands the @samp{qXfer:memory-map:read} packet
 (@pxref{qXfer memory map read}).
 
+@item qXfer:sdata:read
+The remote stub understands the @samp{qXfer:sdata:read} packet
+(@pxref{qXfer sdata read}).
+
 @item qXfer:spu:read
 The remote stub understands the @samp{qXfer:spu:read} packet
 (@pxref{qXfer spu read}).
@@ -31978,6 +32130,10 @@ the source form of tracepoint definition
 @item QAllow
 The remote stub understands the @samp{QAllow} packet.
 
+@item StaticTracepoint
+@cindex static tracepoints, in remote protocol
+The remote stub supports static tracepoints.
+
 @end table
 
 @item qSymbol::
@@ -32062,6 +32218,9 @@ packets.)
 @itemx QTro       
 @itemx qTStatus   
 @itemx qTV
+@itemx qTfSTM
+@itemx qTsSTM
+@itemx qTSTMat
 @xref{Tracepoint Packets}.
 
 @item qXfer:@var{object}:read:@var{annex}:@var{offset},@var{length}
@@ -32118,6 +32277,18 @@ annex part of the generic @samp{qXfer} p
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+@item qXfer:sdata:read::@var{offset},@var{length}
+@anchor{qXfer sdata read}
+
+Read contents of the extra collected static tracepoint marker
+information.  The annex part of the generic @samp{qXfer} packet must
+be empty (@pxref{qXfer read}).  @xref{Tracepoint Actions,,Tracepoint
+Action Lists}.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:siginfo:read::@var{offset},@var{length}
 @anchor{qXfer siginfo read}
 Read contents of the extra signal information on the target
@@ -32657,6 +32828,43 @@ and multiple @code{qTsV} to get addition
 these packets follow the syntax of the @code{QTDV} packets that define
 trace state variables.
 
+@item qTfSTM
+@itemx qTsSTM
+These packets request data about static tracepoint markers that exist
+in the target program.  @value{GDBN} sends @code{qTfSTM} to get the
+first piece of data, and multiple @code{qTsSTM} to get additional
+pieces.  Replies to these packets take the following form:
+
+Reply:
+@table @samp
+@item m @var{address}:@var{id}:@var{extra}
+A single marker
+@item m @var{address}:@var{id}:@var{extra},@var{address}:@var{id}:@var{extra}@dots{}
+a comma-separated list of markers
+@item l
+(lower case letter @samp{L}) denotes end of list.
+@item E @var{nn}
+An error occurred.  @var{nn} are hex digits.
+@item
+An empty reply indicates that the request is not supported by the
+stub.
+@end table
+
+@var{address} is encoded in hex.
+@var{id} and @var{extra} are strings encoded in hex.
+
+In response to each query, the target will reply with a list of one or
+more markers, separated by commas.  @value{GDBN} will respond to each
+reply with a request for more markers (using the @samp{qs} form of the
+query), until the target responds with @samp{l} (lower-case ell, for
+@dfn{last}).
+
+@item qTSTMat:@var{address}
+This packets requests data about static tracepoint markers in the
+target program at @var{address}.  Replies to this packet follow the
+syntax of the @samp{qTfSTM} and @code{qTsSTM} packets that list static
+tracepoint markers.
+
 @item QTSave:@var{filename}
 This packet directs the target to save trace data to the file name
 @var{filename} in the target's filesystem.  @var{filename} is encoded
2010-06-28  Pedro Alves  <pedro@codesourcery.com>

	gdb/gdbserver/
	* configure.ac: Handle --with-ust.  substitute ustlibs and ustinc.
	* mem-break.c (uninsert_all_breakpoints)
	(reinsert_all_breakpoints): New.
	* mem-break.h (reinsert_all_breakpoints, uninsert_all_breakpoints):
	* tracepoint.c (ust_loaded, helper_thread_id, cmd_buf): New.
	(gdb_agent_ust_loaded, helper_thread_id)
	(gdb_agent_helper_thread_id): New macros.
	(struct ipa_sym_addresses): Add addr_ust_loaded,
	addr_helper_thread_id, addr_cmd_buf.
	(symbol_list): Add ust_loaded, helper_thread_id, cmd_buf.
	(in_process_agent_loaded_ust): New.
	(write_e_ust_not_loaded): New.
	(maybe_write_ipa_ust_not_loaded): New.
	(struct collect_static_trace_data_action): New.
	(enum tracepoint_type) <static_tracepoint>: New.
	(struct tracepoint) <handle>: Mention static tracepoints.
	(struct static_tracepoint_ctx): New.
	(CMD_BUF_SIZE): New.
	(add_tracepoint_action): Handle static tracepoint actions.
	(unprobe_marker_at): New.
	(clear_installed_tracepoints): Handle static tracepoints.
	(cmd_qtdp): Handle static tracepoints.
	(probe_marker_at): New.
	(cmd_qtstart): Handle static tracepoints.
	(response_tracepoint): Handle static tracepoints.
	(cmd_qtfstm, cmd_qtsstm, cmd_qtstmat): New.
	(handle_tracepoint_query): Handle qTfSTM, qTsSTM and qTSTMat.
	(get_context_regcache): Handle static tracepoints.
	(do_action_at_tracepoint): Handle static tracepoint actions.
	(traceframe_find_block_type): Handle static trace data blocks.
	(traceframe_read_sdata): New.
	(download_tracepoints): Download static tracepoint actions.
	[HAVE_UST] Include ust/ust.h, dlfcn.h, sys/socket.h, and sys/un.h.
	(GDB_PROBE_NAME): New.
	(ust_ops): New.
	(GET_UST_SYM): New.
	(USTF): New.
	(dlsym_ust): New.
	(ust_marker_to_static_tracepoint): New.
	(gdb_probe): New.
	(collect_ust_data_at_tracepoint): New.
	(gdb_ust_probe): New.
	(UNIX_PATH_MAX, SOCK_DIR): New.
	(gdb_ust_connect_sync_socket): New.
	(resume_thread, stop_thread): New.
	(run_inferior_command): New.
	(init_named_socket): New.
	(gdb_ust_socket_init): New.
	(cstr_to_hexstr): New.
	(next_st): New.
	(first_marker, next_marker): New.
	(response_ust_marker): New.
	(cmd_qtfstm, cmd_qtsstm): New.
	(unprobe_marker_at, probe_marker_at): New.
	(cmd_qtstmat, gdb_ust_thread): New.
	(gdb_ust_init): New.
	(initialize_tracepoint_ftlib): Call gdb_ust_init.
	* linux-amd64-ipa.c [HAVE_UST]: Include ust/processor.h
	(ST_REGENTRY): New.
	(x86_64_st_collect_regmap): New.
	(X86_64_NUM_ST_COLLECT_GREGS): New.
	(AMD64_RIP_REGNUM): New.
	(supply_static_tracepoint_registers): New.
	* linux-i386-ipa.c [HAVE_UST]: Include ust/processor.h
	(ST_REGENTRY): New.
	(i386_st_collect_regmap): New.
	(i386_NUM_ST_COLLECT_GREGS): New.
	(supply_static_tracepoint_registers): New.
	* server.c (handle_query): Handle qXfer:statictrace:read.
	<qSupported>: Report support for StaticTracepoints, and
	qXfer:statictrace:read features.
	* server.h (traceframe_read_sdata)
	(supply_static_tracepoint_registers): Declare.
	* remote-utils.c (convert_int_to_ascii, hexchars, ishex, tohex)
	(unpack_varlen_hex): Include in IPA build.
	* Makefile.in (IPA_OBJS): Add remote-utils-ipa.o.
	* config.in, configure: Regenerate.
	
	gdb/
	* NEWS: Mention new support for static tracepoints.
	(New packets): Mention qTfSTM, qTsSTM, qTSTMat and
	qXfer:statictrace:read.
	(New features in the GDB remote stub, GDBserver): Mention static
	tracepoints support using an UST based backend.
	(New commands): Mention "info static-tracepoint-markers" and
	"strace".
	* breakpoint.c (is_tracepoint): Handle static tracepoints.
	(validate_commands_for_breakpoint): Static tracepoints can't do
	while-stepping.
	(static_tracepoints_here): New.
	(bpstat_what): Handle static tracepoints.
	(print_one_breakpoint_location, allocate_bp_location, mention):
	Ditto.
	(create_breakpoint_sal): Ditto.
	(decode_static_tracepoint_spec): New.
	(create_breakpoint): Replace `hardwareflag', and `traceflag' with
	`type_wanted'.  Adjust.  Handle static tracepoint marker
	locations.
	(break_command_1): Adjust.
	(update_static_tracepoint): New.
	(update_breakpoint_locations): Handle static tracepoints.
	(breakpoint_re_set_one): Handle static tracepoint marker
	locations.
	(disable_command, enable_command): Handle static tracepoints.
	(trace_command, ftrace_command): Adjust.
	(strace_command): New.
	(create_tracepoint_from_upload): Adjust.
	(save_breakpoints): Handle static tracepoints.
	(_initialize_breakpoint): Install the "strace" command.
	* breakpoint.h (enum bptype): New bp_static_tracepoint type.
	(struct breakpoint): New field static_trace_id.
	(breakpoints_here_p): Declare.
	(create_breakpoint): Adjust.
	(static_tracepoints_here): Declare.
	* remote.c (struct remote_state) <static_tracepoints>: New field.
	(PACKET_qXfer_statictrace_read, PACKET_StaticTracepoints): New.
	(remote_static_tracepoint_marker_at): New.
	(remote_static_tracepoint_marker_by_strid): New.
	(remote_list_static_tracepoint_markers): New.
	(remote_static_tracepoint_feature): New.
	(remote_disconnected_tracing_feature): Handle "StaticTracepoints".
	(remote_xfer_partial): Handle TARGET_OBJECT_STATIC_TRACE_DATA.
	(remote_supports_static_tracepoints): New.
	(remote_download_tracepoint): Download static tracepoints.
	(init_remote_ops): Install remote_list_static_tracepoint_markers,
	remote_static_tracepoint_marker_at and
	remote_static_tracepoint_marker_by_strid.
	(_initialize_remote): Install set|show remote static-tracepoints,
	and set|show remote read-static-trace-object commands.
	* target.c (update_current_target): Inherit and default
	to_list_static_tracepoint_markers, to_static_tracepoint_marker_at,
	to_static_tracepoint_marker_by_strid.
	* target.h (static_tracepoint_marker): Forward declare.
	(enum target_object): New object TARGET_OBJECT_STATIC_TRACE_DATA.
	(struct target_ops): New fields to_list_static_tracepoint_markers,
	to_static_tracepoint_marker_at,
	to_static_tracepoint_marker_by_strid.
	(target_list_static_tracepoint_markers)
	(target_static_tracepoint_marker_at)
	(target_static_tracepoint_marker_by_strid): New.
	* tracepoint.c: Include source.h.
	(validate_actionline): Handle $_sdata.
	(struct collection_list): New field strace_data.
	(add_static_trace_data): New.
	(clear_collection_list): Clear strace_data.
	(stringify_collection_list): Account for a possible static trace
	data collection.
	(encode_actions_1): Encode an $_sdata collection.
	(parse_tracepoint_definition): Handle static tracepoints.
	(parse_static_tracepoint_marker_definition): New.
	(release_static_tracepoint_marker): New.
	(print_one_static_tracepoint_marker): New.
	(info_static_tracepoint_markers_command): New.
	(sdata_make_value): New.
	(_initialize_tracepoint): Create the $_sdata convenience variable.
	Add the "info static-tracepoint-markers" command.
	Mention $_sdata in the "collect" command's help output.
	* tracepoint.h (struct static_tracepoint_marker): New.
	(parse_static_tracepoint_marker_definition)
	(print_one_static_tracepoint_marker)
	(release_static_tracepoint_marker): Declare.
	* mi/mi-cmd-break.c (mi_cmd_break_insert): Adjust.
	* python/py-breakpoint.c (bppy_new): Adjust.

	doc/
	* gdb.texinfo (Convenience Variables): Document $_sdata.
	(Commands to Set Tracepoints): Describe static tracepoints.  Add
	`Listing Static Tracepoint Markers' menu entry.  Document
	"strace".
	(Tracepoint Action Lists): Document collecting $_sdata.
	(Listing Static Tracepoint Markers): New subsection.
	(Tracepoints support in gdbserver): Mention static tracepoints.
	(remote packets, enabling and disabling): Mention
	read-sdata-object.
	(General Query Packets) <qSupported>: Document qXfer:sdata:read
	and StaticTracepoint.
	Mention qTfSTM, qTsSTM and qTSTMat as tracepoint packets.
	Document qXfer:sdata:read.
	(Tracepoint packets): Document qTfSTM, qTsSTM and qTSTMat.

---
 gdb/NEWS                        |   69 +-
 gdb/breakpoint.c                |  329 +++++++++-
 gdb/breakpoint.h                |   13 
 gdb/doc/gdb.texinfo             |  232 ++++++-
 gdb/gdbserver/Makefile.in       |    2 
 gdb/gdbserver/config.in         |    3 
 gdb/gdbserver/configure         |  104 +++
 gdb/gdbserver/configure.ac      |   48 +
 gdb/gdbserver/linux-amd64-ipa.c |   89 ++
 gdb/gdbserver/linux-i386-ipa.c  |   77 ++
 gdb/gdbserver/mem-break.c       |   22 
 gdb/gdbserver/mem-break.h       |   11 
 gdb/gdbserver/remote-utils.c    |   19 
 gdb/gdbserver/server.c          |   48 +
 gdb/gdbserver/server.h          |    7 
 gdb/gdbserver/tracepoint.c      | 1272 +++++++++++++++++++++++++++++++++++++++-
 gdb/mi/mi-cmd-break.c           |   15 
 gdb/python/py-breakpoint.c      |    2 
 gdb/remote.c                    |  160 +++++
 gdb/target.c                    |   12 
 gdb/target.h                    |   27 
 gdb/tracepoint.c                |  276 ++++++++
 gdb/tracepoint.h                |   20 
 23 files changed, 2788 insertions(+), 69 deletions(-)

Index: src/gdb/gdbserver/configure.ac
===================================================================
--- src.orig/gdb/gdbserver/configure.ac	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/configure.ac	2010-06-25 12:01:29.000000000 +0100
@@ -45,6 +45,54 @@ AC_CHECK_HEADERS(sgtty.h termio.h termio
 AC_CHECK_FUNCS(pread pwrite pread64)
 AC_REPLACE_FUNCS(memmem)
 
+# Check for UST
+ustlibs=""
+ustinc=""
+
+AC_ARG_WITH(ust, [  --with-ust=PATH       Specify prefix directory for the installed UST package
+                          Equivalent to --with-ust-include=PATH/include
+                          plus --with-ust-lib=PATH/lib])
+AC_ARG_WITH(ust_include, [  --with-ust-include=PATH Specify directory for installed UST include files])
+AC_ARG_WITH(ust_lib, [  --with-ust-lib=PATH   Specify the directory for the installed UST library])
+
+case $with_ust in
+  no)
+    ustlibs=
+    ustinc=
+    ;;
+  "" | yes)
+    ustlibs=" -lust "
+    ustinc=""
+    ;;
+  *)
+    ustlibs="-L$with_ust/lib -lust"
+    ustinc="-I$with_ust/include "
+    ;;
+esac
+if test "x$with_ust_include" != x; then
+  ustinc="-I$with_ust_include "
+fi
+if test "x$with_ust_lib" != x; then
+  ustlibs="-L$with_ust_lib -lust"
+fi
+
+if test "x$with_ust" != "xno"; then
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $ustinc"
+  AC_MSG_CHECKING([for ust])
+  AC_TRY_COMPILE([
+#define CONFIG_UST_GDB_INTEGRATION
+#include <ust/ust.h>
+  ],[],
+  [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_UST, 1, [Define if UST is available])],
+  [AC_MSG_RESULT([no]); ustlibs= ; ustinc= ])
+  CFLAGS="$saved_CFLAGS"
+fi
+
+# Flags needed for UST
+AC_SUBST(ustlibs)
+AC_SUBST(ustinc)
+
 dnl dladdr is glibc-specific.  It is used by thread-db.c but only for
 dnl debugging messages.  It lives in -ldl which is handled below so we don't
 dnl use AC_CHECK_LIB (or AC_SEARCH_LIBS) here.  Instead we just temporarily
Index: src/gdb/gdbserver/mem-break.c
===================================================================
--- src.orig/gdb/gdbserver/mem-break.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/mem-break.c	2010-06-25 12:01:29.000000000 +0100
@@ -777,6 +777,17 @@ uninsert_breakpoints_at (CORE_ADDR pc)
     uninsert_raw_breakpoint (bp);
 }
 
+void
+uninsert_all_breakpoints (void)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
+
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (bp->inserted)
+      uninsert_raw_breakpoint (bp);
+}
+
 static void
 reinsert_raw_breakpoint (struct raw_breakpoint *bp)
 {
@@ -817,6 +828,17 @@ reinsert_breakpoints_at (CORE_ADDR pc)
 }
 
 void
+reinsert_all_breakpoints (void)
+{
+  struct process_info *proc = current_process ();
+  struct raw_breakpoint *bp;
+
+  for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+    if (!bp->inserted)
+      reinsert_raw_breakpoint (bp);
+}
+
+void
 check_breakpoints (CORE_ADDR stop_pc)
 {
   struct process_info *proc = current_process ();
Index: src/gdb/gdbserver/mem-break.h
===================================================================
--- src.orig/gdb/gdbserver/mem-break.h	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/mem-break.h	2010-06-25 12:01:29.000000000 +0100
@@ -78,6 +78,17 @@ void reinsert_breakpoints_at (CORE_ADDR 
 
 void uninsert_breakpoints_at (CORE_ADDR where);
 
+/* Reinsert all breakpoints of the current process (and change their
+   status to inserted).  */
+
+void reinsert_all_breakpoints (void);
+
+/* Uninsert all breakpoints of the current process (and change their
+   status to uninserted).  This still leaves the breakpoints in the
+   table.  */
+
+void uninsert_all_breakpoints (void);
+
 /* See if any breakpoint claims ownership of STOP_PC.  Call the handler for
    the breakpoint, if found.  */
 
Index: src/gdb/gdbserver/tracepoint.c
===================================================================
--- src.orig/gdb/gdbserver/tracepoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/tracepoint.c	2010-06-28 13:23:58.000000000 +0100
@@ -135,6 +135,9 @@ trace_vdebug (const char *fmt, ...)
 # define get_raw_reg gdb_agent_get_raw_reg
 # define get_trace_state_variable_value gdb_agent_get_trace_state_variable_value
 # define set_trace_state_variable_value gdb_agent_set_trace_state_variable_value
+# define ust_loaded gdb_agent_ust_loaded
+# define helper_thread_id gdb_agent_helper_thread_id
+# define cmd_buf gdb_agent_cmd_buf
 #endif
 
 #ifndef IN_PROCESS_AGENT
@@ -168,6 +171,9 @@ struct ipa_sym_addresses
   CORE_ADDR addr_get_raw_reg;
   CORE_ADDR addr_get_trace_state_variable_value;
   CORE_ADDR addr_set_trace_state_variable_value;
+  CORE_ADDR addr_ust_loaded;
+  CORE_ADDR addr_helper_thread_id;
+  CORE_ADDR addr_cmd_buf;
 };
 
 #define STRINGIZE_1(STR) #STR
@@ -209,6 +215,9 @@ static struct
   IPA_SYM(get_raw_reg),
   IPA_SYM(get_trace_state_variable_value),
   IPA_SYM(set_trace_state_variable_value),
+  IPA_SYM(ust_loaded),
+  IPA_SYM(helper_thread_id),
+  IPA_SYM(cmd_buf),
 };
 
 struct ipa_sym_addresses ipa_sym_addrs;
@@ -223,6 +232,29 @@ in_process_agent_loaded (void)
 
 static int read_inferior_integer (CORE_ADDR symaddr, int *val);
 
+/* Returns true if both the in-process agent library and the static
+   tracepoints libraries are loaded in the inferior.  */
+
+static int
+in_process_agent_loaded_ust (void)
+{
+  int loaded = 0;
+
+  if (!in_process_agent_loaded ())
+    {
+      warning ("In-process agent not loaded");
+      return 0;
+    }
+
+  if (read_inferior_integer (ipa_sym_addrs.addr_ust_loaded, &loaded))
+    {
+      warning ("Error reading ust_loaded in lib");
+      return 0;
+    }
+
+  return loaded;
+}
+
 static void
 write_e_ipa_not_loaded (char *buffer)
 {
@@ -231,6 +263,24 @@ write_e_ipa_not_loaded (char *buffer)
 	   "Dynamic tracepoints unavailable.");
 }
 
+/* Write an error to BUFFER indicating that UST isn't loaded in the
+   inferior.  */
+
+static void
+write_e_ust_not_loaded (char *buffer)
+{
+#ifdef HAVE_UST
+  sprintf (buffer,
+	   "E.UST library not loaded in process.  "
+	   "Static tracepoints unavailable.");
+#else
+  sprintf (buffer, "E.GDBserver was built without static tracepoints support");
+#endif
+}
+
+/* If the in-process agent library isn't loaded in the inferior, write
+   an error to BUFFER, and return 1.  Otherwise, return 0.  */
+
 static int
 maybe_write_ipa_not_loaded (char *buffer)
 {
@@ -242,6 +292,26 @@ maybe_write_ipa_not_loaded (char *buffer
   return 0;
 }
 
+/* If the in-process agent library and the ust (static tracepoints)
+   library aren't loaded in the inferior, write an error to BUFFER,
+   and return 1.  Otherwise, return 0.  */
+
+static int
+maybe_write_ipa_ust_not_loaded (char *buffer)
+{
+  if (!in_process_agent_loaded ())
+    {
+      write_e_ipa_not_loaded (buffer);
+      return 1;
+    }
+  else if (!in_process_agent_loaded_ust ())
+    {
+      write_e_ust_not_loaded (buffer);
+      return 1;
+    }
+  return 0;
+}
+
 /* Cache all future symbols that the tracepoints module might request.
    We can not request symbols at arbitrary states in the remote
    protocol, only when the client tells us that new symbols are
@@ -347,6 +417,8 @@ static void download_tracepoints (void);
 static void download_trace_state_variables (void);
 static void upload_fast_traceframes (void);
 
+static int run_inferior_command (char *cmd);
+
 static int
 read_inferior_integer (CORE_ADDR symaddr, int *val)
 {
@@ -542,6 +614,12 @@ struct eval_expr_action
   struct agent_expr *expr;
 };
 
+/* An 'L' (collect static trace data) action.  */
+struct collect_static_trace_data_action
+{
+  struct tracepoint_action base;
+};
+
 /* This structure describes a piece of the source-level definition of
    the tracepoint.  The contents are not interpreted by the target,
    but preserved verbatim for uploading upon reconnection.  */
@@ -569,6 +647,10 @@ enum tracepoint_type
 
   /* A fast tracepoint implemented with a jump instead of a trap.  */
   fast_tracepoint,
+
+  /* A static tracepoint, implemented by a program call into a tracing
+     library.  */
+  static_tracepoint
 };
 
 struct tracepoint_hit_ctx;
@@ -667,8 +749,8 @@ struct tracepoint
   char **step_actions_str;
 
   /* Handle returned by the breakpoint or tracepoint module when we
-     inserted the trap or jump.  NULL if we haven't inserted it
-     yet.  */
+     inserted the trap or jump, or hooked into a static tracepoint.
+     NULL if we haven't inserted it yet.  */
   void *handle;
 #endif
 
@@ -1157,6 +1239,35 @@ struct fast_tracepoint_ctx
   struct tracepoint *tpoint;
 };
 
+/* Static tracepoint specific data to be passed down to
+   collect_data_at_tracepoint.  */
+struct static_tracepoint_ctx
+{
+  struct tracepoint_hit_ctx base;
+
+  /* The regcache corresponding to the registers state at the time of
+     the tracepoint hit.  Initialized lazily, from REGS.  */
+  struct regcache regcache;
+  int regcache_initted;
+
+  /* The buffer space REGCACHE above uses.  We use a separate buffer
+     instead of letting the regcache malloc for both signal safety and
+     performance reasons; this is allocated on the stack instead.  */
+  unsigned char *regspace;
+
+  /* The register buffer as passed on by lttng/ust.  */
+  struct registers *regs;
+
+  /* The "printf" formatter and the args the user passed to the marker
+     call.  We use this to be able to collect "static trace data"
+     ($_sdata).  */
+  const char *fmt;
+  va_list *args;
+
+  /* The GDB tracepoint matching the probed marker that was "hit".  */
+  struct tracepoint *tpoint;
+};
+
 #else
 
 /* Static tracepoint specific data to be passed down to
@@ -1228,6 +1339,10 @@ static struct tracepoint *fast_tracepoin
 #define cmpxchg(mem, oldval, newval) \
   __sync_val_compare_and_swap (mem, oldval, newval)
 
+/* The size in bytes of the buffer used to talk to the IPA helper
+   thread.  */
+#define CMD_BUF_SIZE 1024
+
 /* Record that an error occurred during expression evaluation.  */
 
 static void
@@ -1756,6 +1871,18 @@ add_tracepoint_action (struct tracepoint
 	      ++act;
 	    break;
 	  }
+	case 'L':
+	  {
+	    struct collect_static_trace_data_action *raction;
+
+	    raction = xmalloc (sizeof *raction);
+	    raction->base.type = *act;
+	    action = &raction->base;
+
+	    trace_debug ("Want to collect static trace data");
+	    ++act;
+	    break;
+	  }
 	case 'S':
 	  trace_debug ("Unexpected step action, ignoring");
 	  ++act;
@@ -2147,6 +2274,17 @@ cmd_qtinit (char *packet)
   write_ok (packet);
 }
 
+/* Unprobe the UST marker at ADDRESS.  */
+
+static void
+unprobe_marker_at (CORE_ADDR address)
+{
+  char cmd[CMD_BUF_SIZE];
+
+  sprintf (cmd, "unprobe_marker_at:%s", paddress (address));
+  run_inferior_command (cmd);
+}
+
 /* Restore the program to its pre-tracing state.  This routine may be called
    in error situations, so it needs to be careful about only restoring
    from known-valid bits.  */
@@ -2186,6 +2324,19 @@ clear_installed_tracepoints (void)
 	case fast_tracepoint:
 	  delete_fast_tracepoint_jump (tpoint->handle);
 	  break;
+	case static_tracepoint:
+	  if (prev_stpoint != NULL
+	      && prev_stpoint->address == tpoint->address)
+	    /* Nothing to do.  We already unprobed a tracepoint set at
+	       this marker address (and there can only be one probe
+	       per marker).  */
+	    ;
+	  else
+	    {
+	      unprobe_marker_at (tpoint->address);
+	      prev_stpoint = tpoint;
+	    }
+	  break;
 	}
 
       tpoint->handle = NULL;
@@ -2258,6 +2409,11 @@ cmd_qtdp (char *own_buf)
 	      packet = unpack_varlen_hex (packet, &count);
 	      tpoint->orig_size = count;
 	    }
+	  else if (*packet == 'S')
+	    {
+	      tpoint->type = static_tracepoint;
+	      ++packet;
+	    }
 	  else if (*packet == 'X')
 	    {
 	      actparm = (char *) packet;
@@ -2570,12 +2726,39 @@ sort_tracepoints (void)
       }
 }
 
+/* Ask the IPA to probe the marker at ADDRESS.  Returns -1 if running
+   the command fails, or 0 otherwise.  If the command ran
+   successfully, but probing the marker failed, ERROUT will be filled
+   with the error to reply to GDB, and -1 is also returned.  This
+   allows directly passing IPA errors to GDB.  */
+
+static int
+probe_marker_at (CORE_ADDR address, char *errout)
+{
+  char cmd[CMD_BUF_SIZE];
+  int err;
+
+  sprintf (cmd, "probe_marker_at:%s", paddress (address));
+  err = run_inferior_command (cmd);
+
+  if (err == 0)
+    {
+      if (*cmd == 'E')
+	{
+	  strcpy (errout, cmd);
+	  return -1;
+	}
+    }
+
+  return err;
+}
+
 #define MAX_JUMP_SIZE 20
 
 static void
 cmd_qtstart (char *packet)
 {
-  struct tracepoint *tpoint, *prev_ftpoint;
+  struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint;
   int slow_tracepoint_count, fast_count;
   CORE_ADDR jump_entry;
 
@@ -2614,6 +2797,9 @@ cmd_qtstart (char *packet)
   /* No previous fast tpoint yet.  */
   prev_ftpoint = NULL;
 
+  /* No previous static tpoint yet.  */
+  prev_stpoint = NULL;
+
   *packet = '\0';
 
   /* Install tracepoints.  */
@@ -2699,6 +2885,32 @@ cmd_qtstart (char *packet)
 		}
 	    }
 	}
+      else if (tpoint->type == static_tracepoint)
+	{
+	  if (maybe_write_ipa_ust_not_loaded (packet))
+	    {
+	      trace_debug ("Requested a static tracepoint, but static "
+			   "tracepoints are not supported.");
+	      break;
+	    }
+
+	  /* Can only probe a given marker once.  */
+	  if (prev_stpoint != NULL && prev_stpoint->address == tpoint->address)
+	    {
+	      tpoint->handle = (void *) -1;
+	    }
+	  else
+	    {
+	      if (probe_marker_at (tpoint->address, packet) == 0)
+		{
+		  tpoint->handle = (void *) -1;
+
+		  /* So that we can handle multiple static tracepoints
+		     at the same address easily.  */
+		  prev_stpoint = tpoint;
+		}
+	    }
+	}
 
       /* Any failure in the inner loop is sufficient cause to give
 	 up.  */
@@ -3039,6 +3251,8 @@ response_tracepoint (char *packet, struc
 	   tpoint->pass_count);
   if (tpoint->type == fast_tracepoint)
     sprintf (packet + strlen (packet), ":F%x", tpoint->orig_size);
+  else if (tpoint->type == static_tracepoint)
+    sprintf (packet + strlen (packet), ":S");
 
   if (tpoint->cond)
     {
@@ -3213,6 +3427,36 @@ cmd_qtsv (char *packet)
     strcpy (packet, "l");
 }
 
+/* Return the first static tracepoint marker, and initialize the state
+   machine that will iterate through all the static tracepoints
+   markers.  */
+
+static void
+cmd_qtfstm (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet);
+}
+
+/* Return additional static tracepoints markers.  */
+
+static void
+cmd_qtsstm (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet);
+}
+
+/* Return the definition of the static tracepoint at a given address.
+   Result packet is the same as qTsST's.  */
+
+static void
+cmd_qtstmat (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet);
+}
+
 /* Respond to qTBuffer packet with a block of raw data from the trace
    buffer.  GDB may ask for a lot, but we are allowed to reply with
    only as much as will fit within packet limits or whatever.  */
@@ -3384,6 +3628,21 @@ handle_tracepoint_query (char *packet)
       cmd_qtbuffer (packet);
       return 1;
     }
+  else if (strcmp ("qTfSTM", packet) == 0)
+    {
+      cmd_qtfstm (packet);
+      return 1;
+    }
+  else if (strcmp ("qTsSTM", packet) == 0)
+    {
+      cmd_qtsstm (packet);
+      return 1;
+    }
+  else if (strncmp ("qTSTMat:", packet, strlen ("qTSTMat:")) == 0)
+    {
+      cmd_qtstmat (packet);
+      return 1;
+    }
 
   return 0;
 }
@@ -3697,6 +3956,14 @@ tracepoint_was_hit (struct thread_info *
 
 #endif
 
+#if defined IN_PROCESS_AGENT && defined HAVE_UST
+struct ust_marker_data;
+static void collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
+					    CORE_ADDR stop_pc,
+					    struct tracepoint *tpoint,
+					    struct traceframe *tframe);
+#endif
+
 /* Create a trace frame for the hit of the given tracepoint in the
    given thread.  */
 
@@ -3803,6 +4070,25 @@ get_context_regcache (struct tracepoint_
 	}
       regcache = &fctx->regcache;
     }
+#ifdef HAVE_UST
+  if (ctx->type == static_tracepoint)
+    {
+      struct static_tracepoint_ctx *sctx = (struct static_tracepoint_ctx *) ctx;
+      if (!sctx->regcache_initted)
+	{
+	  sctx->regcache_initted = 1;
+	  init_register_cache (&sctx->regcache, sctx->regspace);
+	  supply_regblock (&sctx->regcache, NULL);
+	  /* Pass down the tracepoint address, because REGS doesn't
+	     include the PC, but we know what it must have been.  */
+	  supply_static_tracepoint_registers (&sctx->regcache,
+					      (const unsigned char *)
+					      sctx->regs,
+					      sctx->tpoint->address);
+	}
+      regcache = &sctx->regcache;
+    }
+#endif
 #else
   if (ctx->type == trap_tracepoint)
     {
@@ -3910,6 +4196,18 @@ do_action_at_tracepoint (struct tracepoi
 	  }
       }
       break;
+    case 'L':
+      {
+#if defined IN_PROCESS_AGENT && defined HAVE_UST
+	trace_debug ("Want to collect static trace data");
+	collect_ust_data_at_tracepoint (ctx, stop_pc,
+					tpoint, tframe);
+#else
+	trace_debug ("warning: collecting static trace data, "
+		     "but static tracepoints are not supported");
+#endif
+      }
+      break;
     default:
       trace_debug ("unknown trace action '%c', ignoring", taction->type);
       break;
@@ -4494,6 +4792,11 @@ traceframe_find_block_type (unsigned cha
 	  /* Skip over the TSV block.  */
 	  dataptr += (sizeof (int) + sizeof (LONGEST));
 	  break;
+	case 'S':
+	  /* Skip over the static trace data block.  */
+	  memcpy (&mlen, dataptr, sizeof (mlen));
+	  dataptr += (sizeof (mlen) + mlen);
+	  break;
 	default:
 	  trace_debug ("traceframe %d has unknown block type 0x%x",
 		       tfnum, blocktype);
@@ -4684,6 +4987,59 @@ traceframe_read_tsv (int tsvnum, LONGEST
   return 1;
 }
 
+/* Read a requested block of static tracepoint data from a trace
+   frame.  */
+
+int
+traceframe_read_sdata (int tfnum, ULONGEST offset,
+		       unsigned char *buf, ULONGEST length,
+		       ULONGEST *nbytes)
+{
+  struct traceframe *tframe;
+  unsigned char *database, *dataptr;
+  unsigned int datasize;
+  unsigned short mlen;
+
+  trace_debug ("traceframe_read_sdata");
+
+  tframe = find_traceframe (tfnum);
+
+  if (!tframe)
+    {
+      trace_debug ("traceframe %d not found", tfnum);
+      return 1;
+    }
+
+  datasize = tframe->data_size;
+  database = &tframe->data[0];
+
+  /* Iterate through a traceframe's blocks, looking for static
+     tracepoint data.  */
+  dataptr = traceframe_find_block_type (database, datasize,
+					tfnum, 'S');
+  if (dataptr != NULL)
+    {
+      memcpy (&mlen, dataptr, sizeof (mlen));
+      dataptr += sizeof (mlen);
+      if (offset < mlen)
+	{
+	  if (offset + length > mlen)
+	    length = mlen - offset;
+
+	  memcpy (buf, dataptr, length);
+	  *nbytes = length;
+	}
+      else
+	*nbytes = 0;
+      return 0;
+    }
+
+  trace_debug ("traceframe %d has no static trace data", tfnum);
+
+  *nbytes = 0;
+  return 0;
+}
+
 /* Return the first fast tracepoint whose jump pad contains PC.  */
 
 static struct tracepoint *
@@ -5631,7 +5987,8 @@ download_tracepoints (void)
     {
       struct tracepoint target_tracepoint;
 
-      if (tpoint->type != fast_tracepoint)
+      if (tpoint->type != fast_tracepoint
+	  && tpoint->type != static_tracepoint)
 	continue;
 
       /* Maybe download a compiled condition.  */
@@ -5742,6 +6099,14 @@ download_tracepoints (void)
 		       expr);
 		    break;
 		  }
+		case 'L':
+		  ipa_action = target_malloc
+		    (sizeof (struct collect_static_trace_data_action));
+		  write_inferior_memory
+		    (ipa_action,
+		     (unsigned char *) action,
+		     sizeof (struct collect_static_trace_data_action));
+		  break;
 		default:
 		  trace_debug ("unknown trace action '%c', ignoring",
 			       action->type);
@@ -6087,20 +6452,901 @@ upload_fast_traceframes (void)
 
 #ifdef IN_PROCESS_AGENT
 
-#include <sys/mman.h>
-#include <fcntl.h>
+IP_AGENT_EXPORT int ust_loaded;
+IP_AGENT_EXPORT char cmd_buf[CMD_BUF_SIZE];
 
-IP_AGENT_EXPORT char *gdb_tp_heap_buffer;
-IP_AGENT_EXPORT char *gdb_jump_pad_buffer;
-IP_AGENT_EXPORT char *gdb_jump_pad_buffer_end;
+#ifdef HAVE_UST
 
-static void __attribute__ ((constructor))
-initialize_tracepoint_ftlib (void)
+/* Static tracepoints.  */
+
+/* UST puts a "struct tracepoint" in the global namespace, which
+   conflicts with our tracepoint.  Arguably, being a library, it
+   shouldn't take ownership of such a generic name.  We work around it
+   here.  */
+#define tracepoint ust_tracepoint
+#include <ust/ust.h>
+#undef tracepoint
+
+extern int serialize_to_text (char *outbuf, int bufsize,
+			      const char *fmt, va_list ap);
+
+#define GDB_PROBE_NAME "gdb"
+
+/* We dynamically search for the UST symbols instead of linking them
+   in.  This lets the user decide if the application uses static
+   tracepoints, instead of always pulling libust.so in.  This vector
+   holds pointers to all functions we care about.  */
+
+static struct
 {
-  initialize_tracepoint ();
+  int (*serialize_to_text) (char *outbuf, int bufsize,
+			    const char *fmt, va_list ap);
+
+  int (*ltt_probe_register) (struct ltt_available_probe *pdata);
+  int (*ltt_probe_unregister) (struct ltt_available_probe *pdata);
+
+  int (*ltt_marker_connect) (const char *channel, const char *mname,
+			     const char *pname);
+  int (*ltt_marker_disconnect) (const char *channel, const char *mname,
+				const char *pname);
+
+  void (*marker_iter_start) (struct marker_iter *iter);
+  void (*marker_iter_next) (struct marker_iter *iter);
+  void (*marker_iter_stop) (struct marker_iter *iter);
+  void (*marker_iter_reset) (struct marker_iter *iter);
+} ust_ops;
+
+#include <dlfcn.h>
+
+/* Cast through typeof to catch incompatible API changes.  Since UST
+   only builds with gcc, we can freely use gcc extensions here
+   too.  */
+#define GET_UST_SYM(SYM)					\
+  do								\
+    {								\
+      if (ust_ops.SYM == NULL)					\
+	ust_ops.SYM = (typeof (&SYM)) dlsym (RTLD_DEFAULT, #SYM);	\
+      if (ust_ops.SYM == NULL)					\
+	return 0;						\
+    } while (0)
+
+#define USTF(SYM) ust_ops.SYM
+
+/* Get pointers to all libust.so functions we care about.  */
+
+static int
+dlsym_ust (void)
+{
+  GET_UST_SYM (serialize_to_text);
+
+  GET_UST_SYM (ltt_probe_register);
+  GET_UST_SYM (ltt_probe_unregister);
+  GET_UST_SYM (ltt_marker_connect);
+  GET_UST_SYM (ltt_marker_disconnect);
+
+  GET_UST_SYM (marker_iter_start);
+  GET_UST_SYM (marker_iter_next);
+  GET_UST_SYM (marker_iter_stop);
+  GET_UST_SYM (marker_iter_reset);
+
+  ust_loaded = 1;
+  return 1;
 }
 
-#endif
+/* Given an UST marker, return the matching gdb static tracepoint.
+   The match is done by address.  */
+
+static struct tracepoint *
+ust_marker_to_static_tracepoint (const struct marker *mdata)
+{
+  struct tracepoint *tpoint;
+
+  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
+    {
+      if (!tpoint->enabled || tpoint->type != static_tracepoint)
+	continue;
+
+      if (tpoint->address == (uintptr_t) mdata->location)
+	return tpoint;
+    }
+
+  return NULL;
+}
+
+/* The probe function we install on lttng/ust markers.  Whenever a
+   probed ust marker is hit, this function is called.  This is similar
+   to gdb_collect, only for static tracepoints, instead of fast
+   tracepoints.  */
+
+static void
+gdb_probe (const struct marker *mdata, void *probe_private,
+	   struct registers *regs, void *call_private,
+	   const char *fmt, va_list *args)
+{
+  struct tracepoint *tpoint;
+  struct static_tracepoint_ctx ctx;
+
+  /* Don't do anything until the trace run is completely set up.  */
+  if (!tracing)
+    {
+      trace_debug ("gdb_probe: not tracing\n");
+      return;
+    }
+
+  ctx.base.type = static_tracepoint;
+  ctx.regcache_initted = 0;
+  ctx.regs = regs;
+  ctx.fmt = fmt;
+  ctx.args = args;
+
+  /* Wrap the regblock in a register cache (in the stack, we don't
+     want to malloc here).  */
+  ctx.regspace = alloca (register_cache_size ());
+  if (ctx.regspace == NULL)
+    {
+      trace_debug ("Trace buffer block allocation failed, skipping");
+      return;
+    }
+
+  tpoint = ust_marker_to_static_tracepoint (mdata);
+  if (tpoint == NULL)
+    {
+      trace_debug ("gdb_probe: marker not known: "
+		   "loc:0x%p, ch:\"%s\",n:\"%s\",f:\"%s\"",
+		   mdata->location, mdata->channel,
+		   mdata->name, mdata->format);
+      return;
+    }
+
+  ctx.tpoint = tpoint;
+
+  trace_debug ("gdb_probe: collecting marker: "
+	       "loc:0x%p, ch:\"%s\",n:\"%s\",f:\"%s\"",
+	       mdata->location, mdata->channel,
+	       mdata->name, mdata->format);
+
+  /* Test the condition if present, and collect if true.  */
+  if (tpoint->cond == NULL
+      || condition_true_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
+				       tpoint))
+    {
+      collect_data_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
+				  tpoint->address, tpoint);
+
+      if (stopping_tracepoint
+	  || trace_buffer_is_full
+	  || expr_eval_result != expr_eval_no_error)
+	stop_tracing ();
+    }
+  else
+    {
+      /* If there was a condition and it evaluated to false, the only
+	 way we would stop tracing is if there was an error during
+	 condition expression evaluation.  */
+      if (expr_eval_result != expr_eval_no_error)
+	stop_tracing ();
+    }
+}
+
+/* Called if the gdb static tracepoint requested collecting "$_sdata",
+   static tracepoint string data.  This is a string passed to the
+   tracing library by the user, at the time of the tracepoint marker
+   call.  E.g., in the UST marker call:
+
+     trace_mark (ust, bar33, "str %s", "FOOBAZ");
+
+   the collected data is "str FOOBAZ".
+*/
+
+static void
+collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
+				CORE_ADDR stop_pc,
+				struct tracepoint *tpoint,
+				struct traceframe *tframe)
+{
+  struct static_tracepoint_ctx *umd = (struct static_tracepoint_ctx *) ctx;
+  unsigned char *bufspace;
+  int size;
+  va_list copy;
+  unsigned short blocklen;
+
+  if (umd == NULL)
+    {
+      trace_debug ("Wanted to collect static trace data, "
+		   "but there's no static trace data");
+      return;
+    }
+
+  va_copy (copy, *umd->args);
+  size = USTF(serialize_to_text) (NULL, 0, umd->fmt, copy);
+  va_end (copy);
+
+  trace_debug ("Want to collect ust data");
+
+  /* 'S' + size + string */
+  bufspace = add_traceframe_block (tframe,
+				   1 + sizeof (blocklen) + size + 1);
+  if (bufspace == NULL)
+    {
+      trace_debug ("Trace buffer block allocation failed, skipping");
+      return;
+    }
+
+  /* Identify a static trace data block.  */
+  *bufspace = 'S';
+
+  blocklen = size + 1;
+  memcpy (bufspace + 1, &blocklen, sizeof (blocklen));
+
+  va_copy (copy, *umd->args);
+  USTF(serialize_to_text) ((char *) bufspace + 1 + sizeof (blocklen),
+			   size + 1, umd->fmt, copy);
+  va_end (copy);
+
+  trace_debug ("Storing static tracepoint data in regblock: %s",
+	       bufspace + 1 + sizeof (blocklen));
+}
+
+/* The probe to register with lttng/ust.  */
+static struct ltt_available_probe gdb_ust_probe =
+  {
+    GDB_PROBE_NAME,
+    NULL,
+    gdb_probe,
+  };
+
+#endif /* HAVE_UST */
+#endif /* IN_PROCESS_AGENT */
+
+#ifdef HAVE_UST
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
+#endif
+
+/* Where we put the socked used for synchronization.  */
+#define SOCK_DIR P_tmpdir
+
+#endif /* HAVE_UST */
+
+#ifndef IN_PROCESS_AGENT
+
+#ifdef HAVE_UST
+
+static int
+gdb_ust_connect_sync_socket (int pid)
+{
+  struct sockaddr_un addr;
+  int res, fd;
+  char path[UNIX_PATH_MAX];
+
+  res = snprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", SOCK_DIR, pid);
+  if (res >= UNIX_PATH_MAX)
+    {
+      trace_debug ("string overflow allocating socket name");
+      return -1;
+    }
+
+  res = fd = socket (PF_UNIX, SOCK_STREAM, 0);
+  if (res == -1)
+    {
+      warning ("error opening sync socket: %s\n", strerror (errno));
+      return -1;
+    }
+
+  addr.sun_family = AF_UNIX;
+
+  res = snprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
+  if (res >= UNIX_PATH_MAX)
+    {
+      warning ("string overflow allocating socket name\n");
+      close (fd);
+      return -1;
+    }
+
+  res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
+  if (res == -1)
+    {
+      warning ("error connecting sync socket (%s): %s. "
+	       "Make sure the directory exists and that it is writable.",
+	       path, strerror (errno));
+      close (fd);
+      return -1;
+    }
+
+  return fd;
+}
+
+/* Resume thread PTID.  */
+
+static void
+resume_thread (ptid_t ptid)
+{
+  struct thread_resume resume_info;
+
+  resume_info.thread = ptid;
+  resume_info.kind = resume_continue;
+  resume_info.sig = TARGET_SIGNAL_0;
+  (*the_target->resume) (&resume_info, 1);
+}
+
+/* Stop thread PTID.  */
+
+static void
+stop_thread (ptid_t ptid)
+{
+  struct thread_resume resume_info;
+
+  resume_info.thread = ptid;
+  resume_info.kind = resume_stop;
+  resume_info.sig = TARGET_SIGNAL_0;
+  (*the_target->resume) (&resume_info, 1);
+}
+
+/* Ask the in-process agent to run a command.  Since we don't want to
+   have to handle the IPA hitting breakpoints while running the
+   command, we pause all threads, remove all breakpoints, and then set
+   the helper thread re-running.  We communicate with the helper
+   thread by means of direct memory xfering, and a socket for
+   synchronization.  */
+
+static int
+run_inferior_command (char *cmd)
+{
+  int err = -1;
+  int fd = -1;
+  int pid = ptid_get_pid (current_inferior->entry.id);
+  int tid;
+  ptid_t ptid = null_ptid;
+
+  trace_debug ("run_inferior_command: running: %s", cmd);
+
+  pause_all (0);
+  uninsert_all_breakpoints ();
+
+  if (read_inferior_integer (ipa_sym_addrs.addr_helper_thread_id, &tid))
+    {
+      warning ("Error reading helper thread's id in lib");
+      goto out;
+    }
+
+  if (tid == 0)
+    {
+      warning ("helper thread not initialized yet");
+      goto out;
+    }
+
+  if (write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
+			     (unsigned char *) cmd, strlen (cmd) + 1))
+    {
+      warning ("Error writing command");
+      goto out;
+    }
+
+  ptid = ptid_build (pid, tid, 0);
+
+  resume_thread (ptid);
+
+  fd = gdb_ust_connect_sync_socket (pid);
+  if (fd >= 0)
+    {
+      char buf[1] = "";
+      int ret;
+
+      trace_debug ("signalling helper thread");
+
+      do
+	{
+	  ret = write (fd, buf, 1);
+	} while (ret == -1 && errno == EINTR);
+
+      trace_debug ("waiting for helper thread's response");
+
+      do
+	{
+	  ret = read (fd, buf, 1);
+	} while (ret == -1 && errno == EINTR);
+
+      close (fd);
+
+      trace_debug ("helper thread's response received");
+    }
+
+ out:
+
+  /* Need to read response with the inferior stopped.  */
+  if (!ptid_equal (ptid, null_ptid))
+    {
+      int was_non_stop = non_stop;
+      struct target_waitstatus status;
+
+      stop_thread (ptid);
+      non_stop = 1;
+      mywait (ptid, &status, 0, 0);
+      non_stop = was_non_stop;
+    }
+
+  if (fd >= 0)
+    {
+      if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
+				(unsigned char *) cmd, CMD_BUF_SIZE))
+	{
+	  warning ("Error reading command response");
+	}
+      else
+	{
+	  err = 0;
+	  trace_debug ("run_inferior_command: response: %s", cmd);
+	}
+    }
+
+  reinsert_all_breakpoints ();
+  unpause_all (0);
+
+  return err;
+}
+
+#else /* HAVE_UST */
+
+static int
+run_inferior_command (char *cmd)
+{
+  return -1;
+}
+
+#endif /* HAVE_UST */
+
+#else /* !IN_PROCESS_AGENT */
+
+/* Thread ID of the helper thread.  GDBserver reads this to know which
+   is the help thread.  This is an LWP id on Linux.  */
+int helper_thread_id;
+
+#ifdef HAVE_UST
+
+static int
+init_named_socket (const char *name)
+{
+  int result, fd;
+  struct sockaddr_un addr;
+
+  result = fd = socket (PF_UNIX, SOCK_STREAM, 0);
+  if (result == -1)
+    {
+      warning ("socket creation failed: %s", strerror (errno));
+      return -1;
+    }
+
+  addr.sun_family = AF_UNIX;
+
+  strncpy (addr.sun_path, name, UNIX_PATH_MAX);
+  addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
+
+  result = access (name, F_OK);
+  if (result == 0)
+    {
+      /* File exists.  */
+      result = unlink (name);
+      if (result == -1)
+	{
+	  warning ("unlink failed: %s", strerror (errno));
+	  close (fd);
+	  return -1;
+	}
+      warning ("socket %s already exists; overwriting", name);
+    }
+
+  result = bind (fd, (struct sockaddr *) &addr, sizeof (addr));
+  if (result == -1)
+    {
+      warning ("bind failed: %s", strerror (errno));
+      close (fd);
+      return -1;
+    }
+
+  result = listen (fd, 1);
+  if (result == -1)
+    {
+      warning ("listen: %s", strerror (errno));
+      close (fd);
+      return -1;
+    }
+
+  return fd;
+}
+
+static int
+gdb_ust_socket_init (void)
+{
+  int result, fd;
+  char name[UNIX_PATH_MAX];
+
+  result = snprintf (name, UNIX_PATH_MAX, "%s/gdb_ust%d",
+		     SOCK_DIR, getpid ());
+  if (result >= UNIX_PATH_MAX)
+    {
+      trace_debug ("string overflow allocating socket name");
+      return -1;
+    }
+
+  fd = init_named_socket (name);
+  if (fd < 0)
+    warning ("Error initializing named socket (%s) for communication with the "
+	     "ust helper thread. Check that directory exists and that it "
+	     "is writable.", name);
+
+  return fd;
+}
+
+/* Return an hexstr version of the STR C string, fit for sending to
+   GDB.  */
+
+static char *
+cstr_to_hexstr (const char *str)
+{
+  int len = strlen (str);
+  char *hexstr = xmalloc (len * 2 + 1);
+  convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
+  return hexstr;
+}
+
+/* The next marker to be returned on a qTsST command.  */
+static const struct marker *next_st;
+
+/* Returns the first known marker.  */
+
+struct marker *
+first_marker (void)
+{
+  struct marker_iter iter;
+
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
+
+  return iter.marker;
+}
+
+/* Returns the marker following M.  */
+
+const struct marker *
+next_marker (const struct marker *m)
+{
+  struct marker_iter iter;
+
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
+
+  for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
+    {
+      if (iter.marker == m)
+	{
+	  USTF(marker_iter_next) (&iter);
+	  return iter.marker;
+	}
+    }
+
+  return NULL;
+}
+
+/* Compose packet that is the response to the qTsSTM/qTfSTM/qTST;at
+   packets.  */
+
+static void
+response_ust_marker (char *packet, const struct marker *st)
+{
+  char *strid, *format, *tmp;
+
+  next_st = next_marker (st);
+
+  tmp = xmalloc (strlen (st->channel) + 1 +
+		 strlen (st->name) + 1);
+  sprintf (tmp, "%s/%s", st->channel, st->name);
+
+  strid = cstr_to_hexstr (tmp);
+  free (tmp);
+
+  format = cstr_to_hexstr (st->format);
+
+  sprintf (packet, "m%s:%s:%s",
+	   paddress ((uintptr_t) st->location),
+	   strid,
+	   format);
+
+  free (strid);
+  free (format);
+}
+
+/* Return the first static tracepoint, and initialize the state
+   machine that will iterate through all the static tracepoints.  */
+
+static void
+cmd_qtfstm (char *packet)
+{
+  trace_debug ("Returning first trace state variable definition");
+
+  if (first_marker ())
+    response_ust_marker (packet, first_marker ());
+  else
+    strcpy (packet, "l");
+}
+
+/* Return additional trace state variable definitions. */
+
+static void
+cmd_qtsstm (char *packet)
+{
+  trace_debug ("Returning static tracepoint");
+
+  if (next_st)
+    response_ust_marker (packet, next_st);
+  else
+    strcpy (packet, "l");
+}
+
+/* Disconnect the GDB probe from a marker at a given address.  */
+
+static void
+unprobe_marker_at (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+
+  p += sizeof ("unprobe_marker_at:") - 1;
+
+  p = unpack_varlen_hex (p, &address);
+
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
+  for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
+    if ((uintptr_t ) iter.marker->location == address)
+      {
+	int result;
+
+	result = USTF(ltt_marker_disconnect) (iter.marker->channel,
+					      iter.marker->name,
+					      GDB_PROBE_NAME);
+	if (result < 0)
+	  warning ("could not disable marker %s/%s",
+		   iter.marker->channel, iter.marker->name);
+	break;
+      }
+}
+
+/* Connect the GDB probe to a marker at a given address.  */
+
+static int
+probe_marker_at (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+  struct marker *m;
+
+  p += sizeof ("probe_marker_at:") - 1;
+
+  p = unpack_varlen_hex (p, &address);
+
+  USTF(marker_iter_reset) (&iter);
+
+  for (USTF(marker_iter_start) (&iter), m = iter.marker;
+       m != NULL;
+       USTF(marker_iter_next) (&iter), m = iter.marker)
+    if ((uintptr_t ) m->location == address)
+      {
+	int result;
+
+	trace_debug ("found marker for address.  "
+		     "ltt_marker_connect (marker = %s/%s)",
+		     m->channel, m->name);
+
+	result = USTF(ltt_marker_connect) (m->channel, m->name, GDB_PROBE_NAME);
+	if (result && result != -EEXIST)
+	  trace_debug ("ltt_marker_connect (marker = %s/%s, errno = %d)",
+		       m->channel, m->name, -result);
+
+	if (result < 0)
+	  {
+	    sprintf (packet, "E.could not connect marker: channel=%s, name=%s",
+		     m->channel, m->name);
+	    return -1;
+	  }
+
+	strcpy (packet, "OK");
+	return 0;
+      }
+
+  sprintf (packet, "E.no marker found at 0x%s", paddress (address));
+  return -1;
+}
+
+static int
+cmd_qtstmat (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+  struct marker *m;
+
+  p += sizeof ("qTSTMat:") - 1;
+
+  p = unpack_varlen_hex (p, &address);
+
+  USTF(marker_iter_reset) (&iter);
+
+  for (USTF(marker_iter_start) (&iter), m = iter.marker;
+       m != NULL;
+       USTF(marker_iter_next) (&iter), m = iter.marker)
+    if ((uintptr_t ) m->location == address)
+      {
+	response_ust_marker (packet, m);
+	return 0;
+      }
+
+  strcpy (packet, "l");
+  return -1;
+}
+
+static void *
+gdb_ust_thread (void *arg)
+{
+  int listen_fd;
+
+  while (1)
+    {
+      listen_fd = gdb_ust_socket_init ();
+
+#ifdef SYS_gettid
+      if (helper_thread_id == 0)
+	helper_thread_id = syscall (SYS_gettid);
+#endif
+
+      if (listen_fd == -1)
+	{
+	  warning ("could not create sync socket\n");
+	  break;
+	}
+
+      while (1)
+	{
+	  socklen_t tmp;
+	  struct sockaddr_un sockaddr;
+	  int fd;
+	  char buf[1];
+	  int ret;
+
+	  tmp = sizeof (sockaddr);
+
+	  do
+	    {
+	      fd = accept (listen_fd, &sockaddr, &tmp);
+	    }
+	  /* It seems an ERESTARTSYS can escape out of accept.  */
+	  while (fd == -512 || (fd == -1 && errno == EINTR));
+
+	  if (fd < 0)
+	    {
+	      warning ("Accept returned %d, error: %s\n",
+		       fd, strerror (errno));
+	      break;
+	    }
+
+	  do
+	    {
+	      ret = read (fd, buf, 1);
+	    } while (ret == -1 && errno == EINTR);
+
+	  if (ret == -1)
+	    {
+	      warning ("reading socket (fd=%d) failed with %s",
+		       fd, strerror (errno));
+	      close (fd);
+	      break;
+	    }
+
+	  if (cmd_buf[0])
+	    {
+	      if (strcmp ("qTfSTM", cmd_buf) == 0)
+		{
+		  cmd_qtfstm (cmd_buf);
+		}
+	      else if (strcmp ("qTsSTM", cmd_buf) == 0)
+		{
+		  cmd_qtsstm (cmd_buf);
+		}
+	      else if (strncmp ("unprobe_marker_at:",
+				cmd_buf,
+				sizeof ("unprobe_marker_at:") - 1) == 0)
+		{
+		  unprobe_marker_at (cmd_buf);
+		}
+	      else if (strncmp ("probe_marker_at:",
+				cmd_buf,
+				sizeof ("probe_marker_at:") - 1) == 0)
+		{
+		  probe_marker_at (cmd_buf);
+		}
+	      else if (strncmp ("qTSTMat:",
+				cmd_buf,
+				sizeof ("qTSTMat:") - 1) == 0)
+		{
+		  cmd_qtstmat (cmd_buf);
+		}
+	      else if (strcmp (cmd_buf, "help") == 0)
+		{
+		  strcpy (cmd_buf, "for help, press F1\n");
+		}
+	      else
+		strcpy (cmd_buf, "");
+	    }
+
+	  write (fd, buf, 1);
+	  close (fd);
+	}
+    }
+
+  return NULL;
+}
+
+#include <signal.h>
+
+static void
+gdb_ust_init (void)
+{
+  int res;
+  pthread_t thread;
+  sigset_t new_mask;
+  sigset_t orig_mask;
+
+  if (!dlsym_ust ())
+    return;
+
+  /* We want the helper thread to be as transparent as possible, so
+     have it inherit an all-signals-blocked mask.  */
+
+  sigfillset (&new_mask);
+  res = pthread_sigmask (SIG_SETMASK, &new_mask, &orig_mask);
+  if (res)
+    fatal ("pthread_sigmask (1) failed: %s", strerror (res));
+
+  res = pthread_create (&thread,
+			NULL,
+			gdb_ust_thread,
+			NULL);
+
+  res = pthread_sigmask (SIG_SETMASK, &orig_mask, NULL);
+  if (res)
+    fatal ("pthread_sigmask (2) failed: %s", strerror (res));
+
+  while (helper_thread_id == 0)
+    usleep (1);
+
+  USTF(ltt_probe_register) (&gdb_ust_probe);
+}
+
+#endif /* HAVE_UST */
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+IP_AGENT_EXPORT char *gdb_tp_heap_buffer;
+IP_AGENT_EXPORT char *gdb_jump_pad_buffer;
+IP_AGENT_EXPORT char *gdb_jump_pad_buffer_end;
+
+static void __attribute__ ((constructor))
+initialize_tracepoint_ftlib (void)
+{
+  initialize_tracepoint ();
+
+#ifdef HAVE_UST
+  gdb_ust_init ();
+#endif
+}
+
+#endif /* IN_PROCESS_AGENT */
 
 static LONGEST
 tsv_get_timestamp (void)
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/breakpoint.c	2010-06-28 13:23:58.000000000 +0100
@@ -837,7 +837,9 @@ check_no_tracepoint_commands (struct com
 int
 is_tracepoint (const struct breakpoint *b)
 {
-  return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
+  return (b->type == bp_tracepoint
+	  || b->type == bp_fast_tracepoint
+	  || b->type == bp_static_tracepoint);
 }
   
 /* A helper function that validsates that COMMANDS are valid for a
@@ -861,7 +863,11 @@ validate_commands_for_breakpoint (struct
 	  if (c->control_type == while_stepping_control)
 	    {
 	      if (b->type == bp_fast_tracepoint)
-		error (_("The 'while-stepping' command cannot be used for fast tracepoint"));
+		error (_("\
+The 'while-stepping' command cannot be used for fast tracepoint"));
+	      else if (b->type == bp_static_tracepoint)
+		error (_("\
+The 'while-stepping' command cannot be used for static tracepoint"));
 
 	      if (while_stepping)
 		error (_("The 'while-stepping' command can be used only once"));
@@ -888,6 +894,27 @@ validate_commands_for_breakpoint (struct
     }
 }
 
+/* Return a vector of all the static tracepoints set at ADDR.  The
+   caller is responsible for releasing the vector.  */
+
+VEC(breakpoint_p) *
+static_tracepoints_here (CORE_ADDR addr)
+{
+  struct breakpoint *b;
+  VEC(breakpoint_p) *found = 0;
+  struct bp_location *loc;
+
+  ALL_BREAKPOINTS (b)
+    if (b->type == bp_static_tracepoint)
+      {
+	for (loc = b->loc; loc; loc = loc->next)
+	  if (loc->address == addr)
+	    VEC_safe_push(breakpoint_p, found, b);
+      }
+
+  return found;
+}
+
 /* Set the command list of B to COMMANDS.  If breakpoint is tracepoint,
    validate that only allowed commands are included.
 */
@@ -4420,6 +4447,7 @@ bpstat_what (bpstat bs)
 	  break;
 	case bp_tracepoint:
 	case bp_fast_tracepoint:
+	case bp_static_tracepoint:
 	  /* Tracepoint hits should not be reported back to GDB, and
 	     if one got through somehow, it should have been filtered
 	     out already.  */
@@ -4553,6 +4581,7 @@ print_one_breakpoint_location (struct br
     {bp_catchpoint, "catchpoint"},
     {bp_tracepoint, "tracepoint"},
     {bp_fast_tracepoint, "fast tracepoint"},
+    {bp_static_tracepoint, "static tracepoint"},
     {bp_jit_event, "jit events"},
   };
   
@@ -4685,6 +4714,7 @@ print_one_breakpoint_location (struct br
       case bp_std_terminate_master:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_jit_event:
 	if (opts.addressprint)
 	  {
@@ -4755,6 +4785,16 @@ print_one_breakpoint_location (struct br
   
   ui_out_text (uiout, "\n");
   
+  if (!part_of_multiple && b->static_trace_id)
+    {
+      gdb_assert (b->type == bp_static_tracepoint);
+
+      ui_out_text (uiout, "\tstatic tracepoint marker id is ");
+      ui_out_field_string (uiout, "static-tracepoint-marker-string-id",
+			   b->static_trace_id);
+      ui_out_text (uiout, "\n");
+    }
+
   if (part_of_multiple && frame_id_p (b->frame_id))
     {
       annotate_field (6);
@@ -5411,6 +5451,7 @@ allocate_bp_location (struct breakpoint 
     case bp_catchpoint:
     case bp_tracepoint:
     case bp_fast_tracepoint:
+    case bp_static_tracepoint:
       loc->loc_type = bp_loc_other;
       break;
     default:
@@ -6787,6 +6828,16 @@ mention (struct breakpoint *b)
 	printf_filtered (_(" %d"), b->number);
 	say_where = 1;
 	break;
+      case bp_static_tracepoint:
+	if (ui_out_is_mi_like_p (uiout))
+	  {
+	    say_where = 0;
+	    break;
+	  }
+	printf_filtered (_("Static tracepoint"));
+	printf_filtered (_(" %d"), b->number);
+	say_where = 1;
+	break;
 
       case bp_until:
       case bp_finish:
@@ -6966,9 +7017,25 @@ create_breakpoint_sal (struct gdbarch *g
 	  b->ignore_count = ignore_count;
 	  b->enable_state = enabled ? bp_enabled : bp_disabled;
 	  b->disposition = disposition;
-
 	  b->pspace = sals.sals[0].pspace;
 
+	  if (type == bp_static_tracepoint)
+	    {
+	      struct static_tracepoint_marker marker;
+
+	      if (target_static_tracepoint_marker_at (sal.pc, &marker))
+		{
+		  b->static_trace_id = xstrdup (marker.str_id);
+		  release_static_tracepoint_marker (&marker);
+
+		  printf_filtered (_("Probed static tracepoint marker \"%s\"\n"),
+				   b->static_trace_id);
+		}
+	      else
+		warning (_("\
+Couldn't determine the static tracepoint marker to probe"));
+	    }
+
 	  if (enabled && b->pspace->executing_startup
 	      && (b->type == bp_breakpoint
 		  || b->type == bp_hardware_breakpoint))
@@ -7381,6 +7448,49 @@ find_condition_and_thread (char *tok, CO
     }
 }
 
+/* Decode a static tracepoint marker spec.  */
+
+static struct symtabs_and_lines
+decode_static_tracepoint_spec (char **arg_p)
+{
+  struct static_tracepoint_marker stmarker;
+  struct symtabs_and_lines sals;
+  struct symtab_and_line sal;
+  struct symbol *sym;
+  struct cleanup *old_chain;
+  char *p = &(*arg_p)[3];
+  char *endp;
+  char *marker;
+
+  while (*p == ' ' || *p == '\t')
+    p++;
+
+  endp = p;
+  while (*endp != ' ' && *endp != '\t' && *endp != '\0')
+    endp++;
+
+  marker = savestring (p, endp - p);
+  old_chain = make_cleanup (xfree, marker);
+
+  if (!target_static_tracepoint_marker_by_strid (marker, &stmarker))
+    error (_("No known static tracepoint marker named %s"), p);
+
+  init_sal (&sal);
+
+  sal.pc = stmarker.address;
+  sal = find_pc_line (stmarker.address, 0);
+
+  sals.nelts = 1;
+  sals.sals = xmalloc (sizeof *sals.sals);
+  sals.sals[0] = sal;
+
+  release_static_tracepoint_marker (&stmarker);
+  do_cleanups (old_chain);
+
+  *arg_p = endp;
+  return sals;
+}
+
 /* Set a breakpoint.  This function is shared between CLI and MI
    functions for setting a breakpoint.  This function has two major
    modes of operations, selected by the PARSE_CONDITION_AND_THREAD
@@ -7394,7 +7504,7 @@ int
 create_breakpoint (struct gdbarch *gdbarch,
 		   char *arg, char *cond_string, int thread,
 		   int parse_condition_and_thread,
-		   int tempflag, int hardwareflag, int traceflag,
+		   int tempflag, enum bptype type_wanted,
 		   int ignore_count,
 		   enum auto_boolean pending_break_support,
 		   struct breakpoint_ops *ops,
@@ -7413,7 +7523,6 @@ create_breakpoint (struct gdbarch *gdbar
   int i;
   int pending = 0;
   int not_found = 0;
-  enum bptype type_wanted;
   int task = 0;
   int prev_bkpt_count = breakpoint_count;
 
@@ -7426,6 +7535,18 @@ create_breakpoint (struct gdbarch *gdbar
   parse_args.addr_string_p = &addr_string;
   parse_args.not_found_ptr = &not_found;
 
+  if (type_wanted == bp_static_tracepoint
+      && (strncmp (arg, "-m", 2) == 0
+	  && (arg[2] == ' ' || arg[2] == '\t')))
+    {
+      sals = decode_static_tracepoint_spec (&arg);
+
+      copy_arg = savestring (addr_start, arg - addr_start);
+      addr_string = xmalloc (sizeof (char **));
+      addr_string[0] = copy_arg;
+      goto done;
+    }
+
   e = catch_exception (uiout, do_captured_parse_breakpoint, 
 		       &parse_args, RETURN_MASK_ALL);
 
@@ -7472,6 +7593,8 @@ create_breakpoint (struct gdbarch *gdbar
 	return 0;
     }
 
+  done:
+
   /* Create a chain of things that always need to be cleaned up. */
   old_chain = make_cleanup (null_cleanup, 0);
 
@@ -7503,10 +7626,6 @@ create_breakpoint (struct gdbarch *gdbar
   if (!pending)
     breakpoint_sals_to_pc (&sals, addr_start);
 
-  type_wanted = (traceflag
-		 ? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint)
-		 : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
-
   /* Fast tracepoints may have additional restrictions on location.  */
   if (type_wanted == bp_fast_tracepoint)
     check_fast_tracepoint_sals (gdbarch, &sals);
@@ -7599,13 +7718,15 @@ create_breakpoint (struct gdbarch *gdbar
 static void
 break_command_1 (char *arg, int flag, int from_tty)
 {
-  int hardwareflag = flag & BP_HARDWAREFLAG;
   int tempflag = flag & BP_TEMPFLAG;
+  enum bptype type_wanted = (flag & BP_HARDWAREFLAG
+			     ? bp_hardware_breakpoint
+			     : bp_breakpoint);
 
   create_breakpoint (get_current_arch (),
 		     arg,
 		     NULL, 0, 1 /* parse arg */,
-		     tempflag, hardwareflag, 0 /* traceflag */,
+		     tempflag, type_wanted,
 		     0 /* Ignore count */,
 		     pending_break_support,
 		     NULL /* breakpoint_ops */,
@@ -8578,7 +8699,7 @@ handle_gnu_v3_exceptions (int tempflag, 
   create_breakpoint (get_current_arch (),
 		     trigger_func_name, cond_string, -1,
 		     0 /* condition and thread are valid.  */,
-		     tempflag, 0, 0,
+		     tempflag, bp_breakpoint,
 		     0,
 		     AUTO_BOOLEAN_TRUE /* pending */,
 		     &gnu_v3_exception_catchpoint_ops, from_tty,
@@ -9630,6 +9751,119 @@ ambiguous_names_p (struct bp_location *l
   return 0;
 }
 
+/* When symbols change, it probably means the sources changed as well,
+   and it might mean the static tracepoint markers are no longer at
+   the same address or line numbers they used to be at last we
+   checked.  Losing your static tracepoints whenever you rebuild is
+   undesirable.  This function tries to resync/rematch gdb static
+   tracepoints with the markers on the target.  The heuristic is:
+
+   1) look for a marker at the old PC.  If one is found there, assume
+   to be the same marker.  If the name / string id of the marker found
+   is different from the previous known name, assume that means the
+   user renamed the marker in the sources, and output a warning.
+
+   2) If a marker is no longer found at the same address, it may mean
+   the marker no longer exists.  But it may also just mean the code
+   changed a bit.  Maybe the user added a few lines of code that made
+   the marker move up or down (in line number terms).  Ask the target
+   for info about the marker with the string id as we knew it.  If
+   found, update line number and address in the matching static
+   tracepoint.  */
+
+static struct symtab_and_line
+update_static_tracepoint (struct breakpoint *b,
+			  struct symtab_and_line sal)
+{
+  struct static_tracepoint_marker marker;
+  int i;
+
+  CORE_ADDR pc;
+
+  pc = sal.pc;
+  if (sal.line)
+    find_line_pc (sal.symtab, sal.line, &pc);
+
+  if (target_static_tracepoint_marker_at (pc, &marker))
+    {
+      if (strcmp (b->static_trace_id, marker.str_id) != 0)
+	warning (_("static tracepoint %d changed probed marker from %s to %s"),
+		 b->number,
+		 b->static_trace_id, marker.str_id);
+
+      xfree (b->static_trace_id);
+      b->static_trace_id = xstrdup (marker.str_id);
+      release_static_tracepoint_marker (&marker);
+
+      return sal;
+    }
+
+  /* Old marker wasn't found on target at lineno.  Try looking it up
+     by string ID.  */
+  if (!sal.explicit_pc
+      && sal.line != 0
+      && sal.symtab != NULL
+      && b->static_trace_id != NULL
+      && target_static_tracepoint_marker_by_strid (b->static_trace_id,
+						   &marker))
+    {
+      struct symtab_and_line sal;
+      struct symbol *sym;
+
+      xfree (b->static_trace_id);
+      b->static_trace_id = xstrdup (marker.str_id);
+
+      warning (_("marker for static tracepoint %d (%s) not "
+		 "found at previous line number"),
+	       b->number, b->static_trace_id);
+
+      init_sal (&sal);
+
+      sal.pc = marker.address;
+
+      sal = find_pc_line (marker.address, 0);
+      sym = find_pc_sect_function (marker.address, NULL);
+      ui_out_text (uiout, "Now in ");
+      if (sym)
+	{
+	  ui_out_field_string (uiout, "func",
+			       SYMBOL_PRINT_NAME (sym));
+	  ui_out_text (uiout, " at ");
+	}
+      ui_out_field_string (uiout, "file", sal.symtab->filename);
+      ui_out_text (uiout, ":");
+
+      if (ui_out_is_mi_like_p (uiout))
+	{
+	  char *fullname = symtab_to_fullname (sal.symtab);
+
+	  if (fullname)
+	    ui_out_field_string (uiout, "fullname", fullname);
+	}
+
+      ui_out_field_int (uiout, "line", sal.line);
+      ui_out_text (uiout, "\n");
+
+      b->line_number = sal.line;
+
+      xfree (b->source_file);
+      if (sym)
+	b->source_file = xstrdup (sal.symtab->filename);
+      else
+	b->source_file = NULL;
+
+      xfree (b->addr_string);
+      b->addr_string = xstrprintf ("%s:%d",
+				   sal.symtab->filename, b->line_number);
+
+      /* Might be nice to check if function changed, and warn if
+	 so.  */
+
+      release_static_tracepoint_marker (&marker);
+    }
+  return sal;
+}
+
 static void
 update_breakpoint_locations (struct breakpoint *b,
 			     struct symtabs_and_lines sals)
@@ -9760,6 +9994,7 @@ breakpoint_re_set_one (void *bint)
     case bp_hardware_breakpoint:
     case bp_tracepoint:
     case bp_fast_tracepoint:
+    case bp_static_tracepoint:
       /* Do not attempt to re-set breakpoints disabled during startup.  */
       if (b->enable_state == bp_startup_disabled)
 	return 0;
@@ -9780,8 +10015,13 @@ breakpoint_re_set_one (void *bint)
 
       TRY_CATCH (e, RETURN_MASK_ERROR)
 	{
-	  sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
-				not_found_ptr);
+	  if (b->type == bp_static_tracepoint
+	      && (strncmp (s, "-m", 2) == 0
+		  && (s[2] == ' ' || s[2] == '\t')))
+	    sals = decode_static_tracepoint_spec (&s);
+	  else
+	    sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
+				  not_found_ptr);
 	}
       if (e.reason < 0)
 	{
@@ -9831,6 +10071,9 @@ breakpoint_re_set_one (void *bint)
 	      b->condition_not_parsed = 0;
 	    }
 
+	  if (b->type == bp_static_tracepoint)
+	    sals.sals[0] = update_static_tracepoint (b, sals.sals[0]);
+
 	  expanded = expand_line_sal_maybe (sals.sals[0]);
 	}
 
@@ -10183,6 +10426,7 @@ disable_command (char *args, int from_tt
       case bp_breakpoint:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -10283,6 +10527,7 @@ enable_command (char *args, int from_tty
       case bp_breakpoint:
       case bp_tracepoint:
       case bp_fast_tracepoint:
+      case bp_static_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -10583,8 +10828,8 @@ trace_command (char *arg, int from_tty)
   if (create_breakpoint (get_current_arch (),
 			 arg,
 			 NULL, 0, 1 /* parse arg */,
-			 0 /* tempflag */, 0 /* hardwareflag */,
-			 1 /* traceflag */,
+			 0 /* tempflag */,
+			 bp_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
 			 NULL,
@@ -10599,8 +10844,26 @@ ftrace_command (char *arg, int from_tty)
   if (create_breakpoint (get_current_arch (),
 			 arg,
 			 NULL, 0, 1 /* parse arg */,
-			 0 /* tempflag */, 1 /* hardwareflag */,
-			 1 /* traceflag */,
+			 0 /* tempflag */,
+			 bp_fast_tracepoint /* type_wanted */,
+			 0 /* Ignore count */,
+			 pending_break_support,
+			 NULL,
+			 from_tty,
+			 1 /* enabled */))
+    set_tracepoint_count (breakpoint_count);
+}
+
+/* strace command implementation.  Creates a static tracepoint.  */
+
+void
+strace_command (char *arg, int from_tty)
+{
+  if (create_breakpoint (get_current_arch (),
+			 arg,
+			 NULL, 0, 1 /* parse arg */,
+			 0 /* tempflag */,
+			 bp_static_tracepoint /* type_wanted */,
 			 0 /* Ignore count */,
 			 pending_break_support,
 			 NULL,
@@ -10662,8 +10925,7 @@ create_tracepoint_from_upload (struct up
 			  addr_str,
 			  utp->cond_string, -1, 0 /* parse cond/thread */,
 			  0 /* tempflag */,
-			  (utp->type == bp_fast_tracepoint) /* hardwareflag */,
-			  1 /* traceflag */,
+			  utp->type /* type_wanted */,
 			  0 /* Ignore count */,
 			  pending_break_support,
 			  NULL,
@@ -10985,6 +11247,8 @@ save_breakpoints (char *filename, int fr
       {
 	if (tp->type == bp_fast_tracepoint)
 	  fprintf_unfiltered (fp, "ftrace");
+	if (tp->type == bp_static_tracepoint)
+	  fprintf_unfiltered (fp, "strace");
 	else if (tp->type == bp_tracepoint)
 	  fprintf_unfiltered (fp, "trace");
 	else if (tp->type == bp_breakpoint && tp->disposition == disp_del)
@@ -11569,6 +11833,31 @@ BREAK_ARGS_HELP ("ftrace") "\n\
 Do \"help tracepoints\" for info on other tracepoint commands."));
   set_cmd_completer (c, location_completer);
 
+  c = add_com ("strace", class_breakpoint, strace_command, _("\
+Set a static tracepoint at specified line, function or marker.\n\
+\n\
+strace [LOCATION] [if CONDITION]\n\
+LOCATION may be a line number, function name, \"*\" and an address,\n\
+or -m MARKER_ID.\n\
+If a line number is specified, probe the marker at start of code\n\
+for that line.  If a function is specified, probe the marker at start\n\
+of code for that function.  If an address is specified, probe the marker\n\
+at that exact address.  If a marker id is specified, probe the marker\n\
+with that name.  With no LOCATION, uses current execution address of\n\
+the selected stack frame.\n\
+Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
+This collects arbitrary user data passed in the probe point call to the\n\
+tracing library.  You can inspect it when analyzing the trace buffer,\n\
+by printing the $_sdata variable like any other convenience variable.\n\
+\n\
+CONDITION is a boolean expression.\n\
+\n\
+Multiple tracepoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.\n\
+Do \"help tracepoints\" for info on other tracepoint commands."));
+  set_cmd_completer (c, location_completer);
+
   add_info ("tracepoints", tracepoints_info, _("\
 Status of tracepoints, or tracepoint number NUMBER.\n\
 Convenience variable \"$tpnum\" contains the number of the\n\
Index: src/gdb/breakpoint.h
===================================================================
--- src.orig/gdb/breakpoint.h	2010-06-25 12:01:15.000000000 +0100
+++ src/gdb/breakpoint.h	2010-06-25 12:01:29.000000000 +0100
@@ -129,6 +129,7 @@ enum bptype
 
     bp_tracepoint,
     bp_fast_tracepoint,
+    bp_static_tracepoint,
 
     /* Event for JIT compiled code generation or deletion.  */
     bp_jit_event,
@@ -536,6 +537,9 @@ struct breakpoint
 
     /* The number of the tracepoint on the target.  */
     int number_on_target;
+
+    /* The static tracepoint string id, if known.  */
+    char *static_trace_id;
   };
 
 typedef struct breakpoint *breakpoint_p;
@@ -780,6 +784,8 @@ extern void breakpoint_re_set (void);
 
 extern void breakpoint_re_set_thread (struct breakpoint *);
 
+extern struct breakpoint *breakpoints_here_p (CORE_ADDR);
+
 extern struct breakpoint *set_momentary_breakpoint
   (struct gdbarch *, struct symtab_and_line, struct frame_id, enum bptype);
 
@@ -818,7 +824,7 @@ extern void tbreak_command (char *, int)
 extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
 			      char *cond_string, int thread,
 			      int parse_condition_and_thread,
-			      int tempflag, int hardwareflag, int traceflag,
+			      int tempflag, enum bptype wanted_type,
 			      int ignore_count,
 			      enum auto_boolean pending_break_support,
 			      struct breakpoint_ops *ops,
@@ -1040,6 +1046,11 @@ extern VEC(breakpoint_p) *all_tracepoint
 
 extern int is_tracepoint (const struct breakpoint *b);
 
+/* Return a vector of all static tracepoints defined at ADDR.  The
+   vector is newly allocated; the caller should free when done with
+   it.  */
+extern VEC(breakpoint_p) *static_tracepoints_here (CORE_ADDR addr);
+
 /* Function that can be passed to read_command_line to validate
    that each command is suitable for tracepoint command list.  */
 extern void check_tracepoint_command (char *line, void *closure);
Index: src/gdb/gdbserver/config.in
===================================================================
--- src.orig/gdb/gdbserver/config.in	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/config.in	2010-06-25 12:01:29.000000000 +0100
@@ -154,6 +154,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define if UST is available */
+#undef HAVE_UST
+
 /* Checking if errno must be defined */
 #undef MUST_DEFINE_ERRNO
 
Index: src/gdb/gdbserver/configure
===================================================================
--- src.orig/gdb/gdbserver/configure	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/configure	2010-06-25 12:01:29.000000000 +0100
@@ -601,6 +601,8 @@ RDYNAMIC
 REPORT_BUGS_TEXI
 REPORT_BUGS_TO
 PKGVERSION
+ustinc
+ustlibs
 LIBOBJS
 INSTALL_DATA
 INSTALL_SCRIPT
@@ -668,6 +670,9 @@ SHELL'
 ac_subst_files=''
 ac_user_opts='
 enable_option_checking
+with_ust
+with_ust_include
+with_ust_lib
 with_pkgversion
 with_bugurl
 with_libthread_db
@@ -1298,6 +1303,11 @@ if test -n "$ac_init_help"; then
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-ust=PATH       Specify prefix directory for the installed UST package
+                          Equivalent to --with-ust-include=PATH/include
+                          plus --with-ust-lib=PATH/lib
+  --with-ust-include=PATH Specify directory for installed UST include files
+  --with-ust-lib=PATH   Specify the directory for the installed UST library
   --with-pkgversion=PKG   Use PKG in the version string in place of "GDB"
   --with-bugurl=URL       Direct users to URL to report a bug
   --with-libthread-db=PATH
@@ -1747,8 +1757,10 @@ $as_echo "$ac_res" >&6; }
 ac_fn_c_check_decl ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
-$as_echo_n "checking whether $2 is declared... " >&6; }
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
 if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
   $as_echo_n "(cached) " >&6
 else
@@ -1758,8 +1770,12 @@ $4
 int
 main ()
 {
-#ifndef $2
-  (void) $2;
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
 #endif
 
   ;
@@ -3818,6 +3834,86 @@ done
 
 
 
+# Check for UST
+ustlibs=""
+ustinc=""
+
+
+# Check whether --with-ust was given.
+if test "${with_ust+set}" = set; then :
+  withval=$with_ust;
+fi
+
+
+# Check whether --with-ust_include was given.
+if test "${with_ust_include+set}" = set; then :
+  withval=$with_ust_include;
+fi
+
+
+# Check whether --with-ust_lib was given.
+if test "${with_ust_lib+set}" = set; then :
+  withval=$with_ust_lib;
+fi
+
+
+case $with_ust in
+  no)
+    ustlibs=
+    ustinc=
+    ;;
+  "" | yes)
+    ustlibs=" -lust "
+    ustinc=""
+    ;;
+  *)
+    ustlibs="-L$with_ust/lib -lust"
+    ustinc="-I$with_ust/include "
+    ;;
+esac
+if test "x$with_ust_include" != x; then
+  ustinc="-I$with_ust_include "
+fi
+if test "x$with_ust_lib" != x; then
+  ustlibs="-L$with_ust_lib -lust"
+fi
+
+if test "x$with_ust" != "xno"; then
+  saved_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $ustinc"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ust" >&5
+$as_echo_n "checking for ust... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#define CONFIG_UST_GDB_INTEGRATION
+#include <ust/ust.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; };
+$as_echo "#define HAVE_UST 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }; ustlibs= ; ustinc=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS="$saved_CFLAGS"
+fi
+
+# Flags needed for UST
+
+
+
 old_LIBS="$LIBS"
 LIBS="$LIBS -ldl"
 for ac_func in dladdr
Index: src/gdb/gdbserver/linux-amd64-ipa.c
===================================================================
--- src.orig/gdb/gdbserver/linux-amd64-ipa.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/linux-amd64-ipa.c	2010-06-25 12:34:11.000000000 +0100
@@ -75,6 +75,95 @@ gdb_agent_get_raw_reg (const unsigned ch
   return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
 }
 
+#ifdef HAVE_UST
+
+#include <ust/processor.h>
+
+/* "struct registers" is the UST object type holding the registers at
+   the time of the static tracepoint marker call.  This doesn't
+   contain RIP, but we know what it must have been (the marker
+   address).  */
+
+#define ST_REGENTRY(REG)			\
+  {						\
+    offsetof (struct registers, REG),		\
+    sizeof (((struct registers *) NULL)->REG)	\
+  }
+
+static struct
+{
+  int offset;
+  int size;
+} x86_64_st_collect_regmap[] =
+  {
+    ST_REGENTRY(rax),
+    ST_REGENTRY(rbx),
+    ST_REGENTRY(rcx),
+    ST_REGENTRY(rdx),
+    ST_REGENTRY(rsi),
+    ST_REGENTRY(rdi),
+    ST_REGENTRY(rbp),
+    ST_REGENTRY(rsp),
+    ST_REGENTRY(r8),
+    ST_REGENTRY(r9),
+    ST_REGENTRY(r10),
+    ST_REGENTRY(r11),
+    ST_REGENTRY(r12),
+    ST_REGENTRY(r13),
+    ST_REGENTRY(r14),
+    ST_REGENTRY(r15),
+    { -1, 0 },
+    ST_REGENTRY(rflags),
+    ST_REGENTRY(cs),
+    ST_REGENTRY(ss),
+  };
+
+#define X86_64_NUM_ST_COLLECT_GREGS \
+  (sizeof (x86_64_st_collect_regmap) / sizeof (x86_64_st_collect_regmap[0]))
+
+/* GDB's RIP register number.  */
+#define AMD64_RIP_REGNUM 16
+
+void
+supply_static_tracepoint_registers (struct regcache *regcache,
+				    const unsigned char *buf,
+				    CORE_ADDR pc)
+{
+  int i;
+  unsigned long newpc = pc;
+
+  supply_register (regcache, AMD64_RIP_REGNUM, &newpc);
+
+  for (i = 0; i < X86_64_NUM_ST_COLLECT_GREGS; i++)
+    if (x86_64_st_collect_regmap[i].offset != -1)
+      {
+	switch (x86_64_st_collect_regmap[i].size)
+	  {
+	  case 8:
+	    supply_register (regcache, i,
+			     ((char *) buf)
+			     + x86_64_st_collect_regmap[i].offset);
+	    break;
+	  case 2:
+	    {
+	      unsigned long reg
+		= * (short *) (((char *) buf)
+			       + x86_64_st_collect_regmap[i].offset);
+	      reg &= 0xffff;
+	      supply_register (regcache, i, &reg);
+	    }
+	    break;
+	  default:
+	    internal_error (__FILE__, __LINE__,
+			    "unhandled register size: %d",
+			    x86_64_st_collect_regmap[i].size);
+	    break;
+	  }
+      }
+}
+
+#endif /* HAVE_UST */
+
 /* This is only needed because reg-i386-linux-lib.o references it.  We
    may use it proper at some point.  */
 const char *gdbserver_xmltarget;
Index: src/gdb/gdbserver/linux-i386-ipa.c
===================================================================
--- src.orig/gdb/gdbserver/linux-i386-ipa.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/linux-i386-ipa.c	2010-06-25 12:33:50.000000000 +0100
@@ -110,6 +110,83 @@ gdb_agent_get_raw_reg (unsigned char *ra
     return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
 }
 
+#ifdef HAVE_UST
+
+#include <ust/processor.h>
+
+/* "struct registers" is the UST object type holding the registers at
+   the time of the static tracepoint marker call.  This doesn't
+   contain EIP, but we know what it must have been (the marker
+   address).  */
+
+#define ST_REGENTRY(REG)			\
+  {						\
+    offsetof (struct registers, REG),		\
+    sizeof (((struct registers *) NULL)->REG)	\
+  }
+
+static struct
+{
+  int offset;
+  int size;
+} i386_st_collect_regmap[] =
+  {
+    ST_REGENTRY(eax),
+    ST_REGENTRY(ecx),
+    ST_REGENTRY(edx),
+    ST_REGENTRY(ebx),
+    ST_REGENTRY(esp),
+    ST_REGENTRY(ebp),
+    ST_REGENTRY(esi),
+    ST_REGENTRY(edi),
+    { -1, 0 }, /* eip */
+    ST_REGENTRY(eflags),
+    ST_REGENTRY(cs),
+    ST_REGENTRY(ss),
+  };
+
+#define i386_NUM_ST_COLLECT_GREGS \
+  (sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
+
+void
+supply_static_tracepoint_registers (struct regcache *regcache,
+				    const unsigned char *buf,
+				    CORE_ADDR pc)
+{
+  int i;
+  unsigned int newpc = pc;
+
+  supply_register (regcache, I386_EIP_REGNUM, &newpc);
+
+  for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
+    if (i386_st_collect_regmap[i].offset != -1)
+      {
+	switch (i386_st_collect_regmap[i].size)
+	  {
+	  case 4:
+	    supply_register (regcache, i,
+			     ((char *) buf)
+			     + i386_st_collect_regmap[i].offset);
+	    break;
+	  case 2:
+	    {
+	      unsigned long reg
+		= * (short *) (((char *) buf)
+			       + i386_st_collect_regmap[i].offset);
+	      reg &= 0xffff;
+	      supply_register (regcache, i, &reg);
+	    }
+	    break;
+	  default:
+	    internal_error ("unhandled register size: %d",
+			    i386_st_collect_regmap[i].size);
+	  }
+      }
+}
+
+#endif /* HAVE_UST */
+
+
 /* This is only needed because reg-i386-linux-lib.o references it.  We
    may use it proper at some point.  */
 const char *gdbserver_xmltarget;
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/server.c	2010-06-25 16:36:16.000000000 +0100
@@ -1336,6 +1336,52 @@ handle_query (char *own_buf, int packet_
       return;
     }
 
+  if (strncmp ("qXfer:statictrace:read:", own_buf,
+	       sizeof ("qXfer:statictrace:read:") -1) == 0)
+    {
+      unsigned char *data;
+      CORE_ADDR ofs;
+      unsigned int len;
+      char *annex;
+      ULONGEST nbytes;
+
+      require_running (own_buf);
+
+      if (current_traceframe == -1)
+	{
+	  write_enn (own_buf);
+	  return;
+	}
+
+      /* Reject any annex; grab the offset and length.  */
+      if (decode_xfer_read (own_buf + sizeof ("qXfer:statictrace:read:") -1,
+			    &annex, &ofs, &len) < 0
+	  || annex[0] != '\0')
+	{
+	  strcpy (own_buf, "E00");
+	  return;
+	}
+
+      /* Read one extra byte, as an indicator of whether there is
+	 more.  */
+      if (len > PBUFSIZ - 2)
+	len = PBUFSIZ - 2;
+      data = malloc (len + 1);
+      if (!data)
+	return;
+
+      if (traceframe_read_sdata (current_traceframe, ofs,
+				 data, len + 1, &nbytes))
+	write_enn (own_buf);
+      else if (nbytes > len)
+	*new_packet_len_p = write_qxfer_response (own_buf, data, len, 1);
+      else
+	*new_packet_len_p = write_qxfer_response (own_buf, data, nbytes, 0);
+
+      free (data);
+      return;
+    }
+
   /* Protocol features query.  */
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
@@ -1433,6 +1479,8 @@ handle_query (char *own_buf, int packet_
 	  strcat (own_buf, ";DisconnectedTracing+");
 	  if (gdb_supports_qRelocInsn && target_supports_fast_tracepoints ())
 	    strcat (own_buf, ";FastTracepoints+");
+	  strcat (own_buf, ";StaticTracepoints+");
+	  strcat (own_buf, ";qXfer:statictrace:read+");
 	}
 
       return;
Index: src/gdb/mi/mi-cmd-break.c
===================================================================
--- src.orig/gdb/mi/mi-cmd-break.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/mi/mi-cmd-break.c	2010-06-25 12:01:29.000000000 +0100
@@ -75,6 +75,7 @@ mi_cmd_break_insert (char *command, char
   int enabled = 1;
   int tracepoint = 0;
   struct cleanup *back_to;
+  enum bptype type_wanted;
 
   enum opt
     {
@@ -151,9 +152,21 @@ mi_cmd_break_insert (char *command, char
 
   back_to = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
   mi_can_breakpoint_notify = 1;
+
+  /* Note that to request a fast tracepoint, the client uses the
+     "hardware" flag, although there's nothing of hardware related to
+     fast tracepoints -- one can implement slow tracepoints with
+     hardware breakpoints, but fast tracepoints are always software.
+     "fast" is a misnomer, actually, "jump" would be more appropriate.
+     A simulator or an emulator could conceivably implement fast
+     regular non-jump based tracepoints.  */
+  type_wanted = (tracepoint
+		 ? (hardware ? bp_fast_tracepoint : bp_tracepoint)
+		 : (hardware ? bp_hardware_breakpoint : bp_breakpoint));
+
   create_breakpoint (get_current_arch (), address, condition, thread,
 		     0 /* condition and thread are valid.  */,
-		     temp_p, hardware, tracepoint,
+		     temp_p, type_wanted,
 		     ignore_count,
 		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
 		     NULL, 0, enabled);
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/remote.c	2010-06-26 10:27:30.000000000 +0100
@@ -322,6 +322,9 @@ struct remote_state
   /* True if the stub reports support for fast tracepoints.  */
   int fast_tracepoints;
 
+  /* True if the stub reports support for static tracepoints.  */
+  int static_tracepoints;
+
   /* True if the stub can continue running a trace while GDB is
      disconnected.  */
   int disconnected_tracing;
@@ -1198,6 +1201,7 @@ enum {
   PACKET_qXfer_spu_write,
   PACKET_qXfer_osdata,
   PACKET_qXfer_threads,
+  PACKET_qXfer_statictrace_read,
   PACKET_qGetTIBAddr,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
@@ -1212,6 +1216,7 @@ enum {
   PACKET_qAttached,
   PACKET_ConditionalTracepoints,
   PACKET_FastTracepoints,
+  PACKET_StaticTracepoints,
   PACKET_bc,
   PACKET_bs,
   PACKET_TracepointSource,
@@ -2772,6 +2777,100 @@ remote_threads_extra_info (struct thread
 }
 
 
+static int
+remote_static_tracepoint_marker_at (CORE_ADDR addr,
+				    struct static_tracepoint_marker *marker)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p = rs->buf;
+
+  sprintf (p, "qTSTMat:");
+  p += strlen (p);
+  p += hexnumstr (p, addr);
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  if (*p++ == 'm')
+    {
+      parse_static_tracepoint_marker_definition (p, &p, marker);
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+remote_static_tracepoint_marker_by_strid (const char *strid,
+					  struct static_tracepoint_marker *marker)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p;
+
+  /* Ask for a first packet of static tracepoint marker
+     definition.  */
+  putpkt ("qTfSTM");
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  while (*p++ == 'm')
+    {
+      do
+	{
+	  parse_static_tracepoint_marker_definition (p, &p, marker);
+
+	  if (strcmp (strid, marker->str_id) == 0)
+	    return 1;
+
+	  release_static_tracepoint_marker (marker);
+	}
+      while (*p++ == ',');	/* comma-separated list */
+      /* Ask for another packet of static tracepoint definition.  */
+      putpkt ("qTsSTM");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      p = rs->buf;
+    }
+
+  return 0;
+}
+
+static void
+remote_list_static_tracepoint_markers (void)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p;
+
+  /* Ask for a first packet of static tracepoint definition.  */
+  putpkt ("qTfSTM");
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  while (*p++ == 'm')
+    {
+      do
+	{
+	  struct static_tracepoint_marker marker;
+
+	  parse_static_tracepoint_marker_definition (p, &p, &marker);
+	  print_one_static_tracepoint_marker (&marker);
+	  release_static_tracepoint_marker (&marker);
+	}
+      while (*p++ == ',');	/* comma-separated list */
+      /* Ask for another packet of static tracepoint definition.  */
+      putpkt ("qTsSTM");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      p = rs->buf;
+    }
+}
+
+
 /* Implement the to_get_ada_task_ptid function for the remote targets.  */
 
 static ptid_t
@@ -3552,6 +3651,16 @@ remote_fast_tracepoint_feature (const st
 }
 
 static void
+remote_static_tracepoint_feature (const struct protocol_feature *feature,
+				  enum packet_support support,
+				  const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  rs->static_tracepoints = (support == PACKET_ENABLE);
+}
+
+static void
 remote_disconnected_tracing_feature (const struct protocol_feature *feature,
 				     enum packet_support support,
 				     const char *value)
@@ -3593,6 +3702,8 @@ static struct protocol_feature remote_pr
     PACKET_ConditionalTracepoints },
   { "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
     PACKET_FastTracepoints },
+  { "StaticTracepoints", PACKET_DISABLE, remote_static_tracepoint_feature,
+    PACKET_StaticTracepoints },
   { "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature,
     -1 },
   { "ReverseContinue", PACKET_DISABLE, remote_supported_packet,
@@ -8046,6 +8157,16 @@ remote_xfer_partial (struct target_ops *
 				   [PACKET_qXfer_siginfo_write]);
     }
 
+  if (object == TARGET_OBJECT_STATIC_TRACE_DATA)
+    {
+      if (readbuf)
+	return remote_read_qxfer (ops, "statictrace", annex, readbuf, offset, len,
+				  &remote_protocol_packets
+				  [PACKET_qXfer_statictrace_read]);
+      else
+	return -1;
+    }
+
   /* Only handle flash writes.  */
   if (writebuf != NULL)
     {
@@ -9478,6 +9599,14 @@ remote_supports_fast_tracepoints (void)
   return rs->fast_tracepoints;
 }
 
+static int
+remote_supports_static_tracepoints (void)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return rs->static_tracepoints;
+}
+
 static void
 remote_trace_init (void)
 {
@@ -9606,6 +9735,25 @@ remote_download_tracepoint (struct break
 	       give up on the trace run.  */
 	    warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
 	}
+      else if (t->type == bp_static_tracepoint)
+	{
+	  /* Only test for support at download time; we may not know
+	     target capabilities at definition time.  */
+	  if (remote_supports_static_tracepoints ())
+	    {
+	      struct static_tracepoint_marker marker;
+
+	      if (target_static_tracepoint_marker_at (tpaddr, &marker))
+		strcat (buf, ":S");
+	      else
+		error ("Static tracepoint not valid during download");
+	    }
+	  else
+	    /* Fast tracepoints are functionally identical to regular
+	       tracepoints, so don't take lack of support as a reason
+	       to give up on the trace run.  */
+	    error (_("Target does not support static tracepoints"));
+	}
       /* If the tracepoint has a conditional, make it into an agent
 	 expression and append to the definition.  */
       if (loc->cond)
@@ -10101,6 +10249,12 @@ Specify the serial device it is connecte
   remote_ops.to_verify_memory = remote_verify_memory;
   remote_ops.to_get_tib_address = remote_get_tib_address;
   remote_ops.to_set_permissions = remote_set_permissions;
+  remote_ops.to_list_static_tracepoint_markers
+    = remote_list_static_tracepoint_markers;
+  remote_ops.to_static_tracepoint_marker_at
+    = remote_static_tracepoint_marker_at;
+  remote_ops.to_static_tracepoint_marker_by_strid
+    = remote_static_tracepoint_marker_by_strid;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -10579,6 +10733,12 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QAllow],
 			 "QAllow", "allow", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_StaticTracepoints],
+			 "StaticTracepoints", "static-tracepoints", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_statictrace_read],
+                         "qXfer:statictrace:read", "read-sdata-object", 0);
+
   /* Keep the old ``set remote Z-packet ...'' working.  Each individual
      Z sub-packet has its own set and show commands, but users may
      have sets to this variable in their .gdbinit files (or in their
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/target.c	2010-06-25 12:01:29.000000000 +0100
@@ -679,6 +679,9 @@ update_current_target (void)
       INHERIT (to_set_circular_trace_buffer, t);
       INHERIT (to_get_tib_address, t);
       INHERIT (to_set_permissions, t);
+      INHERIT (to_list_static_tracepoint_markers, t);
+      INHERIT (to_static_tracepoint_marker_at, t);
+      INHERIT (to_static_tracepoint_marker_by_strid, t);
       INHERIT (to_magic, t);
       /* Do not inherit to_memory_map.  */
       /* Do not inherit to_flash_erase.  */
@@ -878,6 +881,15 @@ update_current_target (void)
   de_fault (to_set_permissions,
 	    (void (*) (void))
 	    target_ignore);
+  de_fault (to_list_static_tracepoint_markers,
+	    (void (*) (void))
+	    target_ignore);
+  de_fault (to_static_tracepoint_marker_at,
+	    (int (*) (CORE_ADDR, struct static_tracepoint_marker *))
+	    return_zero);
+  de_fault (to_static_tracepoint_marker_by_strid,
+	    (int (*) (const char *, struct static_tracepoint_marker *))
+	    return_zero);
 #undef de_fault
 
   /* Finally, position the target-stack beneath the squashed
Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/target.h	2010-06-25 12:01:29.000000000 +0100
@@ -35,6 +35,7 @@ struct trace_state_variable;
 struct trace_status;
 struct uploaded_tsv;
 struct uploaded_tp;
+struct static_tracepoint_marker;
 
 /* This include file defines the interface between the main part
    of the debugger, and the part which is target-specific, or
@@ -261,6 +262,8 @@ enum target_object
   TARGET_OBJECT_SIGNAL_INFO,
   /* The list of threads that are being debugged.  */
   TARGET_OBJECT_THREADS,
+  /* Collected static trace data.  */
+  TARGET_OBJECT_STATIC_TRACE_DATA,
   /* Possible future objects: TARGET_OBJECT_FILE, ... */
 };
 
@@ -689,6 +692,21 @@ struct target_ops
     /* Send the new settings of write permission variables.  */
     void (*to_set_permissions) (void);
 
+    /* List static tracepoint markers in the target.  Should call
+       print_one_static_tracepoint_marker for each marker.  */
+    void (*to_list_static_tracepoint_markers) (void);
+
+    /* Look for a static tracepoint marker at ADDR, and fill in MARKER
+       with its details.  Return 1 on success, 0 on failure.  */
+    int (*to_static_tracepoint_marker_at) (CORE_ADDR,
+					   struct static_tracepoint_marker *marker);
+
+    /* Look for a static tracepoint marker with string id ID, and fill
+       in MARKER with its details.  Return 1 on success, 0 on
+       failure.  */
+    int (*to_static_tracepoint_marker_by_strid) (const char *id,
+						 struct static_tracepoint_marker *marker);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -1384,6 +1402,15 @@ extern int target_search_memory (CORE_AD
 #define target_set_permissions() \
   (*current_target.to_set_permissions) ()
 
+#define target_list_static_tracepoint_markers() \
+  (*current_target.to_list_static_tracepoint_markers) ()
+
+#define target_static_tracepoint_marker_at(addr, marker) \
+  (*current_target.to_static_tracepoint_marker_at) (addr, marker)
+
+#define target_static_tracepoint_marker_by_strid(marker_id, marker) \
+  (*current_target.to_static_tracepoint_marker_by_strid) (marker_id, marker)
+
 /* Command logging facility.  */
 
 #define target_log_command(p)						\
Index: src/gdb/tracepoint.c
===================================================================
--- src.orig/gdb/tracepoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/tracepoint.c	2010-06-28 13:23:58.000000000 +0100
@@ -47,7 +47,7 @@
 #include "stack.h"
 #include "gdbcore.h"
 #include "remote.h"
-
+#include "source.h"
 #include "ax.h"
 #include "ax-gdb.h"
 
@@ -622,9 +622,10 @@ validate_actionline (char **line, struct
 
 	  if (*p == '$')	/* look for special pseudo-symbols */
 	    {
-	      if ((0 == strncasecmp ("reg", p + 1, 3)) ||
-		  (0 == strncasecmp ("arg", p + 1, 3)) ||
-		  (0 == strncasecmp ("loc", p + 1, 3)))
+	      if (0 == strncasecmp ("reg", p + 1, 3)
+		  || 0 == strncasecmp ("arg", p + 1, 3)
+		  || 0 == strncasecmp ("loc", p + 1, 3)
+		  || 0 == strncasecmp ("_sdata", p + 1, 6))
 		{
 		  p = strchr (p, ',');
 		  continue;
@@ -747,6 +748,9 @@ struct collection_list
     long next_aexpr_elt;
     struct agent_expr **aexpr_list;
 
+    /* True is the user requested a collection of "$_sdata", "static
+       tracepoint data".  */
+    int strace_data;
   }
 tracepoint_list, stepping_list;
 
@@ -1086,6 +1090,14 @@ add_local_symbols (struct collection_lis
     }
 }
 
+static void
+add_static_trace_data (struct collection_list *collection)
+{
+  if (info_verbose)
+    printf_filtered ("collect static trace data\n");
+  collection->strace_data = 1;
+}
+
 /* worker function */
 static void
 clear_collection_list (struct collection_list *list)
@@ -1100,6 +1112,7 @@ clear_collection_list (struct collection
     }
   list->next_aexpr_elt = 0;
   memset (list->regs_mask, 0, sizeof (list->regs_mask));
+  list->strace_data = 0;
 }
 
 /* reduce a collection list to string form (for gdb protocol) */
@@ -1114,9 +1127,19 @@ stringify_collection_list (struct collec
   char *end;
   long i;
 
-  count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
+  count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
   str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
 
+  if (list->strace_data)
+    {
+      if (info_verbose)
+	printf_filtered ("\nCollecting static trace data\n");
+      end = temp_buf;
+      *end++ = 'L';
+      (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
+      ndx++;
+    }
+
   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
     if (list->regs_mask[i] != 0)	/* skip leading zeroes in regs_mask */
       break;
@@ -1276,6 +1299,11 @@ encode_actions_1 (struct command_line *a
 				     'L');
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
+	      else if (0 == strncasecmp ("$_sdata", action_exp, 7))
+		{
+		  add_static_trace_data (collect);
+		  action_exp = strchr (action_exp, ',');	/* more? */
+		}
 	      else
 		{
 		  unsigned long addr, len;
@@ -3476,6 +3504,11 @@ parse_tracepoint_definition (char *line,
 	      p++;
 	      p = unpack_varlen_hex (p, &orig_size);
 	    }
+	  else if (*p == 'S')
+	    {
+	      type = bp_static_tracepoint;
+	      p++;
+	    }
 	  else if (*p == 'X')
 	    {
 	      p++;
@@ -4075,12 +4108,239 @@ init_tfile_ops (void)
   tfile_ops.to_magic = OPS_MAGIC;
 }
 
+/* Given a line of text defining a static tracepoint marker, parse it
+   into a "static tracepoint marker" object.  Throws an error is
+   parsing fails.  If PP is non-null, it points to one past the end of
+   the parsed marker definition.  */
+
+void
+parse_static_tracepoint_marker_definition (char *line, char **pp,
+					   struct static_tracepoint_marker *marker)
+{
+  char *p, *endp;
+  ULONGEST addr;
+  int end;
+
+  p = line;
+  p = unpack_varlen_hex (p, &addr);
+  p++;  /* skip a colon */
+
+  marker->gdbarch = target_gdbarch;
+  marker->address = (CORE_ADDR) addr;
+
+  endp = strchr (p, ':');
+  if (endp == NULL)
+    error ("bad marker definition: %s", line);
+
+  marker->str_id = xmalloc (endp - p + 1);
+  end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2);
+  marker->str_id[end] = '\0';
+
+  p += 2 * end;
+  p++;  /* skip a colon */
+
+  marker->extra = xmalloc (strlen (p) + 1);
+  end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2);
+  marker->extra[end] = '\0';
+
+  if (pp)
+    *pp = p;
+}
+
+/* Release a static tracepoint marker's contents.  Note that the
+   object itself isn't released here.  There objects are usually on
+   the stack.  */
+
+void
+release_static_tracepoint_marker (struct static_tracepoint_marker *marker)
+{
+  xfree (marker->str_id);
+  marker->str_id = NULL;
+}
+
+/* Print MARKER to gdb_stdout.  */
+
+void
+print_one_static_tracepoint_marker (struct static_tracepoint_marker *marker)
+{
+  struct command_line *l;
+  struct symbol *sym;
+
+  char wrap_indent[80];
+  struct ui_stream *stb = ui_out_stream_new (uiout);
+  struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
+  struct cleanup *bkpt_chain;
+  VEC(breakpoint_p) *tracepoints;
+
+  struct symtab_and_line sal;
+
+  init_sal (&sal);
+
+  sal.pc = marker->address;
+
+  tracepoints = static_tracepoints_here (marker->address);
+
+  bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker");
+
+  ui_out_field_fmt (uiout, "enabled", "%c",
+		    !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
+  ui_out_spaces (uiout, 2);
+
+  strcpy (wrap_indent, "                           ");
+  if (gdbarch_addr_bit (marker->gdbarch) <= 32)
+    strcat (wrap_indent, "           ");
+  else
+    strcat (wrap_indent, "                   ");
+
+  ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address);
+
+  sal = find_pc_line (marker->address, 0);
+  sym = find_pc_sect_function (marker->address, NULL);
+  if (sym)
+    {
+      ui_out_text (uiout, "in ");
+      ui_out_field_string (uiout, "func",
+			   SYMBOL_PRINT_NAME (sym));
+      ui_out_wrap_hint (uiout, wrap_indent);
+      ui_out_text (uiout, " at ");
+    }
+  else
+    ui_out_field_skip (uiout, "func");
+
+  if (sal.symtab != NULL)
+    {
+      ui_out_field_string (uiout, "file", sal.symtab->filename);
+      ui_out_text (uiout, ":");
+
+      if (ui_out_is_mi_like_p (uiout))
+	{
+	  char *fullname = symtab_to_fullname (sal.symtab);
+
+	  if (fullname)
+	    ui_out_field_string (uiout, "fullname", fullname);
+	}
+      else
+	ui_out_field_skip (uiout, "fullname");
+
+      ui_out_field_int (uiout, "line", sal.line);
+    }
+  else
+    {
+      ui_out_field_skip (uiout, "fullname");
+      ui_out_field_skip (uiout, "line");
+    }
+  ui_out_text (uiout, "\n");
+
+  ui_out_text (uiout, _("     ID: "));
+  ui_out_field_string (uiout, "string-id", marker->str_id);
+  ui_out_text (uiout, "\n");
+
+  ui_out_text (uiout, _("     Data: "));
+  ui_out_field_string (uiout, "extra-data", marker->extra);
+  ui_out_text (uiout, "\n");
+
+  if (!VEC_empty (breakpoint_p, tracepoints))
+    {
+      struct cleanup *cleanup_chain;
+      int ix;
+      struct breakpoint *b;
+
+      cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout,
+							   "tracepoints-at");
+
+      ui_out_text (uiout, _("     Probed by static tracepoints: "));
+      for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
+	{
+	  if (ix > 0)
+	    ui_out_text (uiout, ", ");
+	  ui_out_text (uiout, "#");
+	  ui_out_field_int (uiout, "tracepoint-id", b->number);
+	}
+
+      do_cleanups (cleanup_chain);
+
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_int (uiout, "number-of-tracepoints",
+			  VEC_length(breakpoint_p, tracepoints));
+      else
+	ui_out_text (uiout, "\n");
+    }
+  VEC_free (breakpoint_p, tracepoints);
+
+  do_cleanups (bkpt_chain);
+  do_cleanups (old_chain);
+}
+
+static void
+info_static_tracepoint_markers_command (char *arg, int from_tty)
+{
+  struct cleanup *bkpttbl_chain;
+
+  bkpttbl_chain
+    = make_cleanup_ui_out_table_begin_end (uiout, 3, -1,
+					   "StaticTracepointMarkersTable");
+
+  ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");
+  if (gdbarch_addr_bit (target_gdbarch) <= 32)
+    ui_out_table_header (uiout, 10, ui_left, "addr", "Address");
+  else
+    ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
+  ui_out_table_header (uiout, 40, ui_noalign, "what", "What");
+  ui_out_table_body (uiout);
+
+  target_list_static_tracepoint_markers ();
+
+  do_cleanups (bkpttbl_chain);
+}
+
+/* The $_sdata convenience variable is a bit special.  We don't know
+   for sure type of the value until we actually have a chance to fetch
+   the data --- the size of the object depends on what has been
+   collected.  We solve this by making $_sdata be an internalvar that
+   creates a new value on access.  */
+
+/* Return a new value with the correct type for the sdata object of
+   the current trace frame.  Return a void value if there's no object
+   available.  */
+
+static struct value *
+sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+{
+  LONGEST size;
+  gdb_byte *buf;
+
+  /* We need to read the whole object before we know its size.  */
+  size = target_read_alloc (&current_target,
+			    TARGET_OBJECT_STATIC_TRACE_DATA,
+			    NULL, &buf);
+  if (size >= 0)
+    {
+      struct value *v;
+      struct type *type;
+
+      type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
+			       size);
+      v = allocate_value (type);
+      memcpy (value_contents_raw (v), buf, size);
+      xfree (buf);
+      return v;
+    }
+  else
+    return allocate_value (builtin_type (gdbarch)->builtin_void);
+}
+
 /* module initialization */
 void
 _initialize_tracepoint (void)
 {
   struct cmd_list_element *c;
 
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_sdata", sdata_make_value);
+
   traceframe_number = -1;
   tracepoint_number = -1;
 
@@ -4143,6 +4403,11 @@ If no arguments are supplied, delete all
 Status of trace state variables and their values.\n\
 "));
 
+  add_info ("static-tracepoint-markers",
+	    info_static_tracepoint_markers_command, _("\
+List target static tracepoints markers.\n\
+"));
+
   add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\
 Select a trace frame;\n\
 No argument means forward by one frame; '-' means backward by one frame."),
@@ -4223,6 +4488,7 @@ Also accepts the following special argum
     $regs   -- all registers.\n\
     $args   -- all function arguments.\n\
     $locals -- all variables local to the block/function scope.\n\
+    $_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\
 Note: this command can only be used in a tracepoint \"actions\" list."));
 
   add_com ("teval", class_trace, teval_pseudocommand, _("\
Index: src/gdb/tracepoint.h
===================================================================
--- src.orig/gdb/tracepoint.h	2010-06-25 12:01:15.000000000 +0100
+++ src/gdb/tracepoint.h	2010-06-25 12:01:29.000000000 +0100
@@ -166,6 +166,26 @@ struct uploaded_tsv
   struct uploaded_tsv *next;
 };
 
+/* Struct recording info about a target static tracepoint marker.  */
+
+struct static_tracepoint_marker
+{
+  struct gdbarch *gdbarch;
+  CORE_ADDR address;
+
+  /* The string ID of the marker.  */
+  char *str_id;
+
+  /* Extra target reported info associated with the marker.  */
+  char *extra;
+};
+
+extern void parse_static_tracepoint_marker_definition
+  (char *line, char **pp,
+   struct static_tracepoint_marker *marker);
+extern void print_one_static_tracepoint_marker (struct static_tracepoint_marker *);
+extern void release_static_tracepoint_marker (struct static_tracepoint_marker *);
+
 /* A hook used to notify the UI of tracepoint operations.  */
 
 extern void (*deprecated_trace_find_hook) (char *arg, int from_tty);
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/gdbserver/server.h	2010-06-25 12:01:29.000000000 +0100
@@ -542,6 +542,10 @@ int fetch_traceframe_registers (int tfnu
 				struct regcache *regcache,
 				int regnum);
 
+int traceframe_read_sdata (int tfnum, ULONGEST offset,
+			   unsigned char *buf, ULONGEST length,
+			   ULONGEST *nbytes);
+
 /* If a thread is determined to be collecting a fast tracepoint, this
    structure holds the collect status.  */
 
@@ -569,6 +573,9 @@ int handle_tracepoint_bkpts (struct thre
 void initialize_low_tracepoint (void);
 void supply_fast_tracepoint_registers (struct regcache *regcache,
 				       const unsigned char *regs);
+void supply_static_tracepoint_registers (struct regcache *regcache,
+					 const unsigned char *regs,
+					 CORE_ADDR pc);
 #else
 void stop_tracing (void);
 #endif
Index: src/gdb/python/py-breakpoint.c
===================================================================
--- src.orig/gdb/python/py-breakpoint.c	2010-06-25 12:01:14.000000000 +0100
+++ src/gdb/python/py-breakpoint.c	2010-06-25 12:01:29.000000000 +0100
@@ -592,7 +592,7 @@ bppy_new (PyTypeObject *subtype, PyObjec
 	    create_breakpoint (python_gdbarch,
 			       spec, NULL, -1,
 			       0,
-			       0, 0, 0,
+			       0, bp_breakpoint,
 			       0,
 			       AUTO_BOOLEAN_TRUE,
 			       NULL, 0, 1);
Index: src/gdb/gdbserver/Makefile.in
===================================================================
--- src.orig/gdb/gdbserver/Makefile.in	2010-06-25 12:01:13.000000000 +0100
+++ src/gdb/gdbserver/Makefile.in	2010-06-25 12:01:29.000000000 +0100
@@ -197,7 +197,7 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS)
 	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
 	  $(XM_CLIBS)
 
-IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o ${IPA_DEPFILES}
+IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o ${IPA_DEPFILES}
 
 IPA_LIB=libinproctrace.so
 
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2010-06-25 12:01:13.000000000 +0100
+++ src/gdb/gdbserver/remote-utils.c	2010-06-25 12:01:29.000000000 +0100
@@ -74,6 +74,8 @@
 typedef int socklen_t;
 #endif
 
+#ifndef IN_PROCESS_AGENT
+
 #if USE_WIN32API
 # define INVALID_DESCRIPTOR INVALID_SOCKET
 #else
@@ -371,6 +373,8 @@ fromhex (int a)
   return 0;
 }
 
+#endif
+
 static const char hexchars[] = "0123456789abcdef";
 
 static int
@@ -394,6 +398,8 @@ ishex (int ch, int *val)
   return 0;
 }
 
+#ifndef IN_PROCESS_AGENT
+
 int
 unhexify (char *bin, const char *hex, int count)
 {
@@ -446,6 +452,8 @@ decode_address_to_semicolon (CORE_ADDR *
   return end;
 }
 
+#endif
+
 /* Convert number NIB to a hex digit.  */
 
 static int
@@ -457,6 +465,8 @@ tohex (int nib)
     return 'a' + nib - 10;
 }
 
+#ifndef IN_PROCESS_AGENT
+
 int
 hexify (char *hex, const char *bin, int count)
 {
@@ -600,6 +610,8 @@ try_rle (char *buf, int remaining, unsig
   return n + 1;
 }
 
+#endif
+
 char *
 unpack_varlen_hex (char *buff,	/* packet to parse */
 		   ULONGEST *result)
@@ -617,6 +629,8 @@ unpack_varlen_hex (char *buff,	/* packet
   return buff;
 }
 
+#ifndef IN_PROCESS_AGENT
+
 /* Write a PTID to BUF.  Returns BUF+CHARACTERS_WRITTEN.  */
 
 char *
@@ -1126,6 +1140,8 @@ write_enn (char *buf)
   buf[3] = '\0';
 }
 
+#endif
+
 void
 convert_int_to_ascii (const unsigned char *from, char *to, int n)
 {
@@ -1142,6 +1158,7 @@ convert_int_to_ascii (const unsigned cha
   *to++ = 0;
 }
 
+#ifndef IN_PROCESS_AGENT
 
 void
 convert_ascii_to_int (const char *from, unsigned char *to, int n)
@@ -1841,3 +1858,5 @@ buffer_xml_printf (struct buffer *buffer
   buffer_grow_str (buffer, prev);
   va_end (ap);
 }
+
+#endif
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2010-06-25 12:34:56.000000000 +0100
+++ src/gdb/NEWS	2010-06-28 13:23:58.000000000 +0100
@@ -12,6 +12,27 @@
   thread-specific pointer to the TIB.  This feature is also supported
   when remote debugging using GDBserver.
 
+* Static tracepoints
+
+  Static tracepoints are calls in the user program into a tracing
+  library.  One such library is a port of the LTTng kernel tracer to
+  userspace --- UST (LTTng Userspace Tracer, http://lttng.org/ust).
+  When debugging with GDBserver, GDB now supports combining the GDB
+  tracepoint machinery with such libraries.  For example: the user can
+  use GDB to probe a static tracepoint marker (a call from the user
+  program into the tracing library) with the new "strace" command (see
+  "New commands" below).  This creates a "static tracepoint" in the
+  breakpoint list, that can be manipulated with the same feature set
+  as fast and regular tracepoints.  E.g., collect registers, local and
+  global variables, collect trace state variables, and define
+  tracepoint conditions.  In addition, the user can collect extra
+  static tracepoint marker specific data, by collecting the new
+  $_sdata internal variable.  When analying the trace buffer, you can
+  inspect $_sdata like any other variable available to GDB.  For more
+  information, see the "Tracepoints" chapter in GDB user manual.  New
+  remote packets have been defined to support static tracepoints, see
+  the "New remote packets" section below.
+
 * New remote packets
 
 qGetTIBAddr
@@ -27,23 +48,42 @@ qRelocInsn
   is particularly useful for stubs that support fast tracepoints.  GDB
   reports support for this feature in the qSupported packet.
 
+qTfSTM, qTsSTM
+
+  List static tracepoint markers in the target program.
+
+qTSTMat
+
+  List static tracepoint markers at a given address in the target
+  program.
+
+qXfer:statictrace:read
+
+  Read the static trace data collected (by a `collect $_sdata'
+  tracepoint action).  The remote stub reports support for this packet
+  to gdb's qSupported query.
+
 * The source command now accepts a -s option to force searching for the
   script in the source search path even if the script name specifies
   a directory.
 
 * New features in the GDB remote stub, GDBserver
 
-  - GDBserver now support tracepoints (including fast tracepoints).
-    The feature is currently supported by the i386-linux and
-    amd64-linux builds.  See the "Tracepoints support in gdbserver"
-    section in the manual for more information.  GDBserver JIT
-    compiles the tracepoint's conditional agent expression bytecode
-    into native code whenever possible for low overhead dynamic
-    tracepoints conditionals.  For such tracepoints, an expression
-    that examines program state is evaluated when the tracepoint is
-    reached, in order to determine whether to capture trace data.  If
-    the condition is simple and false, processing the tracepoint
-    finishes very quickly and no data is gathered.
+  - GDBserver now support tracepoints (including fast tracepoints, and
+    static tracepoints).  The feature is currently supported by the
+    i386-linux and amd64-linux builds.  See the "Tracepoints support
+    in gdbserver" section in the manual for more information.
+
+    GDBserver JIT compiles the tracepoint's conditional agent
+    expression bytecode into native code whenever possible for low
+    overhead dynamic tracepoints conditionals.  For such tracepoints,
+    an expression that examines program state is evaluated when the
+    tracepoint is reached, in order to determine whether to capture
+    trace data.  If the condition is simple and false, processing the
+    tracepoint finishes very quickly and no data is gathered.
+
+    GDBserver interfaces with the UST (LTTng Userspace Tracer) library
+    for static tracepoints support.
 
   - GDBserver now supports x86_64 Windows 64-bit debugging.
 
@@ -97,6 +137,13 @@ save breakpoints <filename>
 `save tracepoints' is a new alias for `save-tracepoints'.  The latter
 is now deprecated.
 
+info static-tracepoint-markers
+  Display information about static tracepoint markers in the target.
+
+strace FN | FILE:LINE | *ADDR | -m MARKER_ID
+  Define a static tracepoint by probing a marker at the given
+  function, line, address, or MARKER_ID.
+
 * Python scripting
 
 ** The GDB Python API now has access to breakpoints, symbols, symbol
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2010-06-25 13:11:25.000000000 +0100
+++ src/gdb/doc/gdb.texinfo	2010-06-28 13:23:58.000000000 +0100
@@ -8279,6 +8279,13 @@ to match the format in which the data wa
 The variable @code{$_exitcode} is automatically set to the exit code when
 the program being debugged terminates.
 
+@item $_sdata
+@vindex $_sdata@r{, inspect, convenience variable}
+The variable @code{$_sdata} contains extra collected static tracepoint
+data.  @xref{Tracepoint Actions,,Tracepoint Action Lists}.  Note that
+@code{$_sdata} could be empty, if not inspecting a trace buffer, or
+if extra static tracepoint data has not been collected.
+
 @item $_siginfo
 @vindex $_siginfo@r{, convenience variable}
 The variable @code{$_siginfo} contains extra signal information
@@ -9590,6 +9597,27 @@ Some targets may support @dfn{fast trace
 a different way (such as with a jump instead of a trap), that is
 faster but possibly restricted in where they may be installed.
 
+@cindex static tracepoints
+@cindex markers, static tracepoints
+@cindex probing markers, static tracepoints
+Regular and fast tracepoints are dynamic tracing facilities, meaning
+that they can be used to insert tracepoints at (almost) any location
+in the target.  Some targets may also support controlling @dfn{static
+tracepoints} from @value{GDBN}.  With static tracing, a set of
+instrumentation points, also known as @dfn{markers}, are embedded in
+the target program, and can be activated or deactivated by name or
+address.  These are usually placed at locations which facilitate
+investigating what the target is actually doing.  @value{GDBN}'s
+support for static tracing includes being able to list instrumentation
+points, and attach them with @value{GDBN} defined high level
+tracepoints that expose the whole range of convenience of
+@value{GDBN}'s tracepoints support.  Namelly, support for collecting
+registers values and values of global or local (to the instrumentation
+point) variables; tracepoint conditions and trace state variables.
+The act of installing a @value{GDBN} static tracepoint on an
+instrumentation point, or marker, is referred to as @dfn{probing} a
+static tracepoint marker.
+
 @code{gdbserver} supports tracepoints on some target systems.
 @xref{Server,,Tracepoints support in @code{gdbserver}}.
 
@@ -9604,6 +9632,7 @@ conditions and actions.
 * Trace State Variables::
 * Tracepoint Actions::
 * Listing Tracepoints::
+* Listing Static Tracepoint Markers::
 * Starting and Stopping Trace Experiments::
 * Tracepoint Restrictions::
 @end menu
@@ -9663,6 +9692,64 @@ message.
 @value{GDBN} handles arguments to @code{ftrace} exactly as for
 @code{trace}.
 
+@item strace @var{location} [ if @var{cond} ]
+@cindex static tracepoint, setting
+@kindex strace
+The @code{strace} command sets a static tracepoint.  For targets that
+support it, setting a static tracepoint probes a static
+instrumentation point, or marker, found at @var{location}.  It may not
+be possible to set a static tracepoint at the desired location, in
+which case the command will exit with an explanatory message.
+
+@value{GDBN} handles arguments to @code{strace} exactly as for
+@code{trace}, with the addition that the user can also specify
+@code{-m @var{marker}} as @var{location}.  This probes the marker
+identified by the @var{marker} string identifier.  This identifier
+depends on the static tracepoint backend library your program is
+using.  You can find all the marker identifiers in the @samp{ID} field
+of the @code{info static-tracepoint-markers} command output.
+@xref{Listing Static Tracepoint Markers,,Listing Static Tracepoint
+Markers}.  For example, in the following small program using the UST
+tracing engine:
+
+@smallexample
+main ()
+@{
+  trace_mark(ust, bar33, "str %s", "FOOBAZ");
+@}
+@end smallexample
+
+The marker id is composed of joining the first two arguments to the
+@code{trace_mark} call with a slash, which translates to:
+
+@smallexample
+(@value{GDBP}) info static-tracepoint-markers
+Enb Address            What
+n   0x0000000000400ddc in main at stexample.c:22
+     ID: ust/bar33
+     Data: str %s
+[etc...]
+@end smallexample
+
+You can probe that marker with:
+
+@smallexample
+(@value{GDBP}) strace -m ust/bar33
+@end smallexample
+
+Static tracepoints accept an extra collect action --- @code{collect
+$_sdata}.  This collects arbitrary user data passed in the probe point
+call to the tracing library.  In the UST example above, you'll see
+that the third argument to @code{trace_mark} is a printf-like format
+string.  The user data is then the result of running that formating
+string against the following arguments.  Note that @code{info
+static-tracepoint-markers} command output lists that format string in
+the @samp{Data:} field.
+
+You can inspect this data when analyzing the trace buffer, by printing
+the $_sdata variable like any other variable available to
+@value{GDBN}.  @xref{Tracepoint Actions,,Tracepoint Action Lists}.
+
 @vindex $tpnum
 @cindex last tracepoint number
 @cindex recent tracepoint number
@@ -9899,13 +9986,32 @@ special arguments are supported:
 
 @table @code
 @item $regs
-collect all registers
+Collect all registers.
 
 @item $args
-collect all function arguments
+Collect all function arguments.
 
 @item $locals
-collect all local variables.
+Collect all local variables.
+
+@item $_sdata
+@vindex $_sdata@r{, collect}
+Collect static tracepoint marker specific data.  Only available for
+static tracepoints.  @xref{Tracepoint Actions,,Tracepoint Action
+Lists}.  This usually consists of data formatted to a character string
+using the format provided by the programmer that instrumented the
+program.  E.g., on some systems, an instrumentation point resembles a
+printf function call:
+
+@smallexample
+ const char master_name[] = "$your_name";
+ TRACE(tp1, "hello %s", master_name)
+@end smallexample
+
+In this case, collecting @code{$_sdata} collects the string
+@samp{hello $yourname}.  When analying the trace buffer, you can
+inspect @samp{$_sdata} like any other variable available to
+@value{GDBN}.
 @end table
 
 You can give several consecutive @code{collect} commands, each one
@@ -10000,6 +10106,30 @@ Num     Type           Disp Enb Address 
 This command can be abbreviated @code{info tp}.
 @end table
 
+@node Listing Static Tracepoint Markers
+@subsection Listing Static Tracepoint Markers
+
+@table @code
+@kindex info static-tracepoint-markers
+@cindex information about static tracepoint markers
+@item info static-tracepoint-markers
+Display information about all static tracepoint markers defined in the
+program.
+
+@smallexample
+(@value{GDBP}) info static-tracepoint-markers
+Enb Address            What
+y   0x0000000000400e1a in main at stexample.c:25
+     ID: ust/bar2
+     Data: number1 %d number2 %d
+     Probed by static tracepoints: #2
+n   0x0000000000400c87 in main at stexample.c:24
+     ID: ust/bar33
+     Data: str %s
+(@value{GDBP})
+@end smallexample
+@end table
+
 @node Starting and Stopping Trace Experiments
 @subsection Starting and Stopping Trace Experiments
 
@@ -15848,13 +15978,21 @@ of a multi-process mode debug session.
 @subsection Tracepoints support in @code{gdbserver}
 @cindex tracepoints support in @code{gdbserver}
 
-On some targets, @code{gdbserver} supports tracepoints and fast
-tracepoints.
+On some targets, @code{gdbserver} supports tracepoints, fast
+tracepoints and static tracepoints.
 
-For fast tracepoints to work, a special library called the
+For fast or static tracepoints to work, a special library called the
 @dfn{in-process agent} (IPA), must be loaded in the inferior process.
 This library is built and distributed as an integral part of
-@code{gdbserver}.
+@code{gdbserver}.  In addition, support for static tracepoints
+requires building the in-process agent library with static tracepoints
+support.  At present, the UST (LTTng Userspace Tracer,
+@url{http://lttng.org/ust}) tracing engine is supported.  This support
+is automatically available if UST development headers are found in the
+standard include path when @code{gdbserver} is built, or if
+@code{gdbserver} was explicitly configured using @option{--with-ust}
+to point at such headers.  You can explicitly disable the support
+using @option{--with-ust=no}.
 
 There are several ways to load the in-process agent in your program:
 
@@ -15895,10 +16033,10 @@ systems, when you connect to @code{gdbse
 remote}, you'll find that the program is stopped at the dynamic
 loader's entry point, and no shared library has been loaded in the
 program's address space yet, including the in-process agent.  In that
-case, before being able to use any of the fast tracepoints features,
-you need to let the loader run and load the shared libraries.  The
-most simple way to do that is to run the program to the main
-procedure.  E.g., if debugging a C or C@t{++} program, start
+case, before being able to use any of the fast or static tracepoints
+features, you need to let the loader run and load the shared
+libraries.  The simplest way to do that is to run the program to the
+main procedure.  E.g., if debugging a C or C@t{++} program, start
 @code{gdbserver} like so:
 
 @smallexample
@@ -15918,7 +16056,8 @@ $ gdb myprogram
 The in-process tracing agent library should now be loaded into the
 process; you can confirm it with the @code{info sharedlibrary}
 command, which will list @file{libinproctrace.so} as loaded in the
-process.  You are now ready to install fast tracepoints and start
+process.  You are now ready to install fast tracepoints, list static
+tracepoint markers, probe static tracepoints markers, and start
 tracing.
 
 @node Remote Configuration
@@ -16170,6 +16309,10 @@ are:
 @tab @code{qXfer:memory-map:read}
 @tab @code{info mem}
 
+@item @code{read-sdata-object}
+@tab @code{qXfer:sdata:read}
+@tab @code{print $_sdata}
+
 @item @code{read-spu-object}
 @tab @code{qXfer:spu:read}
 @tab @code{info spu}
@@ -31807,6 +31950,11 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:sdata:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{qXfer:spu:read}
 @tab No
 @tab @samp{-}
@@ -31910,6 +32058,10 @@ The remote stub understands the @samp{qX
 The remote stub understands the @samp{qXfer:memory-map:read} packet
 (@pxref{qXfer memory map read}).
 
+@item qXfer:sdata:read
+The remote stub understands the @samp{qXfer:sdata:read} packet
+(@pxref{qXfer sdata read}).
+
 @item qXfer:spu:read
 The remote stub understands the @samp{qXfer:spu:read} packet
 (@pxref{qXfer spu read}).
@@ -31978,6 +32130,10 @@ the source form of tracepoint definition
 @item QAllow
 The remote stub understands the @samp{QAllow} packet.
 
+@item StaticTracepoint
+@cindex static tracepoints, in remote protocol
+The remote stub supports static tracepoints.
+
 @end table
 
 @item qSymbol::
@@ -32062,6 +32218,9 @@ packets.)
 @itemx QTro       
 @itemx qTStatus   
 @itemx qTV
+@itemx qTfSTM
+@itemx qTsSTM
+@itemx qTSTMat
 @xref{Tracepoint Packets}.
 
 @item qXfer:@var{object}:read:@var{annex}:@var{offset},@var{length}
@@ -32118,6 +32277,18 @@ annex part of the generic @samp{qXfer} p
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+@item qXfer:sdata:read::@var{offset},@var{length}
+@anchor{qXfer sdata read}
+
+Read contents of the extra collected static tracepoint marker
+information.  The annex part of the generic @samp{qXfer} packet must
+be empty (@pxref{qXfer read}).  @xref{Tracepoint Actions,,Tracepoint
+Action Lists}.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qSupported}).
+
 @item qXfer:siginfo:read::@var{offset},@var{length}
 @anchor{qXfer siginfo read}
 Read contents of the extra signal information on the target
@@ -32657,6 +32828,43 @@ and multiple @code{qTsV} to get addition
 these packets follow the syntax of the @code{QTDV} packets that define
 trace state variables.
 
+@item qTfSTM
+@itemx qTsSTM
+These packets request data about static tracepoint markers that exist
+in the target program.  @value{GDBN} sends @code{qTfSTM} to get the
+first piece of data, and multiple @code{qTsSTM} to get additional
+pieces.  Replies to these packets take the following form:
+
+Reply:
+@table @samp
+@item m @var{address}:@var{id}:@var{extra}
+A single marker
+@item m @var{address}:@var{id}:@var{extra},@var{address}:@var{id}:@var{extra}@dots{}
+a comma-separated list of markers
+@item l
+(lower case letter @samp{L}) denotes end of list.
+@item E @var{nn}
+An error occurred.  @var{nn} are hex digits.
+@item
+An empty reply indicates that the request is not supported by the
+stub.
+@end table
+
+@var{address} is encoded in hex.
+@var{id} and @var{extra} are strings encoded in hex.
+
+In response to each query, the target will reply with a list of one or
+more markers, separated by commas.  @value{GDBN} will respond to each
+reply with a request for more markers (using the @samp{qs} form of the
+query), until the target responds with @samp{l} (lower-case ell, for
+@dfn{last}).
+
+@item qTSTMat:@var{address}
+This packets requests data about static tracepoint markers in the
+target program at @var{address}.  Replies to this packet follow the
+syntax of the @samp{qTfSTM} and @code{qTsSTM} packets that list static
+tracepoint markers.
+
 @item QTSave:@var{filename}
 This packet directs the target to save trace data to the file name
 @var{filename} in the target's filesystem.  @var{filename} is encoded


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]