constify gdbserver/server.c
[deliverable/binutils-gdb.git] / gdb / gdbserver / tracepoint.c
index bafd82ad270300f02c2ea19644b3067c7e5bd9d0..42b27c072e0af5e6570f890581f66534468f40e4 100644 (file)
@@ -1,5 +1,5 @@
 /* Tracepoint code for remote server for GDB.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "server.h"
+#include "tracepoint.h"
+#include "gdbthread.h"
+#include "agent.h"
+#include "rsp-low.h"
+
 #include <ctype.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/time.h>
-#include <stddef.h>
-#if HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#if HAVE_STDINT_H
+#include <inttypes.h>
 #include <stdint.h>
-#endif
 
-/* This file is built for both both GDBserver, and the in-process
+#include "ax.h"
+#include "tdesc.h"
+
+#define DEFAULT_TRACE_BUFFER_SIZE 5242880 /* 5*1024*1024 */
+
+/* This file is built for both GDBserver, and the in-process
    agent (IPA), a shared library that includes a tracing agent that is
    loaded by the inferior to support fast tracepoints.  Fast
    tracepoints (or more accurately, jump based tracepoints) are
@@ -56,7 +61,9 @@
 
 */
 
-static void trace_vdebug (const char *, ...) ATTR_FORMAT (printf, 1, 2);
+#ifdef IN_PROCESS_AGENT
+
+static void trace_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2);
 
 static void
 trace_vdebug (const char *fmt, ...)
@@ -66,75 +73,69 @@ trace_vdebug (const char *fmt, ...)
 
   va_start (ap, fmt);
   vsprintf (buf, fmt, ap);
-  fprintf (stderr, "gdbserver/tracepoint: %s\n", buf);
+  fprintf (stderr, PROG "/tracepoint: %s\n", buf);
   va_end (ap);
 }
 
 #define trace_debug_1(level, fmt, args...)     \
   do {                                         \
-    if (level <= debug_threads)                        \
+    if (level <= debug_threads)                \
       trace_vdebug ((fmt), ##args);            \
   } while (0)
 
-#define trace_debug(FMT, args...)              \
-  trace_debug_1 (1, FMT, ##args)
-
-#if defined(__GNUC__)
-#  define ATTR_USED __attribute__((used))
-#  define ATTR_NOINLINE __attribute__((noinline))
-#  define ATTR_CONSTRUCTOR __attribute__ ((constructor))
 #else
-#  define ATTR_USED
-#  define ATTR_NOINLINE
-#  define ATTR_CONSTRUCTOR
-#endif
 
-/* Make sure the functions the IPA needs to export (symbols GDBserver
-   needs to query GDB about) are exported.  */
+#define trace_debug_1(level, fmt, args...)     \
+  do {                                         \
+    if (level <= debug_threads)                        \
+      {                                                \
+       debug_printf ((fmt), ##args);           \
+       debug_printf ("\n");                    \
+      }                                                \
+  } while (0)
 
-#ifdef IN_PROCESS_AGENT
-# if defined _WIN32 || defined __CYGWIN__
-#   define IP_AGENT_EXPORT __declspec(dllexport) ATTR_USED
-# else
-#   if __GNUC__ >= 4
-#     define IP_AGENT_EXPORT \
-  __attribute__ ((visibility("default"))) ATTR_USED
-#   else
-#     define IP_AGENT_EXPORT ATTR_USED
-#   endif
-# endif
-#else
-#  define IP_AGENT_EXPORT
 #endif
 
+#define trace_debug(FMT, args...)              \
+  trace_debug_1 (1, FMT, ##args)
+
 /* Prefix exported symbols, for good citizenship.  All the symbols
-   that need exporting are defined in this module.  */
+   that need exporting are defined in this module.  Note that all
+   these symbols must be tagged with IP_AGENT_EXPORT_*.  */
 #ifdef IN_PROCESS_AGENT
-# define gdb_tp_heap_buffer gdb_agent_gdb_tp_heap_buffer
-# define gdb_jump_pad_buffer gdb_agent_gdb_jump_pad_buffer
-# define gdb_jump_pad_buffer_end gdb_agent_gdb_jump_pad_buffer_end
-# define collecting gdb_agent_collecting
-# define gdb_collect gdb_agent_gdb_collect
-# define stop_tracing gdb_agent_stop_tracing
-# define flush_trace_buffer gdb_agent_flush_trace_buffer
-# define about_to_request_buffer_space gdb_agent_about_to_request_buffer_space
-# define trace_buffer_is_full gdb_agent_trace_buffer_is_full
-# define stopping_tracepoint gdb_agent_stopping_tracepoint
-# define expr_eval_result gdb_agent_expr_eval_result
-# define error_tracepoint gdb_agent_error_tracepoint
-# define tracepoints gdb_agent_tracepoints
-# define tracing gdb_agent_tracing
-# define trace_buffer_ctrl gdb_agent_trace_buffer_ctrl
-# define trace_buffer_ctrl_curr gdb_agent_trace_buffer_ctrl_curr
-# define trace_buffer_lo gdb_agent_trace_buffer_lo
-# define trace_buffer_hi gdb_agent_trace_buffer_hi
-# define traceframe_read_count gdb_agent_traceframe_read_count
-# define traceframe_write_count gdb_agent_traceframe_write_count
-# define traceframes_created gdb_agent_traceframes_created
-# define trace_state_variables gdb_agent_trace_state_variables
-# 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 gdb_tp_heap_buffer IPA_SYM_EXPORTED_NAME (gdb_tp_heap_buffer)
+# define gdb_jump_pad_buffer IPA_SYM_EXPORTED_NAME (gdb_jump_pad_buffer)
+# define gdb_jump_pad_buffer_end IPA_SYM_EXPORTED_NAME (gdb_jump_pad_buffer_end)
+# define gdb_trampoline_buffer IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer)
+# define gdb_trampoline_buffer_end IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer_end)
+# define gdb_trampoline_buffer_error IPA_SYM_EXPORTED_NAME (gdb_trampoline_buffer_error)
+# define collecting IPA_SYM_EXPORTED_NAME (collecting)
+# define gdb_collect IPA_SYM_EXPORTED_NAME (gdb_collect)
+# define stop_tracing IPA_SYM_EXPORTED_NAME (stop_tracing)
+# define flush_trace_buffer IPA_SYM_EXPORTED_NAME (flush_trace_buffer)
+# define about_to_request_buffer_space IPA_SYM_EXPORTED_NAME (about_to_request_buffer_space)
+# define trace_buffer_is_full IPA_SYM_EXPORTED_NAME (trace_buffer_is_full)
+# define stopping_tracepoint IPA_SYM_EXPORTED_NAME (stopping_tracepoint)
+# define expr_eval_result IPA_SYM_EXPORTED_NAME (expr_eval_result)
+# define error_tracepoint IPA_SYM_EXPORTED_NAME (error_tracepoint)
+# define tracepoints IPA_SYM_EXPORTED_NAME (tracepoints)
+# define tracing IPA_SYM_EXPORTED_NAME (tracing)
+# define trace_buffer_ctrl IPA_SYM_EXPORTED_NAME (trace_buffer_ctrl)
+# define trace_buffer_ctrl_curr IPA_SYM_EXPORTED_NAME (trace_buffer_ctrl_curr)
+# define trace_buffer_lo IPA_SYM_EXPORTED_NAME (trace_buffer_lo)
+# define trace_buffer_hi IPA_SYM_EXPORTED_NAME (trace_buffer_hi)
+# define traceframe_read_count IPA_SYM_EXPORTED_NAME (traceframe_read_count)
+# define traceframe_write_count IPA_SYM_EXPORTED_NAME (traceframe_write_count)
+# define traceframes_created IPA_SYM_EXPORTED_NAME (traceframes_created)
+# define trace_state_variables IPA_SYM_EXPORTED_NAME (trace_state_variables)
+# define get_raw_reg IPA_SYM_EXPORTED_NAME (get_raw_reg)
+# define get_trace_state_variable_value \
+  IPA_SYM_EXPORTED_NAME (get_trace_state_variable_value)
+# define set_trace_state_variable_value \
+  IPA_SYM_EXPORTED_NAME (set_trace_state_variable_value)
+# define ust_loaded IPA_SYM_EXPORTED_NAME (ust_loaded)
+# define helper_thread_id IPA_SYM_EXPORTED_NAME (helper_thread_id)
+# define cmd_buf IPA_SYM_EXPORTED_NAME (cmd_buf)
 #endif
 
 #ifndef IN_PROCESS_AGENT
@@ -146,6 +147,9 @@ struct ipa_sym_addresses
   CORE_ADDR addr_gdb_tp_heap_buffer;
   CORE_ADDR addr_gdb_jump_pad_buffer;
   CORE_ADDR addr_gdb_jump_pad_buffer_end;
+  CORE_ADDR addr_gdb_trampoline_buffer;
+  CORE_ADDR addr_gdb_trampoline_buffer_end;
+  CORE_ADDR addr_gdb_trampoline_buffer_error;
   CORE_ADDR addr_collecting;
   CORE_ADDR addr_gdb_collect;
   CORE_ADDR addr_stop_tracing;
@@ -168,16 +172,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;
 };
 
-#define STRINGIZE_1(STR) #STR
-#define STRINGIZE(STR) STRINGIZE_1(STR)
-#define IPA_SYM(SYM)                           \
-  {                                                    \
-    STRINGIZE (gdb_agent_ ## SYM),                     \
-    offsetof (struct ipa_sym_addresses, addr_ ## SYM)  \
-  }
-
 static struct
 {
   const char *name;
@@ -187,6 +184,9 @@ static struct
   IPA_SYM(gdb_tp_heap_buffer),
   IPA_SYM(gdb_jump_pad_buffer),
   IPA_SYM(gdb_jump_pad_buffer_end),
+  IPA_SYM(gdb_trampoline_buffer),
+  IPA_SYM(gdb_trampoline_buffer_end),
+  IPA_SYM(gdb_trampoline_buffer_error),
   IPA_SYM(collecting),
   IPA_SYM(gdb_collect),
   IPA_SYM(stop_tracing),
@@ -209,36 +209,98 @@ 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),
 };
 
-struct ipa_sym_addresses ipa_sym_addrs;
+static struct ipa_sym_addresses ipa_sym_addrs;
 
-int all_tracepoint_symbols_looked_up;
+static int read_inferior_integer (CORE_ADDR symaddr, int *val);
 
-int
-in_process_agent_loaded (void)
+/* Returns true if both the in-process agent library and the static
+   tracepoints libraries are loaded in the inferior, and agent has
+   capability on static tracepoints.  */
+
+static int
+in_process_agent_supports_ust (void)
 {
-  return all_tracepoint_symbols_looked_up;
-}
+  int loaded = 0;
 
-static int read_inferior_integer (CORE_ADDR symaddr, int *val);
+  if (!agent_loaded_p ())
+    {
+      warning ("In-process agent not loaded");
+      return 0;
+    }
+
+  if (agent_capability_check (AGENT_CAPA_STATIC_TRACE))
+    {
+      /* Agent understands static tracepoint, then check whether UST is in
+        fact loaded in the inferior.  */
+      if (read_inferior_integer (ipa_sym_addrs.addr_ust_loaded, &loaded))
+       {
+         warning ("Error reading ust_loaded in lib");
+         return 0;
+       }
+
+      return loaded;
+    }
+  else
+    return 0;
+}
 
 static void
 write_e_ipa_not_loaded (char *buffer)
 {
   sprintf (buffer,
           "E.In-process agent library not loaded in process.  "
-          "Dynamic tracepoints unavailable.");
+          "Fast and static 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)
 {
-  if (!in_process_agent_loaded ())
+  if (!agent_loaded_p ())
+    {
+      write_e_ipa_not_loaded (buffer);
+      return 1;
+    }
+  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 (!agent_loaded_p ())
     {
       write_e_ipa_not_loaded (buffer);
       return 1;
     }
+  else if (!in_process_agent_supports_ust ())
+    {
+      write_e_ust_not_loaded (buffer);
+      return 1;
+    }
   return 0;
 }
 
@@ -251,13 +313,11 @@ maybe_write_ipa_not_loaded (char *buffer)
 void
 tracepoint_look_up_symbols (void)
 {
-  int all_ok;
   int i;
 
-  if (all_tracepoint_symbols_looked_up)
+  if (agent_loaded_p ())
     return;
 
-  all_ok = 1;
   for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
     {
       CORE_ADDR *addrp =
@@ -266,12 +326,12 @@ tracepoint_look_up_symbols (void)
       if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0)
        {
          if (debug_threads)
-           fprintf (stderr, "symbol `%s' not found\n", symbol_list[i].name);
-         all_ok = 0;
+           debug_printf ("symbol `%s' not found\n", symbol_list[i].name);
+         return;
        }
     }
 
-  all_tracepoint_symbols_looked_up = all_ok;
+  agent_look_up_symbols (NULL);
 }
 
 #endif
@@ -290,8 +350,6 @@ tracepoint_look_up_symbols (void)
    GDBserver side.  */
 
 #ifdef IN_PROCESS_AGENT
-int debug_threads = 0;
-
 int
 read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
 {
@@ -310,14 +368,14 @@ read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
 #  define UNKNOWN_SIDE_EFFECTS() do {} while (0)
 #endif
 
-IP_AGENT_EXPORT void ATTR_USED ATTR_NOINLINE
+IP_AGENT_EXPORT_FUNC void
 stop_tracing (void)
 {
   /* GDBserver places breakpoint here.  */
   UNKNOWN_SIDE_EFFECTS();
 }
 
-IP_AGENT_EXPORT void ATTR_USED ATTR_NOINLINE
+IP_AGENT_EXPORT_FUNC void
 flush_trace_buffer (void)
 {
   /* GDBserver places breakpoint here.  */
@@ -343,10 +401,11 @@ static int stop_tracing_handler (CORE_ADDR);
 struct breakpoint *flush_trace_buffer_bkpt;
 static int flush_trace_buffer_handler (CORE_ADDR);
 
-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, int len);
+
 static int
 read_inferior_integer (CORE_ADDR symaddr, int *val)
 {
@@ -354,6 +413,9 @@ read_inferior_integer (CORE_ADDR symaddr, int *val)
                               sizeof (*val));
 }
 
+struct tracepoint;
+static int tracepoint_send_agent (struct tracepoint *tpoint);
+
 static int
 read_inferior_uinteger (CORE_ADDR symaddr, unsigned int *val)
 {
@@ -392,127 +454,39 @@ write_inferior_uinteger (CORE_ADDR symaddr, unsigned int val)
   return write_inferior_memory (symaddr, (unsigned char *) &val, sizeof (val));
 }
 
-#endif
+static CORE_ADDR target_malloc (ULONGEST size);
+static int write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr);
 
-/* This enum must exactly match what is documented in
-   gdb/doc/agentexpr.texi, including all the numerical values.  */
+#define COPY_FIELD_TO_BUF(BUF, OBJ, FIELD)     \
+  do {                                                 \
+    memcpy (BUF, &(OBJ)->FIELD, sizeof ((OBJ)->FIELD)); \
+    BUF += sizeof ((OBJ)->FIELD);                      \
+  } while (0)
 
-enum gdb_agent_op
-  {
-    gdb_agent_op_float = 0x01,
-    gdb_agent_op_add = 0x02,
-    gdb_agent_op_sub = 0x03,
-    gdb_agent_op_mul = 0x04,
-    gdb_agent_op_div_signed = 0x05,
-    gdb_agent_op_div_unsigned = 0x06,
-    gdb_agent_op_rem_signed = 0x07,
-    gdb_agent_op_rem_unsigned = 0x08,
-    gdb_agent_op_lsh = 0x09,
-    gdb_agent_op_rsh_signed = 0x0a,
-    gdb_agent_op_rsh_unsigned = 0x0b,
-    gdb_agent_op_trace = 0x0c,
-    gdb_agent_op_trace_quick = 0x0d,
-    gdb_agent_op_log_not = 0x0e,
-    gdb_agent_op_bit_and = 0x0f,
-    gdb_agent_op_bit_or = 0x10,
-    gdb_agent_op_bit_xor = 0x11,
-    gdb_agent_op_bit_not = 0x12,
-    gdb_agent_op_equal = 0x13,
-    gdb_agent_op_less_signed = 0x14,
-    gdb_agent_op_less_unsigned = 0x15,
-    gdb_agent_op_ext = 0x16,
-    gdb_agent_op_ref8 = 0x17,
-    gdb_agent_op_ref16 = 0x18,
-    gdb_agent_op_ref32 = 0x19,
-    gdb_agent_op_ref64 = 0x1a,
-    gdb_agent_op_ref_float = 0x1b,
-    gdb_agent_op_ref_double = 0x1c,
-    gdb_agent_op_ref_long_double = 0x1d,
-    gdb_agent_op_l_to_d = 0x1e,
-    gdb_agent_op_d_to_l = 0x1f,
-    gdb_agent_op_if_goto = 0x20,
-    gdb_agent_op_goto = 0x21,
-    gdb_agent_op_const8 = 0x22,
-    gdb_agent_op_const16 = 0x23,
-    gdb_agent_op_const32 = 0x24,
-    gdb_agent_op_const64 = 0x25,
-    gdb_agent_op_reg = 0x26,
-    gdb_agent_op_end = 0x27,
-    gdb_agent_op_dup = 0x28,
-    gdb_agent_op_pop = 0x29,
-    gdb_agent_op_zero_ext = 0x2a,
-    gdb_agent_op_swap = 0x2b,
-    gdb_agent_op_getv = 0x2c,
-    gdb_agent_op_setv = 0x2d,
-    gdb_agent_op_tracev = 0x2e,
-    gdb_agent_op_trace16 = 0x30,
-    gdb_agent_op_last
-  };
+#endif
 
-static const char *gdb_agent_op_names [gdb_agent_op_last] =
-  {
-    "?undef?",
-    "float",
-    "add",
-    "sub",
-    "mul",
-    "div_signed",
-    "div_unsigned",
-    "rem_signed",
-    "rem_unsigned",
-    "lsh",
-    "rsh_signed",
-    "rsh_unsigned",
-    "trace",
-    "trace_quick",
-    "log_not",
-    "bit_and",
-    "bit_or",
-    "bit_xor",
-    "bit_not",
-    "equal",
-    "less_signed",
-    "less_unsigned",
-    "ext",
-    "ref8",
-    "ref16",
-    "ref32",
-    "ref64",
-    "ref_float",
-    "ref_double",
-    "ref_long_double",
-    "l_to_d",
-    "d_to_l",
-    "if_goto",
-    "goto",
-    "const8",
-    "const16",
-    "const32",
-    "const64",
-    "reg",
-    "end",
-    "dup",
-    "pop",
-    "zero_ext",
-    "swap",
-    "getv",
-    "setv",
-    "tracev",
-    "?undef?",
-    "trace16",
-  };
+/* Operations on various types of tracepoint actions.  */
 
-struct agent_expr
+struct tracepoint_action;
+
+struct tracepoint_action_ops
 {
-  int length;
+  /* Download tracepoint action ACTION to IPA.  Return the address of action
+     in IPA/inferior.  */
+  CORE_ADDR (*download) (const struct tracepoint_action *action);
 
-  unsigned char *bytes;
+  /* Send ACTION to agent via command buffer started from BUFFER.  Return
+     updated head of command buffer.  */
+  char* (*send) (char *buffer, const struct tracepoint_action *action);
 };
 
 /* Base action.  Concrete actions inherit this.  */
 
 struct tracepoint_action
 {
+#ifndef IN_PROCESS_AGENT
+  const struct tracepoint_action_ops *ops;
+#endif
   char type;
 };
 
@@ -523,7 +497,7 @@ struct collect_memory_action
 
   ULONGEST addr;
   ULONGEST len;
-  int basereg;
+  int32_t basereg;
 };
 
 /* An 'R' (collect registers) action.  */
@@ -542,6 +516,153 @@ 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;
+};
+
+#ifndef IN_PROCESS_AGENT
+static CORE_ADDR
+m_tracepoint_action_download (const struct tracepoint_action *action)
+{
+  int size_in_ipa = (sizeof (struct collect_memory_action)
+                    - offsetof (struct tracepoint_action, type));
+  CORE_ADDR ipa_action = target_malloc (size_in_ipa);
+
+  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
+                        size_in_ipa);
+
+  return ipa_action;
+}
+static char *
+m_tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
+{
+  struct collect_memory_action *maction
+    = (struct collect_memory_action *) action;
+
+  COPY_FIELD_TO_BUF (buffer, maction, addr);
+  COPY_FIELD_TO_BUF (buffer, maction, len);
+  COPY_FIELD_TO_BUF (buffer, maction, basereg);
+
+  return buffer;
+}
+
+static const struct tracepoint_action_ops m_tracepoint_action_ops =
+{
+  m_tracepoint_action_download,
+  m_tracepoint_action_send,
+};
+
+static CORE_ADDR
+r_tracepoint_action_download (const struct tracepoint_action *action)
+{
+  int size_in_ipa = (sizeof (struct collect_registers_action)
+                    - offsetof (struct tracepoint_action, type));
+  CORE_ADDR ipa_action  = target_malloc (size_in_ipa);
+
+  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
+                       size_in_ipa);
+
+  return ipa_action;
+}
+
+static char *
+r_tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
+{
+  return buffer;
+}
+
+static const struct tracepoint_action_ops r_tracepoint_action_ops =
+{
+  r_tracepoint_action_download,
+  r_tracepoint_action_send,
+};
+
+static CORE_ADDR download_agent_expr (struct agent_expr *expr);
+
+static CORE_ADDR
+x_tracepoint_action_download (const struct tracepoint_action *action)
+{
+  int size_in_ipa = (sizeof (struct eval_expr_action)
+                    - offsetof (struct tracepoint_action, type));
+  CORE_ADDR ipa_action = target_malloc (size_in_ipa);
+  CORE_ADDR expr;
+
+  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
+                        size_in_ipa);
+  expr = download_agent_expr (((struct eval_expr_action *)action)->expr);
+  write_inferior_data_ptr (ipa_action + offsetof (struct eval_expr_action, expr)
+                          - offsetof (struct tracepoint_action, type),
+                          expr);
+
+  return ipa_action;
+}
+
+/* Copy agent expression AEXPR to buffer pointed by P.  If AEXPR is NULL,
+   copy 0 to P.  Return updated header of buffer.  */
+
+static char *
+agent_expr_send (char *p, const struct agent_expr *aexpr)
+{
+  /* Copy the length of condition first, and then copy its
+     content.  */
+  if (aexpr == NULL)
+    {
+      memset (p, 0, 4);
+      p += 4;
+    }
+  else
+    {
+      memcpy (p, &aexpr->length, 4);
+      p +=4;
+
+      memcpy (p, aexpr->bytes, aexpr->length);
+      p += aexpr->length;
+    }
+  return p;
+}
+
+static char *
+x_tracepoint_action_send ( char *buffer, const struct tracepoint_action *action)
+{
+  struct eval_expr_action *eaction = (struct eval_expr_action *) action;
+
+  return agent_expr_send (buffer, eaction->expr);
+}
+
+static const struct tracepoint_action_ops x_tracepoint_action_ops =
+{
+  x_tracepoint_action_download,
+  x_tracepoint_action_send,
+};
+
+static CORE_ADDR
+l_tracepoint_action_download (const struct tracepoint_action *action)
+{
+  int size_in_ipa = (sizeof (struct collect_static_trace_data_action)
+                    - offsetof (struct tracepoint_action, type));
+  CORE_ADDR ipa_action = target_malloc (size_in_ipa);
+
+  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
+                        size_in_ipa);
+
+  return ipa_action;
+}
+
+static char *
+l_tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
+{
+  return buffer;
+}
+
+static const struct tracepoint_action_ops l_tracepoint_action_ops =
+{
+  l_tracepoint_action_download,
+  l_tracepoint_action_send,
+};
+#endif
+
 /* 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 +690,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;
@@ -592,7 +717,7 @@ struct tracepoint
 {
   /* The number of the tracepoint, as specified by GDB.  Several
      tracepoint objects here may share a number.  */
-  int number;
+  uint32_t number;
 
   /* Address at which the tracepoint is supposed to trigger.  Several
      tracepoints may share an address.  */
@@ -602,27 +727,30 @@ struct tracepoint
   enum tracepoint_type type;
 
   /* True if the tracepoint is currently enabled.  */
-  int enabled;
+  int8_t enabled;
 
   /* The number of single steps that will be performed after each
      tracepoint hit.  */
-  long step_count;
+  uint64_t step_count;
 
   /* The number of times the tracepoint may be hit before it will
      terminate the entire tracing run.  */
-  long pass_count;
+  uint64_t pass_count;
 
   /* Pointer to the agent expression that is the tracepoint's
      conditional, or NULL if the tracepoint is unconditional.  */
   struct agent_expr *cond;
 
   /* The list of actions to take when the tracepoint triggers.  */
-  int numactions;
+  uint32_t numactions;
   struct tracepoint_action **actions;
 
   /* Count of the times we've hit this tracepoint during the run.
      Note that while-stepping steps are not counted as "hits".  */
-  long hit_count;
+  uint64_t hit_count;
+
+  /* Cached sum of the sizes of traceframes created by this point.  */
+  uint64_t traceframe_usage;
 
   CORE_ADDR compiled_cond;
 
@@ -642,7 +770,7 @@ struct tracepoint
   /* The number of bytes displaced by fast tracepoints. It may subsume
      multiple instructions, for multi-byte fast tracepoints.  This
      field is only valid for fast tracepoints.  */
-  int orig_size;
+  uint32_t orig_size;
 
   /* Only for fast tracepoints.  */
   CORE_ADDR obj_addr_on_target;
@@ -659,6 +787,12 @@ struct tracepoint
   CORE_ADDR jump_pad;
   CORE_ADDR jump_pad_end;
 
+  /* The address range of the piece of the trampoline buffer that was
+     assigned to this fast tracepoint.  (_end is actually one byte
+     past the end).  */
+  CORE_ADDR trampoline;
+  CORE_ADDR trampoline_end;
+
   /* The list of actions to take while in a stepping loop.  These
      fields are only valid for patch-based tracepoints.  */
   int num_step_actions;
@@ -667,8 +801,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
 
@@ -700,47 +834,34 @@ struct wstep_state
 
 #endif
 
+EXTERN_C_PUSH
+
 /* The linked list of all tracepoints.  Marked explicitly as used as
    the in-process library doesn't use it for the fast tracepoints
    support.  */
-IP_AGENT_EXPORT struct tracepoint *tracepoints ATTR_USED;
-
-#ifndef IN_PROCESS_AGENT
-
-/* Pointer to the last tracepoint in the list, new tracepoints are
-   linked in at the end.  */
-
-static struct tracepoint *last_tracepoint;
-#endif
+IP_AGENT_EXPORT_VAR struct tracepoint *tracepoints;
 
 /* The first tracepoint to exceed its pass count.  */
 
-IP_AGENT_EXPORT struct tracepoint *stopping_tracepoint;
+IP_AGENT_EXPORT_VAR struct tracepoint *stopping_tracepoint;
 
 /* True if the trace buffer is full or otherwise no longer usable.  */
 
-IP_AGENT_EXPORT int trace_buffer_is_full;
+IP_AGENT_EXPORT_VAR int trace_buffer_is_full;
 
-/* Enumeration of the different kinds of things that can happen during
-   agent expression evaluation.  */
+/* The first error that occurred during expression evaluation.  */
 
-enum eval_result_type
-  {
-    expr_eval_no_error,
-    expr_eval_empty_expression,
-    expr_eval_empty_stack,
-    expr_eval_stack_overflow,
-    expr_eval_stack_underflow,
-    expr_eval_unhandled_opcode,
-    expr_eval_unrecognized_opcode,
-    expr_eval_divide_by_zero,
-    expr_eval_invalid_goto
-  };
+IP_AGENT_EXPORT_VAR enum eval_result_type expr_eval_result = expr_eval_no_error;
 
-static enum eval_result_type expr_eval_result = expr_eval_no_error;
+EXTERN_C_POP
 
 #ifndef IN_PROCESS_AGENT
 
+/* Pointer to the last tracepoint in the list, new tracepoints are
+   linked in at the end.  */
+
+static struct tracepoint *last_tracepoint;
+
 static const char *eval_result_names[] =
   {
     "terror:in the attic",  /* this should never be reported */
@@ -757,7 +878,9 @@ static const char *eval_result_names[] =
 
 /* The tracepoint in which the error occurred.  */
 
-static struct tracepoint *error_tracepoint;
+EXTERN_C_PUSH
+IP_AGENT_EXPORT_VAR struct tracepoint *error_tracepoint;
+EXTERN_C_POP
 
 struct trace_state_variable
 {
@@ -791,7 +914,7 @@ struct trace_state_variable
 struct trace_state_variable *alloced_trace_state_variables;
 #endif
 
-IP_AGENT_EXPORT struct trace_state_variable *trace_state_variables;
+IP_AGENT_EXPORT_VAR struct trace_state_variable *trace_state_variables;
 
 /* The results of tracing go into a fixed-size space known as the
    "trace buffer".  Because usage follows a limited number of
@@ -853,6 +976,10 @@ struct traceframe
 
 } ATTR_PACKED;
 
+/* The size of the EOB marker, in bytes.  A traceframe with zeroed
+   fields (and no data) marks the end of trace data.  */
+#define TRACEFRAME_EOB_MARKER_SIZE offsetof (struct traceframe, data)
+
 /* The traceframe to be used as the source of data to send back to
    GDB.  A value of -1 means to get data from the live program.  */
 
@@ -866,14 +993,22 @@ int current_traceframe = -1;
 static int circular_trace_buffer;
 #endif
 
+/* Size of the trace buffer.  */
+
+static LONGEST trace_buffer_size;
+
+EXTERN_C_PUSH
+
 /* Pointer to the block of memory that traceframes all go into.  */
 
-static unsigned char *trace_buffer_lo;
+IP_AGENT_EXPORT_VAR unsigned char *trace_buffer_lo;
 
 /* Pointer to the end of the trace buffer, more precisely to the byte
    after the end of the buffer.  */
 
-static unsigned char *trace_buffer_hi;
+IP_AGENT_EXPORT_VAR unsigned char *trace_buffer_hi;
+
+EXTERN_C_POP
 
 /* Control structure holding the read/write/etc. pointers into the
    trace buffer.  We need more than one of these to implement a
@@ -1027,8 +1162,8 @@ A GDBserver update of `trace_buffer_ctrl_curr' does:
 #define GDBSERVER_UPDATED_FLUSH_COUNT_BIT 0x80000000
 
 #ifdef IN_PROCESS_AGENT
-IP_AGENT_EXPORT struct trace_buffer_control trace_buffer_ctrl[3];
-IP_AGENT_EXPORT unsigned int trace_buffer_ctrl_curr;
+IP_AGENT_EXPORT_VAR struct trace_buffer_control trace_buffer_ctrl[3];
+IP_AGENT_EXPORT_VAR unsigned int trace_buffer_ctrl_curr;
 
 # define TRACE_BUFFER_CTRL_CURR \
   (trace_buffer_ctrl_curr & ~GDBSERVER_FLUSH_COUNT_MASK)
@@ -1073,8 +1208,8 @@ struct trace_buffer_control trace_buffer_ctrl[1];
    of complete traceframes present in the trace buffer.  The IP agent
    writes to the write count, GDBserver writes to read count.  */
 
-IP_AGENT_EXPORT unsigned int traceframe_write_count;
-IP_AGENT_EXPORT unsigned int traceframe_read_count;
+IP_AGENT_EXPORT_VAR unsigned int traceframe_write_count;
+IP_AGENT_EXPORT_VAR unsigned int traceframe_read_count;
 
 /* Convenience macro.  */
 
@@ -1084,7 +1219,7 @@ IP_AGENT_EXPORT unsigned int traceframe_read_count;
 /* The count of all traceframes created in the current run, including
    ones that were discarded to make room.  */
 
-IP_AGENT_EXPORT int traceframes_created;
+IP_AGENT_EXPORT_VAR int traceframes_created;
 
 #ifndef IN_PROCESS_AGENT
 
@@ -1114,7 +1249,7 @@ static struct readonly_region *readonly_regions;
 
 /* The global that controls tracing overall.  */
 
-IP_AGENT_EXPORT int tracing;
+IP_AGENT_EXPORT_VAR int tracing;
 
 #ifndef IN_PROCESS_AGENT
 
@@ -1130,6 +1265,27 @@ static const char *tracing_stop_reason = "tnotrun";
 
 static int tracing_stop_tpnum;
 
+/* 64-bit timestamps for the trace run's start and finish, expressed
+   in microseconds from the Unix epoch.  */
+
+LONGEST tracing_start_time;
+LONGEST tracing_stop_time;
+
+/* The (optional) user-supplied name of the user that started the run.
+   This is an arbitrary string, and may be NULL.  */
+
+char *tracing_user_name;
+
+/* Optional user-supplied text describing the run.  This is
+   an arbitrary string, and may be NULL.  */
+
+char *tracing_notes;
+
+/* Optional user-supplied text explaining a tstop command.  This is an
+   arbitrary string, and may be NULL.  */
+
+char *tracing_stop_note;
+
 #endif
 
 /* Functions local to this file.  */
@@ -1157,6 +1313,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
@@ -1170,19 +1355,6 @@ struct trap_tracepoint_ctx
 
 #endif
 
-#ifndef IN_PROCESS_AGENT
-static struct agent_expr *parse_agent_expr (char **actparm);
-static char *unparse_agent_expr (struct agent_expr *aexpr);
-#endif
-static enum eval_result_type eval_agent_expr (struct tracepoint_hit_ctx *ctx,
-                                             struct traceframe *tframe,
-                                             struct agent_expr *aexpr,
-                                             ULONGEST *rslt);
-
-static int agent_mem_read (struct traceframe *tframe,
-                          unsigned char *to, CORE_ADDR from, ULONGEST len);
-static int agent_tsv_read (struct traceframe *tframe, int n);
-
 #ifndef IN_PROCESS_AGENT
 static CORE_ADDR traceframe_get_pc (struct traceframe *tframe);
 static int traceframe_read_tsv (int num, LONGEST *val);
@@ -1214,8 +1386,16 @@ static void do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
 
 #ifndef IN_PROCESS_AGENT
 static struct tracepoint *fast_tracepoint_from_ipa_tpoint_address (CORE_ADDR);
+
+static void install_tracepoint (struct tracepoint *, char *own_buf);
+static void download_tracepoint (struct tracepoint *);
+static int install_fast_tracepoint (struct tracepoint *, char *errbuf);
+static void clone_fast_tracepoint (struct tracepoint *to,
+                                  const struct tracepoint *from);
 #endif
 
+static LONGEST get_timestamp (void);
+
 #if defined(__GNUC__)
 #  define memory_barrier() asm volatile ("" : : : "memory")
 #else
@@ -1307,17 +1487,26 @@ clear_inferior_trace_buffer (void)
 #endif
 
 static void
-init_trace_buffer (unsigned char *buf, int bufsize)
+init_trace_buffer (LONGEST bufsize)
 {
-  trace_buffer_lo = buf;
-  trace_buffer_hi = trace_buffer_lo + bufsize;
+  size_t alloc_size;
+
+  trace_buffer_size = bufsize;
+
+  /* Make sure to internally allocate at least space for the EOB
+     marker.  */
+  alloc_size = (bufsize < TRACEFRAME_EOB_MARKER_SIZE
+               ? TRACEFRAME_EOB_MARKER_SIZE : bufsize);
+  trace_buffer_lo = xrealloc (trace_buffer_lo, alloc_size);
+
+  trace_buffer_hi = trace_buffer_lo + trace_buffer_size;
 
   clear_trace_buffer ();
 }
 
 #ifdef IN_PROCESS_AGENT
 
-IP_AGENT_EXPORT void ATTR_USED ATTR_NOINLINE
+IP_AGENT_EXPORT_FUNC void
 about_to_request_buffer_space (void)
 {
   /* GDBserver places breakpoint here while it goes about to flush
@@ -1350,7 +1539,7 @@ trace_buffer_alloc (size_t amt)
               (long) amt, (long) sizeof (struct traceframe));
 
   /* Account for the EOB marker.  */
-  amt += sizeof (struct traceframe);
+  amt += TRACEFRAME_EOB_MARKER_SIZE;
 
 #ifdef IN_PROCESS_AGENT
  again:
@@ -1508,8 +1697,9 @@ trace_buffer_alloc (size_t amt)
 
 #ifdef IN_PROCESS_AGENT
   /* Build the tentative token.  */
-  commit_count = (((prev & 0x0007ff00) + 0x100) & 0x0007ff00);
-  commit = (((prev & 0x0007ff00) << 12)
+  commit_count = (((prev & GDBSERVER_FLUSH_COUNT_MASK_CURR) + 0x100)
+                 & GDBSERVER_FLUSH_COUNT_MASK_CURR);
+  commit = (((prev & GDBSERVER_FLUSH_COUNT_MASK_CURR) << 12)
            | commit_count
            | curr);
 
@@ -1541,8 +1731,8 @@ trace_buffer_alloc (size_t amt)
 
     refetch = trace_buffer_ctrl_curr;
 
-    if ((refetch == commit
-        || ((refetch & 0x7ff00000) >> 12) == commit_count))
+    if (refetch == commit
+       || ((refetch & GDBSERVER_FLUSH_COUNT_MASK_PREV) >> 12) == commit_count)
       {
        /* effective */
        trace_debug ("change is effective: (prev=%08x, commit=%08x, "
@@ -1605,12 +1795,13 @@ free_space (void)
 
 static int seen_step_action_flag;
 
-/* Create a tracepoint (location) with given number and address.  */
+/* Create a tracepoint (location) with given number and address.  Add this
+   new tracepoint to list and sort this list.  */
 
 static struct tracepoint *
 add_tracepoint (int num, CORE_ADDR addr)
 {
-  struct tracepoint *tpoint;
+  struct tracepoint *tpoint, **tp_next;
 
   tpoint = xmalloc (sizeof (struct tracepoint));
   tpoint->number = num;
@@ -1630,10 +1821,31 @@ add_tracepoint (int num, CORE_ADDR addr)
   tpoint->handle = NULL;
   tpoint->next = NULL;
 
-  if (!last_tracepoint)
-    tracepoints = tpoint;
-  else
-    last_tracepoint->next = tpoint;
+  /* Find a place to insert this tracepoint into list in order to keep
+     the tracepoint list still in the ascending order.  There may be
+     multiple tracepoints at the same address as TPOINT's, and this
+     guarantees TPOINT is inserted after all the tracepoints which are
+     set at the same address.  For example, fast tracepoints A, B, C are
+     set at the same address, and D is to be insert at the same place as
+     well,
+
+     -->| A |--> | B |-->| C |->...
+
+     One jump pad was created for tracepoint A, B, and C, and the target
+     address of A is referenced/used in jump pad.  So jump pad will let
+     inferior jump to A.  If D is inserted in front of A, like this,
+
+     -->| D |-->| A |--> | B |-->| C |->...
+
+     without updating jump pad, D is not reachable during collect, which
+     is wrong.  As we can see, the order of B, C and D doesn't matter, but
+     A should always be the `first' one.  */
+  for (tp_next = &tracepoints;
+       (*tp_next) != NULL && (*tp_next)->address <= tpoint->address;
+       tp_next = &(*tp_next)->next)
+    ;
+  tpoint->next = *tp_next;
+  *tp_next = tpoint;
   last_tracepoint = tpoint;
 
   seen_step_action_flag = 0;
@@ -1657,6 +1869,28 @@ find_tracepoint (int id, CORE_ADDR addr)
   return NULL;
 }
 
+/* Remove TPOINT from global list.  */
+
+static void
+remove_tracepoint (struct tracepoint *tpoint)
+{
+  struct tracepoint *tp, *tp_prev;
+
+  for (tp = tracepoints, tp_prev = NULL; tp && tp != tpoint;
+       tp_prev = tp, tp = tp->next)
+    ;
+
+  if (tp)
+    {
+      if (tp_prev)
+       tp_prev->next = tp->next;
+      else
+       tracepoints = tp->next;
+
+      xfree (tp);
+    }
+}
+
 /* There may be several tracepoints with the same number (because they
    are "locations", in GDB parlance); return the next one after the
    given tracepoint, or search from the beginning of the list if the
@@ -1680,18 +1914,6 @@ find_next_tracepoint_by_number (struct tracepoint *prev_tp, int num)
 
 #endif
 
-static char *
-save_string (const char *str, size_t len)
-{
-  char *s;
-
-  s = xmalloc (len + 1);
-  memcpy (s, str, len);
-  s[len] = '\0';
-
-  return s;
-}
-
 /* Append another action to perform when the tracepoint triggers.  */
 
 static void
@@ -1722,6 +1944,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
            maction = xmalloc (sizeof *maction);
            maction->base.type = *act;
+           maction->base.ops = &m_tracepoint_action_ops;
            action = &maction->base;
 
            ++act;
@@ -1747,6 +1970,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
            raction = xmalloc (sizeof *raction);
            raction->base.type = *act;
+           raction->base.ops = &r_tracepoint_action_ops;
            action = &raction->base;
 
            trace_debug ("Want to collect registers");
@@ -1756,6 +1980,19 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
              ++act;
            break;
          }
+       case 'L':
+         {
+           struct collect_static_trace_data_action *raction;
+
+           raction = xmalloc (sizeof *raction);
+           raction->base.type = *act;
+           raction->base.ops = &l_tracepoint_action_ops;
+           action = &raction->base;
+
+           trace_debug ("Want to collect static trace data");
+           ++act;
+           break;
+         }
        case 'S':
          trace_debug ("Unexpected step action, ignoring");
          ++act;
@@ -1766,10 +2003,11 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
            xaction = xmalloc (sizeof (*xaction));
            xaction->base.type = *act;
+           xaction->base.ops = &x_tracepoint_action_ops;
            action = &xaction->base;
 
            trace_debug ("Want to evaluate expression");
-           xaction->expr = parse_agent_expr (&act);
+           xaction->expr = gdb_parse_agent_expr (&act);
            break;
          }
        default:
@@ -1796,7 +2034,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
                         * tpoint->num_step_actions));
          tpoint->step_actions[tpoint->num_step_actions - 1] = action;
          tpoint->step_actions_str[tpoint->num_step_actions - 1]
-           = save_string (act_start, act - act_start);
+           = savestring (act_start, act - act_start);
        }
       else
        {
@@ -1809,7 +2047,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
                        sizeof (*tpoint->actions_str) * tpoint->numactions);
          tpoint->actions[tpoint->numactions - 1] = action;
          tpoint->actions_str[tpoint->numactions - 1]
-           = save_string (act_start, act - act_start);
+           = savestring (act_start, act - act_start);
        }
     }
 }
@@ -1871,7 +2109,7 @@ create_trace_state_variable (int num, int gdb)
   return tsv;
 }
 
-IP_AGENT_EXPORT LONGEST
+IP_AGENT_EXPORT_FUNC LONGEST
 get_trace_state_variable_value (int num)
 {
   struct trace_state_variable *tsv;
@@ -1897,7 +2135,7 @@ get_trace_state_variable_value (int num)
   return tsv->value;
 }
 
-IP_AGENT_EXPORT void
+IP_AGENT_EXPORT_FUNC void
 set_trace_state_variable_value (int num, LONGEST val)
 {
   struct trace_state_variable *tsv;
@@ -1913,6 +2151,18 @@ set_trace_state_variable_value (int num, LONGEST val)
   tsv->value = val;
 }
 
+LONGEST
+agent_get_trace_state_variable_value (int num)
+{
+  return get_trace_state_variable_value (num);
+}
+
+void
+agent_set_trace_state_variable_value (int num, LONGEST val)
+{
+  set_trace_state_variable_value (num, val);
+}
+
 static void
 set_trace_state_variable_name (int num, const char *name)
 {
@@ -1966,7 +2216,8 @@ add_traceframe (struct tracepoint *tpoint)
 /* Add a block to the traceframe currently being worked on.  */
 
 static unsigned char *
-add_traceframe_block (struct traceframe *tframe, int amt)
+add_traceframe_block (struct traceframe *tframe,
+                     struct tracepoint *tpoint, int amt)
 {
   unsigned char *block;
 
@@ -1978,7 +2229,10 @@ add_traceframe_block (struct traceframe *tframe, int amt)
   if (!block)
     return NULL;
 
+  gdb_assert (tframe->tpnum == tpoint->number);
+
   tframe->data_size += amt;
+  tpoint->traceframe_usage += amt;
 
   return block;
 }
@@ -2105,9 +2359,18 @@ cmd_qtinit (char *packet)
 {
   struct trace_state_variable *tsv, *prev, *next;
 
+  /* Can't do this command without a pid attached.  */
+  if (current_thread == NULL)
+    {
+      write_enn (packet);
+      return;
+    }
+
   /* Make sure we don't try to read from a trace frame.  */
   current_traceframe = -1;
 
+  stop_tracing ();
+
   trace_debug ("Initializing the trace");
 
   clear_installed_tracepoints ();
@@ -2147,27 +2410,34 @@ cmd_qtinit (char *packet)
   write_ok (packet);
 }
 
-/* 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.  */
+/* Unprobe the UST marker at ADDRESS.  */
 
 static void
-clear_installed_tracepoints (void)
+unprobe_marker_at (CORE_ADDR address)
 {
-  struct tracepoint *tpoint;
+  char cmd[IPA_CMD_BUF_SIZE];
+
+  sprintf (cmd, "unprobe_marker_at:%s", paddress (address));
+  run_inferior_command (cmd, strlen (cmd) + 1);
+}
+
+/* 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.  */
+
+static void
+clear_installed_tracepoints (void)
+{
+  struct tracepoint *tpoint;
   struct tracepoint *prev_stpoint;
 
   pause_all (1);
-  cancel_breakpoints ();
 
   prev_stpoint = NULL;
 
   /* Restore any bytes overwritten by tracepoints.  */
   for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
     {
-      if (!tpoint->enabled)
-       continue;
-
       /* Catch the case where we might try to remove a tracepoint that
         was never actually installed.  */
       if (tpoint->handle == NULL)
@@ -2186,6 +2456,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;
@@ -2200,6 +2483,8 @@ static void
 cmd_qtdp (char *own_buf)
 {
   int tppacket;
+  /* Whether there is a trailing hyphen at the end of the QTDP packet.  */
+  int trail_hyphen = 0;
   ULONGEST num;
   ULONGEST addr;
   ULONGEST count;
@@ -2258,10 +2543,15 @@ 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;
-             tpoint->cond = parse_agent_expr (&actparm);
+             tpoint->cond = gdb_parse_agent_expr (&actparm);
              packet = actparm;
            }
          else if (*packet == '-')
@@ -2272,12 +2562,15 @@ cmd_qtdp (char *own_buf)
            trace_debug ("Unknown optional tracepoint field");
        }
       if (*packet == '-')
-       trace_debug ("Also has actions\n");
+       {
+         trail_hyphen = 1;
+         trace_debug ("Also has actions\n");
+       }
 
       trace_debug ("Defined %stracepoint %d at 0x%s, "
-                  "enabled %d step %ld pass %ld",
+                  "enabled %d step %" PRIu64 " pass %" PRIu64,
                   tpoint->type == fast_tracepoint ? "fast "
-                  : "",
+                  : tpoint->type == static_tracepoint ? "static " : "",
                   tpoint->number, paddress (tpoint->address), tpoint->enabled,
                   tpoint->step_count, tpoint->pass_count);
     }
@@ -2291,6 +2584,75 @@ cmd_qtdp (char *own_buf)
       return;
     }
 
+  /* Install tracepoint during tracing only once for each tracepoint location.
+     For each tracepoint loc, GDB may send multiple QTDP packets, and we can
+     determine the last QTDP packet for one tracepoint location by checking
+     trailing hyphen in QTDP packet.  */
+  if (tracing && !trail_hyphen)
+    {
+      struct tracepoint *tp = NULL;
+
+      /* Pause all threads temporarily while we patch tracepoints.  */
+      pause_all (0);
+
+      /* download_tracepoint will update global `tracepoints'
+        list, so it is unsafe to leave threads in jump pad.  */
+      stabilize_threads ();
+
+      /* Freeze threads.  */
+      pause_all (1);
+
+
+      if (tpoint->type != trap_tracepoint)
+       {
+         /* Find another fast or static tracepoint at the same address.  */
+         for (tp = tracepoints; tp; tp = tp->next)
+           {
+             if (tp->address == tpoint->address && tp->type == tpoint->type
+                 && tp->number != tpoint->number)
+               break;
+           }
+
+         /* TPOINT is installed at the same address as TP.  */
+         if (tp)
+           {
+             if (tpoint->type == fast_tracepoint)
+               clone_fast_tracepoint (tpoint, tp);
+             else if (tpoint->type == static_tracepoint)
+               tpoint->handle = (void *) -1;
+           }
+       }
+
+      if (use_agent && tpoint->type == fast_tracepoint
+         && agent_capability_check (AGENT_CAPA_FAST_TRACE))
+       {
+         /* Download and install fast tracepoint by agent.  */
+         if (tracepoint_send_agent (tpoint) == 0)
+           write_ok (own_buf);
+         else
+           {
+             write_enn (own_buf);
+             remove_tracepoint (tpoint);
+           }
+       }
+      else
+       {
+         download_tracepoint (tpoint);
+
+         if (tpoint->type == trap_tracepoint || tp == NULL)
+           {
+             install_tracepoint (tpoint, own_buf);
+             if (strcmp (own_buf, "OK") != 0)
+               remove_tracepoint (tpoint);
+           }
+         else
+           write_ok (own_buf);
+       }
+
+      unpause_all (1);
+      return;
+    }
+
   write_ok (own_buf);
 }
 
@@ -2333,7 +2695,7 @@ cmd_qtdpsrc (char *own_buf)
   packet = unpack_varlen_hex (packet, &slen);
   ++packet; /* skip a colon */
   src = xmalloc (slen + 1);
-  nbytes = unhexify (src, packet, strlen (packet) / 2);
+  nbytes = hex2bin (packet, (gdb_byte *) src, strlen (packet) / 2);
   src[nbytes] = '\0';
 
   newlast = xmalloc (sizeof (struct source_string));
@@ -2375,7 +2737,7 @@ cmd_qtdv (char *own_buf)
 
   nbytes = strlen (packet) / 2;
   varname = xmalloc (nbytes + 1);
-  nbytes = unhexify (varname, packet, nbytes);
+  nbytes = hex2bin (packet, (gdb_byte *) varname, nbytes);
   varname[nbytes] = '\0';
 
   tsv = create_trace_state_variable (num, 1);
@@ -2387,16 +2749,83 @@ cmd_qtdv (char *own_buf)
   write_ok (own_buf);
 }
 
+static void
+cmd_qtenable_disable (char *own_buf, int enable)
+{
+  char *packet = own_buf;
+  ULONGEST num, addr;
+  struct tracepoint *tp;
+
+  packet += strlen (enable ? "QTEnable:" : "QTDisable:");
+  packet = unpack_varlen_hex (packet, &num);
+  ++packet; /* skip a colon */
+  packet = unpack_varlen_hex (packet, &addr);
+
+  tp = find_tracepoint (num, addr);
+
+  if (tp)
+    {
+      if ((enable && tp->enabled) || (!enable && !tp->enabled))
+       {
+         trace_debug ("Tracepoint %d at 0x%s is already %s",
+                      (int) num, paddress (addr),
+                      enable ? "enabled" : "disabled");
+         write_ok (own_buf);
+         return;
+       }
+
+      trace_debug ("%s tracepoint %d at 0x%s",
+                  enable ? "Enabling" : "Disabling",
+                  (int) num, paddress (addr));
+
+      tp->enabled = enable;
+
+      if (tp->type == fast_tracepoint || tp->type == static_tracepoint)
+       {
+         int ret;
+         int offset = offsetof (struct tracepoint, enabled);
+         CORE_ADDR obj_addr = tp->obj_addr_on_target + offset;
+
+         ret = prepare_to_access_memory ();
+         if (ret)
+           {
+             trace_debug ("Failed to temporarily stop inferior threads");
+             write_enn (own_buf);
+             return;
+           }
+         
+         ret = write_inferior_integer (obj_addr, enable);
+         done_accessing_memory ();
+         
+         if (ret)
+           {
+             trace_debug ("Cannot write enabled flag into "
+                          "inferior process memory");
+             write_enn (own_buf);
+             return;
+           }
+       }
+
+      write_ok (own_buf);
+    }
+  else
+    {
+      trace_debug ("Tracepoint %d at 0x%s not found",
+                  (int) num, paddress (addr));
+      write_enn (own_buf);
+    }
+}
+
 static void
 cmd_qtv (char *own_buf)
 {
   ULONGEST num;
-  LONGEST val;
+  LONGEST val = 0;
   int err;
   char *packet = own_buf;
 
   packet += strlen ("qTV:");
-  packet = unpack_varlen_hex (packet, &num);
+  unpack_varlen_hex (packet, &num);
 
   if (current_traceframe >= 0)
     {
@@ -2501,7 +2930,10 @@ get_jump_space_head (void)
     {
       if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_jump_pad_buffer,
                                      &gdb_jump_pad_head))
-       fatal ("error extracting jump_pad_buffer");
+       {
+         internal_error (__FILE__, __LINE__,
+                         "error extracting jump_pad_buffer");
+       }
     }
 
   return gdb_jump_pad_head;
@@ -2517,80 +2949,258 @@ claim_jump_space (ULONGEST used)
   gdb_jump_pad_head += used;
 }
 
-/* Sort tracepoints by PC, using a bubble sort.  */
+static CORE_ADDR trampoline_buffer_head = 0;
+static CORE_ADDR trampoline_buffer_tail;
 
-static void
-sort_tracepoints (void)
+/* Reserve USED bytes from the trampoline buffer and return the
+   address of the start of the reserved space in TRAMPOLINE.  Returns
+   non-zero if the space is successfully claimed.  */
+
+int
+claim_trampoline_space (ULONGEST used, CORE_ADDR *trampoline)
 {
-  struct tracepoint *lst, *tmp, *prev = NULL;
-  int i, j, n = 0;
+  if (!trampoline_buffer_head)
+    {
+      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer,
+                                     &trampoline_buffer_tail))
+       {
+         internal_error (__FILE__, __LINE__,
+                         "error extracting trampoline_buffer");
+       }
 
-  if (tracepoints == NULL)
-    return;
+      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+                                     &trampoline_buffer_head))
+       {
+         internal_error (__FILE__, __LINE__,
+                         "error extracting trampoline_buffer_end");
+       }
+    }
 
-  /* Count nodes.  */
-  for (tmp = tracepoints; tmp->next; tmp = tmp->next)
-    n++;
+  /* Start claiming space from the top of the trampoline space.  If
+     the space is located at the bottom of the virtual address space,
+     this reduces the possibility that corruption will occur if a null
+     pointer is used to write to memory.  */
+  if (trampoline_buffer_head - trampoline_buffer_tail < used)
+    {
+      trace_debug ("claim_trampoline_space failed to reserve %s bytes",
+                  pulongest (used));
+      return 0;
+    }
 
-  for (i = 0; i < n - 1; i++)
-    for (j = 0, lst = tracepoints;
-        lst && lst->next && (j <= n - 1 - i);
-        j++)
-      {
-       /* If we're at beginning, the start node is the prev
-          node.  */
-       if (j == 0)
-         prev = lst;
+  trampoline_buffer_head -= used;
 
-       /* Compare neighbors.  */
-       if (lst->next->address < lst->address)
-         {
-           struct tracepoint *p;
+  trace_debug ("claim_trampoline_space reserves %s bytes at %s",
+              pulongest (used), paddress (trampoline_buffer_head));
 
-           /* Swap'em.  */
-           tmp = (lst->next ? lst->next->next : NULL);
+  *trampoline = trampoline_buffer_head;
+  return 1;
+}
 
-           if (j == 0 && prev == tracepoints)
-             tracepoints = lst->next;
+/* Returns non-zero if there is space allocated for use in trampolines
+   for fast tracepoints.  */
 
-           p = lst->next;
-           prev->next = lst->next;
-           lst->next->next = lst;
-           lst->next = tmp;
-           prev = p;
-         }
-       else
-         {
-           lst = lst->next;
-           /* Keep track of the previous node.  We need it if we need
-              to swap nodes.  */
-           if (j != 0)
-             prev = prev->next;
-         }
-      }
+int
+have_fast_tracepoint_trampoline_buffer (char *buf)
+{
+  CORE_ADDR trampoline_end, errbuf;
+
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+                                 &trampoline_end))
+    {
+      internal_error (__FILE__, __LINE__,
+                     "error extracting trampoline_buffer_end");
+    }
+  
+  if (buf)
+    {
+      buf[0] = '\0';
+      strcpy (buf, "was claiming");
+      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_error,
+                                 &errbuf))
+       {
+         internal_error (__FILE__, __LINE__,
+                         "error extracting errbuf");
+       }
+
+      read_inferior_memory (errbuf, (unsigned char *) buf, 100);
+    }
+
+  return trampoline_end != 0;
 }
 
-#define MAX_JUMP_SIZE 20
+/* 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[IPA_CMD_BUF_SIZE];
+  int err;
+
+  sprintf (cmd, "probe_marker_at:%s", paddress (address));
+  err = run_inferior_command (cmd, strlen (cmd) + 1);
+
+  if (err == 0)
+    {
+      if (*cmd == 'E')
+       {
+         strcpy (errout, cmd);
+         return -1;
+       }
+    }
+
+  return err;
+}
 
 static void
-cmd_qtstart (char *packet)
+clone_fast_tracepoint (struct tracepoint *to, const struct tracepoint *from)
 {
-  struct tracepoint *tpoint, *prev_ftpoint;
-  int slow_tracepoint_count, fast_count;
-  CORE_ADDR jump_entry;
+  to->jump_pad = from->jump_pad;
+  to->jump_pad_end = from->jump_pad_end;
+  to->trampoline = from->trampoline;
+  to->trampoline_end = from->trampoline_end;
+  to->adjusted_insn_addr = from->adjusted_insn_addr;
+  to->adjusted_insn_addr_end = from->adjusted_insn_addr_end;
+  to->handle = from->handle;
+
+  gdb_assert (from->handle);
+  inc_ref_fast_tracepoint_jump ((struct fast_tracepoint_jump *) from->handle);
+}
+
+#define MAX_JUMP_SIZE 20
 
+/* Install fast tracepoint.  Return 0 if successful, otherwise return
+   non-zero.  */
+
+static int
+install_fast_tracepoint (struct tracepoint *tpoint, char *errbuf)
+{
+  CORE_ADDR jentry, jump_entry;
+  CORE_ADDR trampoline;
+  ULONGEST trampoline_size;
+  int err = 0;
   /* The jump to the jump pad of the last fast tracepoint
      installed.  */
   unsigned char fjump[MAX_JUMP_SIZE];
   ULONGEST fjump_size;
 
-  trace_debug ("Starting the trace");
+  if (tpoint->orig_size < target_get_min_fast_tracepoint_insn_len ())
+    {
+      trace_debug ("Requested a fast tracepoint on an instruction "
+                  "that is of less than the minimum length.");
+      return 0;
+    }
+
+  jentry = jump_entry = get_jump_space_head ();
+
+  trampoline = 0;
+  trampoline_size = 0;
+
+  /* Install the jump pad.  */
+  err = install_fast_tracepoint_jump_pad (tpoint->obj_addr_on_target,
+                                         tpoint->address,
+                                         ipa_sym_addrs.addr_gdb_collect,
+                                         ipa_sym_addrs.addr_collecting,
+                                         tpoint->orig_size,
+                                         &jentry,
+                                         &trampoline, &trampoline_size,
+                                         fjump, &fjump_size,
+                                         &tpoint->adjusted_insn_addr,
+                                         &tpoint->adjusted_insn_addr_end,
+                                         errbuf);
+
+  if (err)
+    return 1;
+
+  /* Wire it in.  */
+  tpoint->handle = set_fast_tracepoint_jump (tpoint->address, fjump,
+                                            fjump_size);
+
+  if (tpoint->handle != NULL)
+    {
+      tpoint->jump_pad = jump_entry;
+      tpoint->jump_pad_end = jentry;
+      tpoint->trampoline = trampoline;
+      tpoint->trampoline_end = trampoline + trampoline_size;
+
+      /* Pad to 8-byte alignment.  */
+      jentry = ((jentry + 7) & ~0x7);
+      claim_jump_space (jentry - jump_entry);
+    }
+
+  return 0;
+}
+
+
+/* Install tracepoint TPOINT, and write reply message in OWN_BUF.  */
+
+static void
+install_tracepoint (struct tracepoint *tpoint, char *own_buf)
+{
+  tpoint->handle = NULL;
+  *own_buf = '\0';
+
+  if (tpoint->type == trap_tracepoint)
+    {
+      /* Tracepoints are installed as memory breakpoints.  Just go
+        ahead and install the trap.  The breakpoints module
+        handles duplicated breakpoints, and the memory read
+        routine handles un-patching traps from memory reads.  */
+      tpoint->handle = set_breakpoint_at (tpoint->address,
+                                         tracepoint_handler);
+    }
+  else if (tpoint->type == fast_tracepoint || tpoint->type == static_tracepoint)
+    {
+      if (!agent_loaded_p ())
+       {
+         trace_debug ("Requested a %s tracepoint, but fast "
+                      "tracepoints aren't supported.",
+                      tpoint->type == static_tracepoint ? "static" : "fast");
+         write_e_ipa_not_loaded (own_buf);
+         return;
+       }
+      if (tpoint->type == static_tracepoint
+         && !in_process_agent_supports_ust ())
+       {
+         trace_debug ("Requested a static tracepoint, but static "
+                      "tracepoints are not supported.");
+         write_e_ust_not_loaded (own_buf);
+         return;
+       }
+
+      if (tpoint->type == fast_tracepoint)
+       install_fast_tracepoint (tpoint, own_buf);
+      else
+       {
+         if (probe_marker_at (tpoint->address, own_buf) == 0)
+           tpoint->handle = (void *) -1;
+       }
+
+    }
+  else
+    internal_error (__FILE__, __LINE__, "Unknown tracepoint type");
 
-  slow_tracepoint_count = fast_count = 0;
+  if (tpoint->handle == NULL)
+    {
+      if (*own_buf == '\0')
+       write_enn (own_buf);
+    }
+  else
+    write_ok (own_buf);
+}
+
+static void download_tracepoint_1 (struct tracepoint *tpoint);
+
+static void
+cmd_qtstart (char *packet)
+{
+  struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint;
+  CORE_ADDR tpptr = 0, prev_tpptr = 0;
 
-  /* Sort tracepoints by ascending address.  This makes installing
-     fast tracepoints at the same address easier to handle. */
-  sort_tracepoints ();
+  trace_debug ("Starting the trace");
 
   /* Pause all threads temporarily while we patch tracepoints.  */
   pause_all (0);
@@ -2605,30 +3215,30 @@ cmd_qtstart (char *packet)
   pause_all (1);
 
   /* Sync the fast tracepoints list in the inferior ftlib.  */
-  if (in_process_agent_loaded ())
-    {
-      download_tracepoints ();
-      download_trace_state_variables ();
-    }
+  if (agent_loaded_p ())
+    download_trace_state_variables ();
 
   /* No previous fast tpoint yet.  */
   prev_ftpoint = NULL;
 
+  /* No previous static tpoint yet.  */
+  prev_stpoint = NULL;
+
   *packet = '\0';
 
-  /* Install tracepoints.  */
+  /* Start out empty.  */
+  if (agent_loaded_p ())
+    write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, 0);
+
+  /* Download and install tracepoints.  */
   for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
     {
       /* Ensure all the hit counts start at zero.  */
       tpoint->hit_count = 0;
-
-      if (!tpoint->enabled)
-       continue;
+      tpoint->traceframe_usage = 0;
 
       if (tpoint->type == trap_tracepoint)
        {
-         ++slow_tracepoint_count;
-
          /* Tracepoints are installed as memory breakpoints.  Just go
             ahead and install the trap.  The breakpoints module
             handles duplicated breakpoints, and the memory read
@@ -2636,68 +3246,89 @@ cmd_qtstart (char *packet)
          tpoint->handle = set_breakpoint_at (tpoint->address,
                                              tracepoint_handler);
        }
-      else if (tpoint->type == fast_tracepoint)
+      else if (tpoint->type == fast_tracepoint
+              || tpoint->type == static_tracepoint)
        {
-         ++fast_count;
-
          if (maybe_write_ipa_not_loaded (packet))
            {
-             trace_debug ("Requested a fast tracepoint, but fast "
-                          "tracepoints aren't supported.");
+             trace_debug ("Requested a %s tracepoint, but fast "
+                          "tracepoints aren't supported.",
+                          tpoint->type == static_tracepoint
+                          ? "static" : "fast");
              break;
            }
 
-         if (prev_ftpoint != NULL && prev_ftpoint->address == tpoint->address)
+         if (tpoint->type == fast_tracepoint)
            {
-             tpoint->handle = set_fast_tracepoint_jump (tpoint->address,
-                                                        fjump,
-                                                        fjump_size);
-             tpoint->jump_pad = prev_ftpoint->jump_pad;
-             tpoint->jump_pad_end = prev_ftpoint->jump_pad_end;
-             tpoint->adjusted_insn_addr = prev_ftpoint->adjusted_insn_addr;
-             tpoint->adjusted_insn_addr_end
-               = prev_ftpoint->adjusted_insn_addr_end;
+             int use_agent_p
+               = use_agent && agent_capability_check (AGENT_CAPA_FAST_TRACE);
+
+             if (prev_ftpoint != NULL
+                 && prev_ftpoint->address == tpoint->address)
+               {
+                 if (use_agent_p)
+                   tracepoint_send_agent (tpoint);
+                 else
+                   download_tracepoint_1 (tpoint);
+
+                 clone_fast_tracepoint (tpoint, prev_ftpoint);
+               }
+             else
+               {
+                 /* Tracepoint is installed successfully?  */
+                 int installed = 0;
+
+                 /* Download and install fast tracepoint by agent.  */
+                 if (use_agent_p)
+                   installed = !tracepoint_send_agent (tpoint);
+                 else
+                   {
+                     download_tracepoint_1 (tpoint);
+                     installed = !install_fast_tracepoint (tpoint, packet);
+                   }
+
+                 if (installed)
+                   prev_ftpoint = tpoint;
+               }
            }
          else
            {
-             CORE_ADDR jentry;
-             int err = 0;
-
-             prev_ftpoint = NULL;
-
-             jentry = jump_entry = get_jump_space_head ();
-
-             /* Install the jump pad.  */
-             err = install_fast_tracepoint_jump_pad
-               (tpoint->obj_addr_on_target,
-                tpoint->address,
-                ipa_sym_addrs.addr_gdb_collect,
-                ipa_sym_addrs.addr_collecting,
-                tpoint->orig_size,
-                &jentry,
-                fjump, &fjump_size,
-                &tpoint->adjusted_insn_addr,
-                &tpoint->adjusted_insn_addr_end);
-
-             /* Wire it in.  */
-             if (!err)
-               tpoint->handle = set_fast_tracepoint_jump (tpoint->address,
-                                                          fjump, fjump_size);
-
-             if (tpoint->handle != NULL)
+             if (!in_process_agent_supports_ust ())
                {
-                 tpoint->jump_pad = jump_entry;
-                 tpoint->jump_pad_end = jentry;
-
-                 /* Pad to 8-byte alignment.  */
-                 jentry = ((jentry + 7) & ~0x7);
-                 claim_jump_space (jentry - jump_entry);
+                 trace_debug ("Requested a static tracepoint, but static "
+                              "tracepoints are not supported.");
+                 break;
+               }
 
-                 /* So that we can handle multiple fast tracepoints
-                    at the same address easily.  */
-                 prev_ftpoint = tpoint;
+             download_tracepoint_1 (tpoint);
+             /* 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;
+                   }
                }
            }
+
+         prev_tpptr = tpptr;
+         tpptr = tpoint->obj_addr_on_target;
+
+         if (tpoint == tracepoints)
+           /* First object in list, set the head pointer in the
+              inferior.  */
+           write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, tpptr);
+         else
+           write_inferior_data_ptr (prev_tpptr + offsetof (struct tracepoint,
+                                                           next),
+                                    tpptr);
        }
 
       /* Any failure in the inner loop is sufficient cause to give
@@ -2722,21 +3353,33 @@ cmd_qtstart (char *packet)
   trace_buffer_is_full = 0;
   expr_eval_result = expr_eval_no_error;
   error_tracepoint = NULL;
+  tracing_start_time = get_timestamp ();
 
   /* Tracing is now active, hits will now start being logged.  */
   tracing = 1;
 
-  if (in_process_agent_loaded ())
+  if (agent_loaded_p ())
     {
       if (write_inferior_integer (ipa_sym_addrs.addr_tracing, 1))
-       fatal ("Error setting tracing variable in lib");
+       {
+         internal_error (__FILE__, __LINE__,
+                         "Error setting tracing variable in lib");
+       }
 
       if (write_inferior_data_pointer (ipa_sym_addrs.addr_stopping_tracepoint,
                                       0))
-       fatal ("Error clearing stopping_tracepoint variable in lib");
+       {
+         internal_error (__FILE__, __LINE__,
+                         "Error clearing stopping_tracepoint variable"
+                         " in lib");
+       }
 
       if (write_inferior_integer (ipa_sym_addrs.addr_trace_buffer_is_full, 0))
-       fatal ("Error clearing trace_buffer_is_full variable in lib");
+       {
+         internal_error (__FILE__, __LINE__,
+                         "Error clearing trace_buffer_is_full variable"
+                         " in lib");
+       }
 
       stop_tracing_bkpt = set_breakpoint_at (ipa_sym_addrs.addr_stop_tracing,
                                             stop_tracing_handler);
@@ -2778,25 +3421,26 @@ stop_tracing (void)
      We can't now, since we may be getting here due to the inferior
      agent calling us.  */
   pause_all (1);
-  /* Since we're removing breakpoints, cancel breakpoint hits,
-     possibly related to the breakpoints we're about to delete.  */
-  cancel_breakpoints ();
 
   /* Stop logging. Tracepoints can still be hit, but they will not be
      recorded.  */
   tracing = 0;
-  if (in_process_agent_loaded ())
+  if (agent_loaded_p ())
     {
       if (write_inferior_integer (ipa_sym_addrs.addr_tracing, 0))
-       fatal ("Error clearing tracing variable in lib");
+       {
+         internal_error (__FILE__, __LINE__,
+                         "Error clearing tracing variable in lib");
+       }
     }
 
+  tracing_stop_time = get_timestamp ();
   tracing_stop_reason = "t???";
   tracing_stop_tpnum = 0;
   if (stopping_tracepoint)
     {
       trace_debug ("Stopping the trace because "
-                  "tracepoint %d was hit %ld times",
+                  "tracepoint %d was hit %" PRIu64 " times",
                   stopping_tracepoint->number,
                   stopping_tracepoint->pass_count);
       tracing_stop_reason = "tpasscount";
@@ -2832,7 +3476,7 @@ stop_tracing (void)
   /* Clear out the tracepoints.  */
   clear_installed_tracepoints ();
 
-  if (in_process_agent_loaded ())
+  if (agent_loaded_p ())
     {
       /* Pull in fast tracepoint trace frames from the inferior lib
         buffer into our buffer, even if our buffer is already full,
@@ -2907,38 +3551,38 @@ cmd_qtframe (char *own_buf)
 
   packet += strlen ("QTFrame:");
 
-  if (strncmp (packet, "pc:", strlen ("pc:")) == 0)
+  if (startswith (packet, "pc:"))
     {
       packet += strlen ("pc:");
-      packet = unpack_varlen_hex (packet, &pc);
+      unpack_varlen_hex (packet, &pc);
       trace_debug ("Want to find next traceframe at pc=0x%s", paddress (pc));
       tframe = find_next_traceframe_in_range (pc, pc, 1, &tfnum);
     }
-  else if (strncmp (packet, "range:", strlen ("range:")) == 0)
+  else if (startswith (packet, "range:"))
     {
       packet += strlen ("range:");
       packet = unpack_varlen_hex (packet, &lo);
       ++packet;
-      packet = unpack_varlen_hex (packet, &hi);
+      unpack_varlen_hex (packet, &hi);
       trace_debug ("Want to find next traceframe in the range 0x%s to 0x%s",
                   paddress (lo), paddress (hi));
       tframe = find_next_traceframe_in_range (lo, hi, 1, &tfnum);
     }
-  else if (strncmp (packet, "outside:", strlen ("outside:")) == 0)
+  else if (startswith (packet, "outside:"))
     {
       packet += strlen ("outside:");
       packet = unpack_varlen_hex (packet, &lo);
       ++packet;
-      packet = unpack_varlen_hex (packet, &hi);
+      unpack_varlen_hex (packet, &hi);
       trace_debug ("Want to find next traceframe "
                   "outside the range 0x%s to 0x%s",
                   paddress (lo), paddress (hi));
       tframe = find_next_traceframe_in_range (lo, hi, 0, &tfnum);
     }
-  else if (strncmp (packet, "tdp:", strlen ("tdp:")) == 0)
+  else if (startswith (packet, "tdp:"))
     {
       packet += strlen ("tdp:");
-      packet = unpack_varlen_hex (packet, &num);
+      unpack_varlen_hex (packet, &num);
       tpnum = (int) num;
       trace_debug ("Want to find next traceframe for tracepoint %d", tpnum);
       tframe = find_next_traceframe_by_tracepoint (tpnum, &tfnum);
@@ -2971,11 +3615,31 @@ static void
 cmd_qtstatus (char *packet)
 {
   char *stop_reason_rsp = NULL;
+  char *buf1, *buf2, *buf3, *str;
+  int slen;
+
+  /* Translate the plain text of the notes back into hex for
+     transmission.  */
+
+  str = (tracing_user_name ? tracing_user_name : "");
+  slen = strlen (str);
+  buf1 = (char *) alloca (slen * 2 + 1);
+  bin2hex ((gdb_byte *) str, buf1, slen);
+
+  str = (tracing_notes ? tracing_notes : "");
+  slen = strlen (str);
+  buf2 = (char *) alloca (slen * 2 + 1);
+  bin2hex ((gdb_byte *) str, buf2, slen);
+
+  str = (tracing_stop_note ? tracing_stop_note : "");
+  slen = strlen (str);
+  buf3 = (char *) alloca (slen * 2 + 1);
+  bin2hex ((gdb_byte *) str, buf3, slen);
 
   trace_debug ("Returning trace status as %d, stop reason %s",
               tracing, tracing_stop_reason);
 
-  if (in_process_agent_loaded ())
+  if (agent_loaded_p ())
     {
       pause_all (1);
 
@@ -2987,9 +3651,9 @@ cmd_qtstatus (char *packet)
   stop_reason_rsp = (char *) tracing_stop_reason;
 
   /* The user visible error string in terror needs to be hex encoded.
-     We leave it as plain string in `tracepoint_stop_reason' to ease
+     We leave it as plain string in `tracing_stop_reason' to ease
      debugging.  */
-  if (strncmp (stop_reason_rsp, "terror:", strlen ("terror:")) == 0)
+  if (startswith (stop_reason_rsp, "terror:"))
     {
       const char *result_name;
       int hexstr_len;
@@ -3000,7 +3664,15 @@ cmd_qtstatus (char *packet)
       p = stop_reason_rsp = alloca (strlen ("terror:") + hexstr_len + 1);
       strcpy (p, "terror:");
       p += strlen (p);
-      convert_int_to_ascii ((gdb_byte *) result_name, p, strlen (result_name));
+      bin2hex ((gdb_byte *) result_name, p, strlen (result_name));
+    }
+
+  /* If this was a forced stop, include any stop note that was supplied.  */
+  if (strcmp (stop_reason_rsp, "tstop") == 0)
+    {
+      stop_reason_rsp = alloca (strlen ("tstop:") + strlen (buf3) + 1);
+      strcpy (stop_reason_rsp, "tstop:");
+      strcat (stop_reason_rsp, buf3);
     }
 
   sprintf (packet,
@@ -3009,19 +3681,52 @@ cmd_qtstatus (char *packet)
           "tframes:%x;tcreated:%x;"
           "tfree:%x;tsize:%s;"
           "circular:%d;"
-          "disconn:%d",
+          "disconn:%d;"
+          "starttime:%s;stoptime:%s;"
+          "username:%s;notes:%s:",
           tracing ? 1 : 0,
           stop_reason_rsp, tracing_stop_tpnum,
           traceframe_count, traceframes_created,
           free_space (), phex_nz (trace_buffer_hi - trace_buffer_lo, 0),
           circular_trace_buffer,
-          disconnected_tracing);
+          disconnected_tracing,
+          phex_nz (tracing_start_time, sizeof (tracing_start_time)),
+          phex_nz (tracing_stop_time, sizeof (tracing_stop_time)),
+          buf1, buf2);
+}
+
+static void
+cmd_qtp (char *own_buf)
+{
+  ULONGEST num, addr;
+  struct tracepoint *tpoint;
+  char *packet = own_buf;
+
+  packet += strlen ("qTP:");
+
+  packet = unpack_varlen_hex (packet, &num);
+  ++packet; /* skip a colon */
+  packet = unpack_varlen_hex (packet, &addr);
+
+  /* See if we already have this tracepoint.  */
+  tpoint = find_tracepoint (num, addr);
+
+  if (!tpoint)
+    {
+      trace_debug ("Tracepoint error: tracepoint %d at 0x%s not found",
+                  (int) num, paddress (addr));
+      write_enn (own_buf);
+      return;
+    }
+
+  sprintf (own_buf, "V%" PRIu64 ":%" PRIu64 "", tpoint->hit_count,
+          tpoint->traceframe_usage);
 }
 
 /* State variables to help return all the tracepoint bits.  */
 static struct tracepoint *cur_tpoint;
-static int cur_action;
-static int cur_step_action;
+static unsigned int cur_action;
+static unsigned int cur_step_action;
 static struct source_string *cur_source_string;
 static struct trace_state_variable *cur_tsv;
 
@@ -3033,16 +3738,18 @@ response_tracepoint (char *packet, struct tracepoint *tpoint)
 {
   char *buf;
 
-  sprintf (packet, "T%x:%s:%c:%lx:%lx", tpoint->number,
+  sprintf (packet, "T%x:%s:%c:%" PRIx64 ":%" PRIx64, tpoint->number,
           paddress (tpoint->address),
           (tpoint->enabled ? 'E' : 'D'), tpoint->step_count,
           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)
     {
-      buf = unparse_agent_expr (tpoint->cond);
+      buf = gdb_unparse_agent_expr (tpoint->cond);
       sprintf (packet + strlen (packet), ":X%x,%s",
               tpoint->cond->length, buf);
       free (buf);
@@ -3076,7 +3783,7 @@ response_source (char *packet,
 
   len = strlen (src->str);
   buf = alloca (len * 2 + 1);
-  convert_int_to_ascii ((gdb_byte *) src->str, buf, len);
+  bin2hex ((gdb_byte *) src->str, buf, len);
 
   sprintf (packet, "Z%x:%s:%s:%x:%x:%s",
           tpoint->number, paddress (tpoint->address),
@@ -3093,7 +3800,7 @@ cmd_qtfp (char *packet)
   trace_debug ("Returning first tracepoint definition piece");
 
   cur_tpoint = tracepoints;
-  cur_action = cur_step_action = -1;
+  cur_action = cur_step_action = 0;
   cur_source_string = NULL;
 
   if (cur_tpoint)
@@ -3118,17 +3825,17 @@ cmd_qtsp (char *packet)
         GDB misbehavior.  */
       strcpy (packet, "l");
     }
-  else if (cur_action < cur_tpoint->numactions - 1)
+  else if (cur_action < cur_tpoint->numactions)
     {
-      ++cur_action;
       response_action (packet, cur_tpoint,
                       cur_tpoint->actions_str[cur_action], 0);
+      ++cur_action;
     }
-  else if (cur_step_action < cur_tpoint->num_step_actions - 1)
+  else if (cur_step_action < cur_tpoint->num_step_actions)
     {
-      ++cur_step_action;
       response_action (packet, cur_tpoint,
                       cur_tpoint->step_actions_str[cur_step_action], 1);
+      ++cur_step_action;
     }
   else if ((cur_source_string
            ? cur_source_string->next
@@ -3143,7 +3850,7 @@ cmd_qtsp (char *packet)
   else
     {
       cur_tpoint = cur_tpoint->next;
-      cur_action = cur_step_action = -1;
+      cur_action = cur_step_action = 0;
       cur_source_string = NULL;
       if (cur_tpoint)
        response_tracepoint (packet, cur_tpoint);
@@ -3165,7 +3872,7 @@ response_tsv (char *packet, struct trace_state_variable *tsv)
     {
       namelen = strlen (tsv->name);
       buf = alloca (namelen * 2 + 1);
-      convert_int_to_ascii ((gdb_byte *) tsv->name, buf, namelen);
+      bin2hex ((gdb_byte *) tsv->name, buf, namelen);
     }
 
   sprintf (packet, "%x:%s:%x:%s", tsv->number, phex_nz (tsv->initial_value, 0),
@@ -3193,15 +3900,9 @@ cmd_qtfv (char *packet)
 static void
 cmd_qtsv (char *packet)
 {
-  trace_debug ("Returning first trace state variable definition");
+  trace_debug ("Returning additional trace state variable definition");
 
-  if (!cur_tpoint)
-    {
-      /* This case would normally never occur, but be prepared for
-        GDB misbehavior.  */
-      strcpy (packet, "l");
-    }
-  else if (cur_tsv)
+  if (cur_tsv)
     {
       cur_tsv = cur_tsv->next;
       if (cur_tsv)
@@ -3213,6 +3914,88 @@ 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, strlen (packet) + 1);
+}
+
+/* Return additional static tracepoints markers.  */
+
+static void
+cmd_qtsstm (char *packet)
+{
+  if (!maybe_write_ipa_ust_not_loaded (packet))
+    run_inferior_command (packet, strlen (packet) + 1);
+}
+
+/* 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, strlen (packet) + 1);
+}
+
+/* Helper for gdb_agent_about_to_close.
+   Return non-zero if thread ENTRY is in the same process in DATA.  */
+
+static int
+same_process_p (struct inferior_list_entry *entry, void *data)
+{
+  int *pid = data;
+
+  return ptid_get_pid (entry->id) == *pid;
+}
+
+/* Sent the agent a command to close it.  */
+
+void
+gdb_agent_about_to_close (int pid)
+{
+  char buf[IPA_CMD_BUF_SIZE];
+
+  if (!maybe_write_ipa_not_loaded (buf))
+    {
+      struct thread_info *saved_thread;
+
+      saved_thread = current_thread;
+
+      /* Find any thread which belongs to process PID.  */
+      current_thread = (struct thread_info *)
+       find_inferior (&all_threads, same_process_p, &pid);
+
+      strcpy (buf, "close");
+
+      run_inferior_command (buf, strlen (buf) + 1);
+
+      current_thread = saved_thread;
+    }
+}
+
+/* Return the minimum instruction size needed for fast tracepoints as a
+   hexadecimal number.  */
+
+static void
+cmd_qtminftpilen (char *packet)
+{
+  if (current_thread == NULL)
+    {
+      /* Indicate that the minimum length is currently unknown.  */
+      strcpy (packet, "0");
+      return;
+    }
+
+  sprintf (packet, "%x", target_get_min_fast_tracepoint_insn_len ());
+}
+
 /* 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.  */
@@ -3228,10 +4011,10 @@ cmd_qtbuffer (char *own_buf)
 
   packet = unpack_varlen_hex (packet, &offset);
   ++packet; /* skip a comma */
-  packet = unpack_varlen_hex (packet, &num);
+  unpack_varlen_hex (packet, &num);
 
   trace_debug ("Want to get trace buffer, %d bytes at offset 0x%s",
-              (int) num, pulongest (offset));
+              (int) num, phex_nz (offset, 0));
 
   tot = (trace_buffer_hi - trace_buffer_lo) - free_space ();
 
@@ -3263,29 +4046,113 @@ cmd_qtbuffer (char *own_buf)
   if (num >= (PBUFSIZ - 16) / 2 )
     num = (PBUFSIZ - 16) / 2;
 
-  convert_int_to_ascii (tbp, own_buf, num);
-  own_buf[num] = '\0';
+  bin2hex (tbp, own_buf, num);
 }
 
 static void
-cmd_bigqtbuffer (char *own_buf)
+cmd_bigqtbuffer_circular (char *own_buf)
 {
   ULONGEST val;
   char *packet = own_buf;
 
-  packet += strlen ("QTBuffer:");
+  packet += strlen ("QTBuffer:circular:");
+
+  unpack_varlen_hex (packet, &val);
+  circular_trace_buffer = val;
+  trace_debug ("Trace buffer is now %s",
+              circular_trace_buffer ? "circular" : "linear");
+  write_ok (own_buf);
+}
+
+static void
+cmd_bigqtbuffer_size (char *own_buf)
+{
+  ULONGEST val;
+  LONGEST sval;
+  char *packet = own_buf;
 
-  if (strncmp ("circular:", packet, strlen ("circular:")) == 0)
+  /* Can't change the size during a tracing run.  */
+  if (tracing)
     {
-      packet += strlen ("circular:");
-      packet = unpack_varlen_hex (packet, &val);
-      circular_trace_buffer = val;
-      trace_debug ("Trace buffer is now %s",
-                  circular_trace_buffer ? "circular" : "linear");
-      write_ok (own_buf);
+      write_enn (own_buf);
+      return;
     }
+
+  packet += strlen ("QTBuffer:size:");
+
+  /* -1 is sent as literal "-1".  */
+  if (strcmp (packet, "-1") == 0)
+    sval = DEFAULT_TRACE_BUFFER_SIZE;
   else
-    write_enn (own_buf);
+    {
+      unpack_varlen_hex (packet, &val);
+      sval = (LONGEST) val;
+    }
+
+  init_trace_buffer (sval);
+  trace_debug ("Trace buffer is now %s bytes",
+              plongest (trace_buffer_size));
+  write_ok (own_buf);
+}
+
+static void
+cmd_qtnotes (char *own_buf)
+{
+  size_t nbytes;
+  char *saved, *user, *notes, *stopnote;
+  char *packet = own_buf;
+
+  packet += strlen ("QTNotes:");
+
+  while (*packet)
+    {
+      if (startswith (packet, "user:"))
+       {
+         packet += strlen ("user:");
+         saved = packet;
+         packet = strchr (packet, ';');
+         nbytes = (packet - saved) / 2;
+         user = xmalloc (nbytes + 1);
+         nbytes = hex2bin (saved, (gdb_byte *) user, nbytes);
+         user[nbytes] = '\0';
+         ++packet; /* skip the semicolon */
+         trace_debug ("User is '%s'", user);
+         xfree (tracing_user_name);
+         tracing_user_name = user;
+       }
+      else if (startswith (packet, "notes:"))
+       {
+         packet += strlen ("notes:");
+         saved = packet;
+         packet = strchr (packet, ';');
+         nbytes = (packet - saved) / 2;
+         notes = xmalloc (nbytes + 1);
+         nbytes = hex2bin (saved, (gdb_byte *) notes, nbytes);
+         notes[nbytes] = '\0';
+         ++packet; /* skip the semicolon */
+         trace_debug ("Notes is '%s'", notes);
+         xfree (tracing_notes);
+         tracing_notes = notes;
+       }
+      else if (startswith (packet, "tstop:"))
+       {
+         packet += strlen ("tstop:");
+         saved = packet;
+         packet = strchr (packet, ';');
+         nbytes = (packet - saved) / 2;
+         stopnote = xmalloc (nbytes + 1);
+         nbytes = hex2bin (saved, (gdb_byte *) stopnote, nbytes);
+         stopnote[nbytes] = '\0';
+         ++packet; /* skip the semicolon */
+         trace_debug ("tstop note is '%s'", stopnote);
+         xfree (tracing_stop_note);
+         tracing_stop_note = stopnote;
+       }
+      else
+       break;
+    }
+
+  write_ok (own_buf);
 }
 
 int
@@ -3296,22 +4163,32 @@ handle_tracepoint_general_set (char *packet)
       cmd_qtinit (packet);
       return 1;
     }
-  else if (strncmp ("QTDP:", packet, strlen ("QTDP:")) == 0)
+  else if (startswith (packet, "QTDP:"))
     {
       cmd_qtdp (packet);
       return 1;
     }
-  else if (strncmp ("QTDPsrc:", packet, strlen ("QTDPsrc:")) == 0)
+  else if (startswith (packet, "QTDPsrc:"))
     {
       cmd_qtdpsrc (packet);
       return 1;
     }
-  else if (strncmp ("QTDV:", packet, strlen ("QTDV:")) == 0)
+  else if (startswith (packet, "QTEnable:"))
+    {
+      cmd_qtenable_disable (packet, 1);
+      return 1;
+    }
+  else if (startswith (packet, "QTDisable:"))
+    {
+      cmd_qtenable_disable (packet, 0);
+      return 1;
+    }
+  else if (startswith (packet, "QTDV:"))
     {
       cmd_qtdv (packet);
       return 1;
     }
-  else if (strncmp ("QTro:", packet, strlen ("QTro:")) == 0)
+  else if (startswith (packet, "QTro:"))
     {
       cmd_qtro (packet);
       return 1;
@@ -3326,20 +4203,29 @@ handle_tracepoint_general_set (char *packet)
       cmd_qtstop (packet);
       return 1;
     }
-  else if (strncmp ("QTDisconnected:", packet,
-                   strlen ("QTDisconnected:")) == 0)
+  else if (startswith (packet, "QTDisconnected:"))
     {
       cmd_qtdisconnected (packet);
       return 1;
     }
-  else if (strncmp ("QTFrame:", packet, strlen ("QTFrame:")) == 0)
+  else if (startswith (packet, "QTFrame:"))
     {
       cmd_qtframe (packet);
       return 1;
     }
-  else if (strncmp ("QTBuffer:", packet, strlen ("QTBuffer:")) == 0)
+  else if (startswith (packet, "QTBuffer:circular:"))
+    {
+      cmd_bigqtbuffer_circular (packet);
+      return 1;
+    }
+  else if (startswith (packet, "QTBuffer:size:"))
+    {
+      cmd_bigqtbuffer_size (packet);
+      return 1;
+    }
+  else if (startswith (packet, "QTNotes:"))
     {
-      cmd_bigqtbuffer (packet);
+      cmd_qtnotes (packet);
       return 1;
     }
 
@@ -3354,6 +4240,11 @@ handle_tracepoint_query (char *packet)
       cmd_qtstatus (packet);
       return 1;
     }
+  else if (startswith (packet, "qTP:"))
+    {
+      cmd_qtp (packet);
+      return 1;
+    }
   else if (strcmp ("qTfP", packet) == 0)
     {
       cmd_qtfp (packet);
@@ -3374,16 +4265,36 @@ handle_tracepoint_query (char *packet)
       cmd_qtsv (packet);
       return 1;
     }
-  else if (strncmp ("qTV:", packet, strlen ("qTV:")) == 0)
+  else if (startswith (packet, "qTV:"))
     {
       cmd_qtv (packet);
       return 1;
     }
-  else if (strncmp ("qTBuffer:", packet, strlen ("qTBuffer:")) == 0)
+  else if (startswith (packet, "qTBuffer:"))
     {
       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 (startswith (packet, "qTSTMat:"))
+    {
+      cmd_qtstmat (packet);
+      return 1;
+    }
+  else if (strcmp ("qTMinFTPILen", packet) == 0)
+    {
+      cmd_qtminftpilen (packet);
+      return 1;
+    }
 
   return 0;
 }
@@ -3465,7 +4376,7 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc)
 
   /* Pull in fast tracepoint trace frames from the inferior lib buffer into
      our buffer.  */
-  if (in_process_agent_loaded ())
+  if (agent_loaded_p ())
     upload_fast_traceframes ();
 
   /* Check if we were indeed collecting data for one of more
@@ -3506,6 +4417,7 @@ tracepoint_finished_step (struct thread_info *tinfo, CORE_ADDR stop_pc)
          /* Unlink.  */
          *wstep_link = wstep->next;
          release_while_stepping_state (wstep);
+         wstep = *wstep_link;
          continue;
        }
 
@@ -3565,7 +4477,7 @@ handle_tracepoint_bkpts (struct thread_info *tinfo, CORE_ADDR stop_pc)
   /* Pull in fast tracepoint trace frames from the inferior in-process
      agent's buffer into our buffer.  */
 
-  if (!in_process_agent_loaded ())
+  if (!agent_loaded_p ())
     return 0;
 
   upload_fast_traceframes ();
@@ -3659,8 +4571,12 @@ tracepoint_was_hit (struct thread_info *tinfo, CORE_ADDR stop_pc)
     {
       /* Note that we collect fast tracepoints here as well.  We'll
         step over the fast tracepoint jump later, which avoids the
-        double collect.  */
-      if (tpoint->enabled && stop_pc == tpoint->address)
+        double collect.  However, we don't collect for static
+        tracepoints here, because UST markers are compiled in program,
+        and probes will be executed in program.  So static tracepoints
+        are collected there.   */
+      if (tpoint->enabled && stop_pc == tpoint->address
+         && tpoint->type != static_tracepoint)
        {
          trace_debug ("Thread %s at address of tracepoint %d at 0x%s",
                       target_pid_to_str (tinfo->entry.id),
@@ -3697,6 +4613,12 @@ tracepoint_was_hit (struct thread_info *tinfo, CORE_ADDR stop_pc)
 
 #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,
+                                           struct traceframe *tframe);
+#endif
+
 /* Create a trace frame for the hit of the given tracepoint in the
    given thread.  */
 
@@ -3720,7 +4642,7 @@ collect_data_at_tracepoint (struct tracepoint_hit_ctx *ctx, CORE_ADDR stop_pc,
       && stopping_tracepoint == NULL)
     stopping_tracepoint = tpoint;
 
-  trace_debug ("Making new traceframe for tracepoint %d at 0x%s, hit %ld",
+  trace_debug ("Making new traceframe for tracepoint %d at 0x%s, hit %" PRIu64,
               tpoint->number, paddress (tpoint->address), tpoint->hit_count);
 
   tframe = add_traceframe (tpoint);
@@ -3757,7 +4679,7 @@ collect_data_at_step (struct tracepoint_hit_ctx *ctx,
   int acti;
 
   trace_debug ("Making new step traceframe for "
-              "tracepoint %d at 0x%s, step %d of %ld, hit %ld",
+              "tracepoint %d at 0x%s, step %d of %" PRIu64 ", hit %" PRIu64,
               tpoint->number, paddress (tpoint->address),
               current_step, tpoint->step_count,
               tpoint->hit_count);
@@ -3785,6 +4707,14 @@ collect_data_at_step (struct tracepoint_hit_ctx *ctx,
 
 #endif
 
+#ifdef IN_PROCESS_AGENT
+/* The target description used by the IPA.  Given that the IPA library
+   is built for a specific architecture that is loaded into the
+   inferior, there only needs to be one such description per
+   build.  */
+const struct target_desc *ipa_tdesc;
+#endif
+
 static struct regcache *
 get_context_regcache (struct tracepoint_hit_ctx *ctx)
 {
@@ -3797,12 +4727,33 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx)
       if (!fctx->regcache_initted)
        {
          fctx->regcache_initted = 1;
-         init_register_cache (&fctx->regcache, fctx->regspace);
+         init_register_cache (&fctx->regcache, ipa_tdesc, fctx->regspace);
          supply_regblock (&fctx->regcache, NULL);
          supply_fast_tracepoint_registers (&fctx->regcache, fctx->regs);
        }
       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, ipa_tdesc, 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)
     {
@@ -3830,32 +4781,35 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
     case 'M':
       {
        struct collect_memory_action *maction;
+       struct eval_agent_expr_context ax_ctx;
 
        maction = (struct collect_memory_action *) taction;
+       ax_ctx.regcache = NULL;
+       ax_ctx.tframe = tframe;
+       ax_ctx.tpoint = tpoint;
 
        trace_debug ("Want to collect %s bytes at 0x%s (basereg %d)",
                     pulongest (maction->len),
                     paddress (maction->addr), maction->basereg);
        /* (should use basereg) */
-       agent_mem_read (tframe, NULL,
-                       (CORE_ADDR) maction->addr, maction->len);
+       agent_mem_read (&ax_ctx, NULL, (CORE_ADDR) maction->addr,
+                       maction->len);
        break;
       }
     case 'R':
       {
-       struct collect_registers_action *raction;
-
        unsigned char *regspace;
        struct regcache tregcache;
        struct regcache *context_regcache;
-
-       raction = (struct collect_registers_action *) taction;
+       int regcache_size;
 
        trace_debug ("Want to collect registers");
 
+       context_regcache = get_context_regcache (ctx);
+       regcache_size = register_cache_size (context_regcache->tdesc);
+
        /* Collect all registers for now.  */
-       regspace = add_traceframe_block (tframe,
-                                        1 + register_cache_size ());
+       regspace = add_traceframe_block (tframe, tpoint, 1 + regcache_size);
        if (regspace == NULL)
          {
            trace_debug ("Trace buffer block allocation failed, skipping");
@@ -3864,11 +4818,10 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
        /* Identify a register block.  */
        *regspace = 'R';
 
-       context_regcache = get_context_regcache (ctx);
-
        /* Wrap the regblock in a register cache (in the stack, we
           don't want to malloc here).  */
-       init_register_cache (&tregcache, regspace + 1);
+       init_register_cache (&tregcache, context_regcache->tdesc,
+                            regspace + 1);
 
        /* Copy the register data to the regblock.  */
        regcache_cpy (&tregcache, context_regcache);
@@ -3885,7 +4838,7 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
           preemptively), since the PC had already been adjusted to
           contain the tracepoint's address by the jump pad.  */
        trace_debug ("Storing stop pc (0x%s) in regblock",
-                    paddress (tpoint->address));
+                    paddress (stop_pc));
 
        /* This changes the regblock, not the thread's
           regcache.  */
@@ -3896,12 +4849,16 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
     case 'X':
       {
        struct eval_expr_action *eaction;
+       struct eval_agent_expr_context ax_ctx;
 
        eaction = (struct eval_expr_action *) taction;
+       ax_ctx.regcache = get_context_regcache (ctx);
+       ax_ctx.tframe = tframe;
+       ax_ctx.tpoint = tpoint;
 
        trace_debug ("Want to evaluate expression");
 
-       err = eval_agent_expr (ctx, tframe, eaction->expr, NULL);
+       err = gdb_eval_agent_expr (&ax_ctx, eaction->expr, NULL);
 
        if (err != expr_eval_no_error)
          {
@@ -3910,6 +4867,17 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
          }
       }
       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, 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;
@@ -3923,11 +4891,34 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
   ULONGEST value = 0;
   enum eval_result_type err;
 
+  /* Presently, gdbserver doesn't run compiled conditions, only the
+     IPA does.  If the program stops at a fast tracepoint's address
+     (e.g., due to a breakpoint, trap tracepoint, or stepping),
+     gdbserver preemptively collect the fast tracepoint.  Later, on
+     resume, gdbserver steps over the fast tracepoint like it steps
+     over breakpoints, so that the IPA doesn't see that fast
+     tracepoint.  This avoids double collects of fast tracepoints in
+     that stopping scenario.  Having gdbserver itself handle the fast
+     tracepoint gives the user a consistent view of when fast or trap
+     tracepoints are collected, compared to an alternative where only
+     trap tracepoints are collected on stop, and fast tracepoints on
+     resume.  When a fast tracepoint is being processed by gdbserver,
+     it is always the non-compiled condition expression that is
+     used.  */
+#ifdef IN_PROCESS_AGENT
   if (tpoint->compiled_cond)
     err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
   else
-    err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
+#endif
+    {
+      struct eval_agent_expr_context ax_ctx;
 
+      ax_ctx.regcache = get_context_regcache (ctx);
+      ax_ctx.tframe = NULL;
+      ax_ctx.tpoint = tpoint;
+
+      err = gdb_eval_agent_expr (&ax_ctx, tpoint->cond, &value);
+    }
   if (err != expr_eval_no_error)
     {
       record_tracepoint_error (tpoint, "condition", err);
@@ -3941,497 +4932,163 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
   return (value ? 1 : 0);
 }
 
-#ifndef IN_PROCESS_AGENT
-
-/* The packet form of an agent expression consists of an 'X', number
-   of bytes in expression, a comma, and then the bytes.  */
+/* Do memory copies for bytecodes.  */
+/* Do the recording of memory blocks for actions and bytecodes.  */
 
-static struct agent_expr *
-parse_agent_expr (char **actparm)
+int
+agent_mem_read (struct eval_agent_expr_context *ctx,
+               unsigned char *to, CORE_ADDR from, ULONGEST len)
 {
-  char *act = *actparm;
-  ULONGEST xlen;
-  struct agent_expr *aexpr;
-
-  ++act;  /* skip the X */
-  act = unpack_varlen_hex (act, &xlen);
-  ++act;  /* skip a comma */
-  aexpr = xmalloc (sizeof (struct agent_expr));
-  aexpr->length = xlen;
-  aexpr->bytes = xmalloc (xlen);
-  convert_ascii_to_int (act, aexpr->bytes, xlen);
-  *actparm = act + (xlen * 2);
-  return aexpr;
-}
+  unsigned char *mspace;
+  ULONGEST remaining = len;
+  unsigned short blocklen;
 
-/* Convert the bytes of an agent expression back into hex digits, so
-   they can be printed or uploaded.  This allocates the buffer,
-   callers should free when they are done with it.  */
+  /* If a 'to' buffer is specified, use it.  */
+  if (to != NULL)
+    {
+      read_inferior_memory (from, to, len);
+      return 0;
+    }
 
-static char *
-unparse_agent_expr (struct agent_expr *aexpr)
-{
-  char *rslt;
+  /* Otherwise, create a new memory block in the trace buffer.  */
+  while (remaining > 0)
+    {
+      size_t sp;
 
-  rslt = xmalloc (2 * aexpr->length + 1);
-  convert_int_to_ascii (aexpr->bytes, rslt, aexpr->length);
-  return rslt;
+      blocklen = (remaining > 65535 ? 65535 : remaining);
+      sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen;
+      mspace = add_traceframe_block (ctx->tframe, ctx->tpoint, sp);
+      if (mspace == NULL)
+       return 1;
+      /* Identify block as a memory block.  */
+      *mspace = 'M';
+      ++mspace;
+      /* Record address and size.  */
+      memcpy (mspace, &from, sizeof (from));
+      mspace += sizeof (from);
+      memcpy (mspace, &blocklen, sizeof (blocklen));
+      mspace += sizeof (blocklen);
+      /* Record the memory block proper.  */
+      read_inferior_memory (from, mspace, blocklen);
+      trace_debug ("%d bytes recorded", blocklen);
+      remaining -= blocklen;
+      from += blocklen;
+    }
+  return 0;
 }
 
-#endif
+int
+agent_mem_read_string (struct eval_agent_expr_context *ctx,
+                      unsigned char *to, CORE_ADDR from, ULONGEST len)
+{
+  unsigned char *buf, *mspace;
+  ULONGEST remaining = len;
+  unsigned short blocklen, i;
 
-/* The agent expression evaluator, as specified by the GDB docs. It
-   returns 0 if everything went OK, and a nonzero error code
-   otherwise.  */
-
-static enum eval_result_type
-eval_agent_expr (struct tracepoint_hit_ctx *ctx,
-                struct traceframe *tframe,
-                struct agent_expr *aexpr,
-                ULONGEST *rslt)
-{
-  int pc = 0;
-#define STACK_MAX 100
-  ULONGEST stack[STACK_MAX], top;
-  int sp = 0;
-  unsigned char op;
-  int arg;
-
-  /* This union is a convenient way to convert representations.  For
-     now, assume a standard architecture where the hardware integer
-     types have 8, 16, 32, 64 bit types.  A more robust solution would
-     be to import stdint.h from gnulib.  */
-  union
-  {
-    union
-    {
-      unsigned char bytes[1];
-      unsigned char val;
-    } u8;
-    union
-    {
-      unsigned char bytes[2];
-      unsigned short val;
-    } u16;
-    union
-    {
-      unsigned char bytes[4];
-      unsigned int val;
-    } u32;
-    union
+  /* To save a bit of space, block lengths are 16-bit, so break large
+     requests into multiple blocks.  Bordering on overkill for strings,
+     but it could happen that someone specifies a large max length.  */
+  while (remaining > 0)
     {
-      unsigned char bytes[8];
-      ULONGEST val;
-    } u64;
-  } cnv;
+      size_t sp;
 
-  if (aexpr->length == 0)
-    {
-      trace_debug ("empty agent expression");
-      return expr_eval_empty_expression;
+      blocklen = (remaining > 65535 ? 65535 : remaining);
+      /* We want working space to accumulate nonzero bytes, since
+        traceframes must have a predecided size (otherwise it gets
+        harder to wrap correctly for the circular case, etc).  */
+      buf = (unsigned char *) xmalloc (blocklen + 1);
+      for (i = 0; i < blocklen; ++i)
+       {
+         /* Read the string one byte at a time, in case the string is
+            at the end of a valid memory area - we don't want a
+            correctly-terminated string to engender segvio
+            complaints.  */
+         read_inferior_memory (from + i, buf + i, 1);
+
+         if (buf[i] == '\0')
+           {
+             blocklen = i + 1;
+             /* Make sure outer loop stops now too.  */
+             remaining = blocklen;
+             break;
+           }
+       }
+      sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen;
+      mspace = add_traceframe_block (ctx->tframe, ctx->tpoint, sp);
+      if (mspace == NULL)
+       {
+         xfree (buf);
+         return 1;
+       }
+      /* Identify block as a memory block.  */
+      *mspace = 'M';
+      ++mspace;
+      /* Record address and size.  */
+      memcpy ((void *) mspace, (void *) &from, sizeof (from));
+      mspace += sizeof (from);
+      memcpy ((void *) mspace, (void *) &blocklen, sizeof (blocklen));
+      mspace += sizeof (blocklen);
+      /* Copy the string contents.  */
+      memcpy ((void *) mspace, (void *) buf, blocklen);
+      remaining -= blocklen;
+      from += blocklen;
+      xfree (buf);
     }
+  return 0;
+}
 
-  /* Cache the stack top in its own variable. Much of the time we can
-     operate on this variable, rather than dinking with the stack. It
-     needs to be copied to the stack when sp changes.  */
-  top = 0;
+/* Record the value of a trace state variable.  */
 
-  while (1)
-    {
-      op = aexpr->bytes[pc++];
+int
+agent_tsv_read (struct eval_agent_expr_context *ctx, int n)
+{
+  unsigned char *vspace;
+  LONGEST val;
 
-      trace_debug ("About to interpret byte 0x%x", op);
+  vspace = add_traceframe_block (ctx->tframe, ctx->tpoint,
+                                1 + sizeof (n) + sizeof (LONGEST));
+  if (vspace == NULL)
+    return 1;
+  /* Identify block as a variable.  */
+  *vspace = 'V';
+  /* Record variable's number and value.  */
+  memcpy (vspace + 1, &n, sizeof (n));
+  val = get_trace_state_variable_value (n);
+  memcpy (vspace + 1 + sizeof (n), &val, sizeof (val));
+  trace_debug ("Variable %d recorded", n);
+  return 0;
+}
 
-      switch (op)
-       {
-       case gdb_agent_op_add:
-         top += stack[--sp];
-         break;
+#ifndef IN_PROCESS_AGENT
 
-       case gdb_agent_op_sub:
-         top = stack[--sp] - top;
-         break;
+/* Callback for traceframe_walk_blocks, used to find a given block
+   type in a traceframe.  */
 
-       case gdb_agent_op_mul:
-         top *= stack[--sp];
-         break;
+static int
+match_blocktype (char blocktype, unsigned char *dataptr, void *data)
+{
+  char *wantedp = data;
 
-       case gdb_agent_op_div_signed:
-         if (top == 0)
-           {
-             trace_debug ("Attempted to divide by zero");
-             return expr_eval_divide_by_zero;
-           }
-         top = ((LONGEST) stack[--sp]) / ((LONGEST) top);
-         break;
+  if (*wantedp == blocktype)
+    return 1;
 
-       case gdb_agent_op_div_unsigned:
-         if (top == 0)
-           {
-             trace_debug ("Attempted to divide by zero");
-             return expr_eval_divide_by_zero;
-           }
-         top = stack[--sp] / top;
-         break;
-
-       case gdb_agent_op_rem_signed:
-         if (top == 0)
-           {
-             trace_debug ("Attempted to divide by zero");
-             return expr_eval_divide_by_zero;
-           }
-         top = ((LONGEST) stack[--sp]) % ((LONGEST) top);
-         break;
-
-       case gdb_agent_op_rem_unsigned:
-         if (top == 0)
-           {
-             trace_debug ("Attempted to divide by zero");
-             return expr_eval_divide_by_zero;
-           }
-         top = stack[--sp] % top;
-         break;
-
-       case gdb_agent_op_lsh:
-         top = stack[--sp] << top;
-         break;
-
-       case gdb_agent_op_rsh_signed:
-         top = ((LONGEST) stack[--sp]) >> top;
-         break;
-
-       case gdb_agent_op_rsh_unsigned:
-         top = stack[--sp] >> top;
-         break;
-
-       case gdb_agent_op_trace:
-         agent_mem_read (tframe,
-                         NULL, (CORE_ADDR) stack[--sp], (ULONGEST) top);
-         if (--sp >= 0)
-           top = stack[sp];
-         break;
-
-       case gdb_agent_op_trace_quick:
-         arg = aexpr->bytes[pc++];
-         agent_mem_read (tframe, NULL, (CORE_ADDR) top, (ULONGEST) arg);
-         break;
-
-       case gdb_agent_op_log_not:
-         top = !top;
-         break;
-
-       case gdb_agent_op_bit_and:
-         top &= stack[--sp];
-         break;
-
-       case gdb_agent_op_bit_or:
-         top |= stack[--sp];
-         break;
-
-       case gdb_agent_op_bit_xor:
-         top ^= stack[--sp];
-         break;
-
-       case gdb_agent_op_bit_not:
-         top = ~top;
-         break;
-
-       case gdb_agent_op_equal:
-         top = (stack[--sp] == top);
-         break;
-
-       case gdb_agent_op_less_signed:
-         top = (((LONGEST) stack[--sp]) < ((LONGEST) top));
-         break;
-
-       case gdb_agent_op_less_unsigned:
-         top = (stack[--sp] < top);
-         break;
-
-       case gdb_agent_op_ext:
-         arg = aexpr->bytes[pc++];
-         if (arg < (sizeof (LONGEST) * 8))
-           {
-             LONGEST mask = 1 << (arg - 1);
-             top &= ((LONGEST) 1 << arg) - 1;
-             top = (top ^ mask) - mask;
-           }
-         break;
-
-       case gdb_agent_op_ref8:
-         agent_mem_read (tframe, cnv.u8.bytes, (CORE_ADDR) top, 1);
-         top = cnv.u8.val;
-         break;
-
-       case gdb_agent_op_ref16:
-         agent_mem_read (tframe, cnv.u16.bytes, (CORE_ADDR) top, 2);
-         top = cnv.u16.val;
-         break;
-
-       case gdb_agent_op_ref32:
-         agent_mem_read (tframe, cnv.u32.bytes, (CORE_ADDR) top, 4);
-         top = cnv.u32.val;
-         break;
-
-       case gdb_agent_op_ref64:
-         agent_mem_read (tframe, cnv.u64.bytes, (CORE_ADDR) top, 8);
-         top = cnv.u64.val;
-         break;
-
-       case gdb_agent_op_if_goto:
-         if (top)
-           pc = (aexpr->bytes[pc] << 8) + (aexpr->bytes[pc + 1]);
-         else
-           pc += 2;
-         if (--sp >= 0)
-           top = stack[sp];
-         break;
-
-       case gdb_agent_op_goto:
-         pc = (aexpr->bytes[pc] << 8) + (aexpr->bytes[pc + 1]);
-         break;
-
-       case gdb_agent_op_const8:
-         /* Flush the cached stack top.  */
-         stack[sp++] = top;
-         top = aexpr->bytes[pc++];
-         break;
-
-       case gdb_agent_op_const16:
-         /* Flush the cached stack top.  */
-         stack[sp++] = top;
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         break;
-
-       case gdb_agent_op_const32:
-         /* Flush the cached stack top.  */
-         stack[sp++] = top;
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         break;
-
-       case gdb_agent_op_const64:
-         /* Flush the cached stack top.  */
-         stack[sp++] = top;
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         break;
-
-       case gdb_agent_op_reg:
-         /* Flush the cached stack top.  */
-         stack[sp++] = top;
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         {
-           int regnum = arg;
-           struct regcache *regcache;
-
-           regcache = get_context_regcache (ctx);
-
-           switch (register_size (regnum))
-             {
-             case 8:
-               collect_register (regcache, regnum, cnv.u64.bytes);
-               top = cnv.u64.val;
-               break;
-             case 4:
-               collect_register (regcache, regnum, cnv.u32.bytes);
-               top = cnv.u32.val;
-               break;
-             case 2:
-               collect_register (regcache, regnum, cnv.u16.bytes);
-               top = cnv.u16.val;
-               break;
-             case 1:
-               collect_register (regcache, regnum, cnv.u8.bytes);
-               top = cnv.u8.val;
-               break;
-             default:
-               internal_error (__FILE__, __LINE__,
-                               "unhandled register size");
-             }
-         }
-         break;
-
-       case gdb_agent_op_end:
-         trace_debug ("At end of expression, sp=%d, stack top cache=0x%s",
-                      sp, pulongest (top));
-         if (rslt)
-           {
-             if (sp <= 0)
-               {
-                 /* This should be an error */
-                 trace_debug ("Stack is empty, nothing to return");
-                 return expr_eval_empty_stack;
-               }
-             *rslt = top;
-           }
-         return expr_eval_no_error;
-
-       case gdb_agent_op_dup:
-         stack[sp++] = top;
-         break;
-
-       case gdb_agent_op_pop:
-         if (--sp >= 0)
-           top = stack[sp];
-         break;
-
-       case gdb_agent_op_zero_ext:
-         arg = aexpr->bytes[pc++];
-         if (arg < (sizeof (LONGEST) * 8))
-           top &= ((LONGEST) 1 << arg) - 1;
-         break;
-
-       case gdb_agent_op_swap:
-         /* Interchange top two stack elements, making sure top gets
-            copied back onto stack.  */
-         stack[sp] = top;
-         top = stack[sp - 1];
-         stack[sp - 1] = stack[sp];
-         break;
-
-       case gdb_agent_op_getv:
-         /* Flush the cached stack top.  */
-         stack[sp++] = top;
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         top = get_trace_state_variable_value (arg);
-         break;
-
-       case gdb_agent_op_setv:
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         set_trace_state_variable_value (arg, top);
-         /* Note that we leave the value on the stack, for the
-            benefit of later/enclosing expressions.  */
-         break;
-
-       case gdb_agent_op_tracev:
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         agent_tsv_read (tframe, arg);
-         break;
-
-         /* GDB never (currently) generates any of these ops.  */
-       case gdb_agent_op_float:
-       case gdb_agent_op_ref_float:
-       case gdb_agent_op_ref_double:
-       case gdb_agent_op_ref_long_double:
-       case gdb_agent_op_l_to_d:
-       case gdb_agent_op_d_to_l:
-       case gdb_agent_op_trace16:
-         trace_debug ("Agent expression op 0x%x valid, but not handled",
-                      op);
-         /* If ever GDB generates any of these, we don't have the
-            option of ignoring.  */
-         return 1;
-
-       default:
-         trace_debug ("Agent expression op 0x%x not recognized", op);
-         /* Don't struggle on, things will just get worse.  */
-         return expr_eval_unrecognized_opcode;
-       }
-
-      /* Check for stack badness.  */
-      if (sp >= (STACK_MAX - 1))
-       {
-         trace_debug ("Expression stack overflow");
-         return expr_eval_stack_overflow;
-       }
-
-      if (sp < 0)
-       {
-         trace_debug ("Expression stack underflow");
-         return expr_eval_stack_underflow;
-       }
-
-      trace_debug ("Op %s -> sp=%d, top=0x%s",
-                  gdb_agent_op_names[op], sp, pulongest (top));
-    }
-}
-
-/* Do memory copies for bytecodes.  */
-/* Do the recording of memory blocks for actions and bytecodes.  */
-
-static int
-agent_mem_read (struct traceframe *tframe,
-               unsigned char *to, CORE_ADDR from, ULONGEST len)
-{
-  unsigned char *mspace;
-  ULONGEST remaining = len;
-  unsigned short blocklen;
-
-  /* If a 'to' buffer is specified, use it.  */
-  if (to != NULL)
-    {
-      read_inferior_memory (from, to, len);
-      return 0;
-    }
-
-  /* Otherwise, create a new memory block in the trace buffer.  */
-  while (remaining > 0)
-    {
-      size_t sp;
-
-      blocklen = (remaining > 65535 ? 65535 : remaining);
-      sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen;
-      mspace = add_traceframe_block (tframe, sp);
-      if (mspace == NULL)
-       return 1;
-      /* Identify block as a memory block.  */
-      *mspace = 'M';
-      ++mspace;
-      /* Record address and size.  */
-      memcpy (mspace, &from, sizeof (from));
-      mspace += sizeof (from);
-      memcpy (mspace, &blocklen, sizeof (blocklen));
-      mspace += sizeof (blocklen);
-      /* Record the memory block proper.  */
-      read_inferior_memory (from, mspace, blocklen);
-      trace_debug ("%d bytes recorded", blocklen);
-      remaining -= blocklen;
-      from += blocklen;
-    }
-  return 0;
-}
-
-/* Record the value of a trace state variable.  */
-
-static int
-agent_tsv_read (struct traceframe *tframe, int n)
-{
-  unsigned char *vspace;
-  LONGEST val;
-
-  vspace = add_traceframe_block (tframe,
-                                1 + sizeof (n) + sizeof (LONGEST));
-  if (vspace == NULL)
-    return 1;
-  /* Identify block as a variable.  */
-  *vspace = 'V';
-  /* Record variable's number and value.  */
-  memcpy (vspace + 1, &n, sizeof (n));
-  val = get_trace_state_variable_value (n);
-  memcpy (vspace + 1 + sizeof (n), &val, sizeof (val));
-  trace_debug ("Variable %d recorded", n);
   return 0;
 }
 
-#ifndef IN_PROCESS_AGENT
+/* Walk over all traceframe blocks of the traceframe buffer starting
+   at DATABASE, of DATASIZE bytes long, and call CALLBACK for each
+   block found, passing in DATA unmodified.  If CALLBACK returns true,
+   this returns a pointer to where the block is found.  Returns NULL
+   if no callback call returned true, indicating that all blocks have
+   been walked.  */
 
 static unsigned char *
-traceframe_find_block_type (unsigned char *database, unsigned int datasize,
-                           int tfnum, char type_wanted)
+traceframe_walk_blocks (unsigned char *database, unsigned int datasize,
+                       int tfnum,
+                       int (*callback) (char blocktype,
+                                        unsigned char *dataptr,
+                                        void *data),
+                       void *data)
 {
   unsigned char *dataptr;
 
@@ -4457,16 +5114,17 @@ traceframe_find_block_type (unsigned char *database, unsigned int datasize,
          datasize = dataptr - database;
          dataptr = database = trace_buffer_lo;
        }
+
       blocktype = *dataptr++;
 
-      if (type_wanted == blocktype)
+      if ((*callback) (blocktype, dataptr, data))
        return dataptr;
 
       switch (blocktype)
        {
        case 'R':
          /* Skip over the registers block.  */
-         dataptr += register_cache_size ();
+         dataptr += current_target_desc ()->registers_size;
          break;
        case 'M':
          /* Skip over the memory block.  */
@@ -4478,6 +5136,11 @@ traceframe_find_block_type (unsigned char *database, unsigned int datasize,
          /* 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);
@@ -4488,6 +5151,18 @@ traceframe_find_block_type (unsigned char *database, unsigned int datasize,
   return NULL;
 }
 
+/* Look for the block of type TYPE_WANTED in the trameframe starting
+   at DATABASE of DATASIZE bytes long.  TFNUM is the traceframe
+   number.  */
+
+static unsigned char *
+traceframe_find_block_type (unsigned char *database, unsigned int datasize,
+                           int tfnum, char type_wanted)
+{
+  return traceframe_walk_blocks (database, datasize, tfnum,
+                                match_blocktype, &type_wanted);
+}
+
 static unsigned char *
 traceframe_find_regblock (struct traceframe *tframe, int tfnum)
 {
@@ -4523,8 +5198,7 @@ fetch_traceframe_registers (int tfnum, struct regcache *regcache, int regnum)
   dataptr = traceframe_find_regblock (tframe, tfnum);
   if (dataptr == NULL)
     {
-      /* We don't like making up numbers, but GDB has all manner of
-        troubles when the target says there are no registers.  */
+      /* Mark registers unavailable.  */
       supply_regblock (regcache, NULL);
 
       /* We can generally guess at a PC, although this will be
@@ -4545,12 +5219,13 @@ traceframe_get_pc (struct traceframe *tframe)
 {
   struct regcache regcache;
   unsigned char *dataptr;
+  const struct target_desc *tdesc = current_target_desc ();
 
   dataptr = traceframe_find_regblock (tframe, -1);
   if (dataptr == NULL)
     return 0;
 
-  init_register_cache (&regcache, dataptr);
+  init_register_cache (&regcache, tdesc, dataptr);
   return regcache_read_pc (&regcache);
 }
 
@@ -4582,7 +5257,8 @@ traceframe_read_mem (int tfnum, CORE_ADDR addr,
 
   /* Iterate through a traceframe's blocks, looking for memory.  */
   while ((dataptr = traceframe_find_block_type (dataptr,
-                                               datasize - (dataptr - database),
+                                               datasize
+                                               - (dataptr - database),
                                                tfnum, 'M')) != NULL)
     {
       memcpy (&maddr, dataptr, sizeof (maddr));
@@ -4592,12 +5268,17 @@ traceframe_read_mem (int tfnum, CORE_ADDR addr,
       trace_debug ("traceframe %d has %d bytes at %s",
                   tfnum, mlen, paddress (maddr));
 
-      /* Check that requested data is in bounds.  */
-      if (maddr <= addr && (addr + length) <= (maddr + mlen))
+      /* If the block includes the first part of the desired range,
+        return as much it has; GDB will re-request the remainder,
+        which might be in a different block of this trace frame.  */
+      if (maddr <= addr && addr < (maddr + mlen))
        {
-         /* Block includes the requested range, copy it out.  */
-         memcpy (buf, dataptr + (addr - maddr), length);
-         *nbytes = length;
+         ULONGEST amt = (maddr + mlen) - addr;
+         if (amt > length)
+           amt = length;
+
+         memcpy (buf, dataptr + (addr - maddr), amt);
+         *nbytes = amt;
          return 0;
        }
 
@@ -4620,6 +5301,7 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)
   unsigned char *database, *dataptr;
   unsigned int datasize;
   int vnum;
+  int found = 0;
 
   trace_debug ("traceframe_read_tsv");
 
@@ -4642,9 +5324,11 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)
   datasize = tframe->data_size;
   database = dataptr = &tframe->data[0];
 
-  /* Iterate through a traceframe's blocks, looking for the tsv.  */
+  /* Iterate through a traceframe's blocks, looking for the last
+     matched tsv.  */
   while ((dataptr = traceframe_find_block_type (dataptr,
-                                               datasize - (dataptr - database),
+                                               datasize
+                                               - (dataptr - database),
                                                tfnum, 'V')) != NULL)
     {
       memcpy (&vnum, dataptr, sizeof (vnum));
@@ -4656,80 +5340,224 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)
       if (tsvnum == vnum)
        {
          memcpy (val, dataptr, sizeof (*val));
-         return 0;
+         found = 1;
        }
 
       /* Skip over this block.  */
       dataptr += sizeof (LONGEST);
     }
 
-  trace_debug ("traceframe %d has no data for variable %d",
-              tfnum, tsvnum);
-  return 1;
+  if (!found)
+    trace_debug ("traceframe %d has no data for variable %d",
+                tfnum, tsvnum);
+  return !found;
 }
 
-/* Return the first fast tracepoint whose jump pad contains PC.  */
+/* Read a requested block of static tracepoint data from a trace
+   frame.  */
 
-static struct tracepoint *
-fast_tracepoint_from_jump_pad_address (CORE_ADDR pc)
+int
+traceframe_read_sdata (int tfnum, ULONGEST offset,
+                      unsigned char *buf, ULONGEST length,
+                      ULONGEST *nbytes)
 {
-  struct tracepoint *tpoint;
-
-  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
-    if (tpoint->type == fast_tracepoint)
-      if (tpoint->jump_pad <= pc && pc < tpoint->jump_pad_end)
-       return tpoint;
-
-  return NULL;
-}
+  struct traceframe *tframe;
+  unsigned char *database, *dataptr;
+  unsigned int datasize;
+  unsigned short mlen;
 
-/* Return GDBserver's tracepoint that matches the IP Agent's
-   tracepoint object that lives at IPA_TPOINT_OBJ in the IP Agent's
-   address space.  */
+  trace_debug ("traceframe_read_sdata");
 
-static struct tracepoint *
-fast_tracepoint_from_ipa_tpoint_address (CORE_ADDR ipa_tpoint_obj)
-{
-  struct tracepoint *tpoint;
+  tframe = find_traceframe (tfnum);
 
-  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
-    if (tpoint->type == fast_tracepoint)
-      if (tpoint->obj_addr_on_target == ipa_tpoint_obj)
-       return tpoint;
+  if (!tframe)
+    {
+      trace_debug ("traceframe %d not found", tfnum);
+      return 1;
+    }
 
-  return NULL;
-}
+  datasize = tframe->data_size;
+  database = &tframe->data[0];
 
-#endif
+  /* 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;
 
-/* The type of the object that is used to synchronize fast tracepoint
-   collection.  */
+         memcpy (buf, dataptr, length);
+         *nbytes = length;
+       }
+      else
+       *nbytes = 0;
+      return 0;
+    }
 
-typedef struct collecting_t
-{
-  /* The fast tracepoint number currently collecting.  */
-  uintptr_t tpoint;
+  trace_debug ("traceframe %d has no static trace data", tfnum);
 
-  /* A number that GDBserver can use to identify the thread that is
-     presently holding the collect lock.  This need not (and usually
-     is not) the thread id, as getting the current thread ID usually
-     requires a system call, which we want to avoid like the plague.
-     Usually this is thread's TCB, found in the TLS (pseudo-)
-     register, which is readable with a single insn on several
-     architectures.  */
-  uintptr_t thread_area;
-} collecting_t;
+  *nbytes = 0;
+  return 0;
+}
 
-#ifndef IN_PROCESS_AGENT
+/* Callback for traceframe_walk_blocks.  Builds a traceframe-info
+   object.  DATA is pointer to a struct buffer holding the
+   traceframe-info object being built.  */
 
-void
-force_unlock_trace_buffer (void)
+static int
+build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data)
 {
-  write_inferior_data_pointer (ipa_sym_addrs.addr_collecting, 0);
-}
+  struct buffer *buffer = data;
 
-/* Check if the thread identified by THREAD_AREA which is stopped at
-   STOP_PC, is presently locking the fast tracepoint collection, and
+  switch (blocktype)
+    {
+    case 'M':
+      {
+       unsigned short mlen;
+       CORE_ADDR maddr;
+
+       memcpy (&maddr, dataptr, sizeof (maddr));
+       dataptr += sizeof (maddr);
+       memcpy (&mlen, dataptr, sizeof (mlen));
+       dataptr += sizeof (mlen);
+       buffer_xml_printf (buffer,
+                          "<memory start=\"0x%s\" length=\"0x%s\"/>\n",
+                          paddress (maddr), phex_nz (mlen, sizeof (mlen)));
+       break;
+      }
+    case 'V':
+      {
+       int vnum;
+
+       memcpy (&vnum, dataptr, sizeof (vnum));
+       buffer_xml_printf (buffer, "<tvar id=\"%d\"/>\n", vnum);
+       break;
+      }
+    case 'R':
+    case 'S':
+      {
+       break;
+      }
+    default:
+      warning ("Unhandled trace block type (%d) '%c ' "
+              "while building trace frame info.",
+              blocktype, blocktype);
+      break;
+    }
+
+  return 0;
+}
+
+/* Build a traceframe-info object for traceframe number TFNUM into
+   BUFFER.  */
+
+int
+traceframe_read_info (int tfnum, struct buffer *buffer)
+{
+  struct traceframe *tframe;
+
+  trace_debug ("traceframe_read_info");
+
+  tframe = find_traceframe (tfnum);
+
+  if (!tframe)
+    {
+      trace_debug ("traceframe %d not found", tfnum);
+      return 1;
+    }
+
+  buffer_grow_str (buffer, "<traceframe-info>\n");
+  traceframe_walk_blocks (tframe->data, tframe->data_size,
+                         tfnum, build_traceframe_info_xml, buffer);
+  buffer_grow_str0 (buffer, "</traceframe-info>\n");
+  return 0;
+}
+
+/* Return the first fast tracepoint whose jump pad contains PC.  */
+
+static struct tracepoint *
+fast_tracepoint_from_jump_pad_address (CORE_ADDR pc)
+{
+  struct tracepoint *tpoint;
+
+  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
+    if (tpoint->type == fast_tracepoint)
+      if (tpoint->jump_pad <= pc && pc < tpoint->jump_pad_end)
+       return tpoint;
+
+  return NULL;
+}
+
+/* Return the first fast tracepoint whose trampoline contains PC.  */
+
+static struct tracepoint *
+fast_tracepoint_from_trampoline_address (CORE_ADDR pc)
+{
+  struct tracepoint *tpoint;
+
+  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
+    {
+      if (tpoint->type == fast_tracepoint
+         && tpoint->trampoline <= pc && pc < tpoint->trampoline_end)
+       return tpoint;
+    }
+
+  return NULL;
+}
+
+/* Return GDBserver's tracepoint that matches the IP Agent's
+   tracepoint object that lives at IPA_TPOINT_OBJ in the IP Agent's
+   address space.  */
+
+static struct tracepoint *
+fast_tracepoint_from_ipa_tpoint_address (CORE_ADDR ipa_tpoint_obj)
+{
+  struct tracepoint *tpoint;
+
+  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
+    if (tpoint->type == fast_tracepoint)
+      if (tpoint->obj_addr_on_target == ipa_tpoint_obj)
+       return tpoint;
+
+  return NULL;
+}
+
+#endif
+
+/* The type of the object that is used to synchronize fast tracepoint
+   collection.  */
+
+typedef struct collecting_t
+{
+  /* The fast tracepoint number currently collecting.  */
+  uintptr_t tpoint;
+
+  /* A number that GDBserver can use to identify the thread that is
+     presently holding the collect lock.  This need not (and usually
+     is not) the thread id, as getting the current thread ID usually
+     requires a system call, which we want to avoid like the plague.
+     Usually this is thread's TCB, found in the TLS (pseudo-)
+     register, which is readable with a single insn on several
+     architectures.  */
+  uintptr_t thread_area;
+} collecting_t;
+
+#ifndef IN_PROCESS_AGENT
+
+void
+force_unlock_trace_buffer (void)
+{
+  write_inferior_data_pointer (ipa_sym_addrs.addr_collecting, 0);
+}
+
+/* Check if the thread identified by THREAD_AREA which is stopped at
+   STOP_PC, is presently locking the fast tracepoint collection, and
    if so, gather some status of said collection.  Returns 0 if the
    thread isn't collecting or in the jump pad at all.  1, if in the
    jump pad (or within gdb_collect) and hasn't executed the adjusted
@@ -4745,6 +5573,8 @@ fast_tracepoint_collecting (CORE_ADDR thread_area,
 {
   CORE_ADDR ipa_collecting;
   CORE_ADDR ipa_gdb_jump_pad_buffer, ipa_gdb_jump_pad_buffer_end;
+  CORE_ADDR ipa_gdb_trampoline_buffer;
+  CORE_ADDR ipa_gdb_trampoline_buffer_end;
   struct tracepoint *tpoint;
   int needs_breakpoint;
 
@@ -4778,12 +5608,32 @@ fast_tracepoint_collecting (CORE_ADDR thread_area,
 
   if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_jump_pad_buffer,
                                  &ipa_gdb_jump_pad_buffer))
-    fatal ("error extracting `gdb_jump_pad_buffer'");
+    {
+      internal_error (__FILE__, __LINE__,
+                     "error extracting `gdb_jump_pad_buffer'");
+    }
   if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_jump_pad_buffer_end,
                                  &ipa_gdb_jump_pad_buffer_end))
-    fatal ("error extracting `gdb_jump_pad_buffer_end'");
+    {
+      internal_error (__FILE__, __LINE__,
+                     "error extracting `gdb_jump_pad_buffer_end'");
+    }
+
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer,
+                                 &ipa_gdb_trampoline_buffer))
+    {
+      internal_error (__FILE__, __LINE__,
+                     "error extracting `gdb_trampoline_buffer'");
+    }
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+                                 &ipa_gdb_trampoline_buffer_end))
+    {
+      internal_error (__FILE__, __LINE__,
+                     "error extracting `gdb_trampoline_buffer_end'");
+    }
 
-  if (ipa_gdb_jump_pad_buffer <= stop_pc && stop_pc < ipa_gdb_jump_pad_buffer_end)
+  if (ipa_gdb_jump_pad_buffer <= stop_pc
+      && stop_pc < ipa_gdb_jump_pad_buffer_end)
     {
       /* We can tell which tracepoint(s) the thread is collecting by
         matching the jump pad address back to the tracepoint.  */
@@ -4810,6 +5660,30 @@ fast_tracepoint_collecting (CORE_ADDR thread_area,
          && stop_pc < tpoint->adjusted_insn_addr)
        needs_breakpoint =  1;
     }
+  else if (ipa_gdb_trampoline_buffer <= stop_pc
+          && stop_pc < ipa_gdb_trampoline_buffer_end)
+    {
+      /* We can tell which tracepoint(s) the thread is collecting by
+        matching the trampoline address back to the tracepoint.  */
+      tpoint = fast_tracepoint_from_trampoline_address (stop_pc);
+      if (tpoint == NULL)
+       {
+         warning ("in trampoline, but no matching tpoint?");
+         return 0;
+       }
+      else
+       {
+         trace_debug ("in trampoline of tpoint (%d, %s); trampoline(%s, %s)",
+                      tpoint->number, paddress (tpoint->address),
+                      paddress (tpoint->trampoline),
+                      paddress (tpoint->trampoline_end));
+       }
+
+      /* Have not reached jump pad yet, but treat the trampoline as a
+        part of the jump pad that is before the adjusted original
+        instruction.  */
+      needs_breakpoint = 1;
+    }
   else
     {
       collecting_t ipa_collecting_obj;
@@ -4904,13 +5778,15 @@ fast_tracepoint_collecting, returning continue-until-break at %s",
    NULL if it isn't locked.  Note that this lock *must* be set while
    executing any *function other than the jump pad.  See
    fast_tracepoint_collecting.  */
-static collecting_t * ATTR_USED collecting;
+EXTERN_C_PUSH
+IP_AGENT_EXPORT_VAR collecting_t *collecting;
+EXTERN_C_POP
 
 /* This routine, called from the jump pad (in asm) is designed to be
    called from the jump pads of fast tracepoints, thus it is on the
    critical path.  */
 
-IP_AGENT_EXPORT void ATTR_USED
+IP_AGENT_EXPORT_FUNC void
 gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
 {
   struct fast_tracepoint_ctx ctx;
@@ -4922,41 +5798,58 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
   ctx.base.type = fast_tracepoint;
   ctx.regs = regs;
   ctx.regcache_initted = 0;
-  ctx.tpoint = tpoint;
-
   /* Wrap the regblock in a register cache (in the stack, we don't
      want to malloc here).  */
-  ctx.regspace = alloca (register_cache_size ());
+  ctx.regspace = alloca (ipa_tdesc->registers_size);
   if (ctx.regspace == NULL)
     {
       trace_debug ("Trace buffer block allocation failed, skipping");
       return;
     }
 
-  /* Test the condition if present, and collect if true.  */
-  if (tpoint->cond == NULL
-      || condition_true_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
-                                      tpoint))
+  for (ctx.tpoint = tpoint;
+       ctx.tpoint != NULL && ctx.tpoint->address == tpoint->address;
+       ctx.tpoint = ctx.tpoint->next)
     {
-      collect_data_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
-                                 tpoint->address, tpoint);
+      if (!ctx.tpoint->enabled)
+       continue;
 
-      /* Note that this will cause original insns to be written back
-        to where we jumped from, but that's OK because we're jumping
-        back to the next whole instruction.  This will go badly if
-        instruction restoration is not atomic though.  */
-      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 ();
+      /* Multiple tracepoints of different types, such as fast tracepoint and
+        static tracepoint, can be set at the same address.  */
+      if (ctx.tpoint->type != tpoint->type)
+       continue;
+
+      /* Test the condition if present, and collect if true.  */
+      if (ctx.tpoint->cond == NULL
+         || condition_true_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
+                                          ctx.tpoint))
+       {
+         collect_data_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
+                                     ctx.tpoint->address, ctx.tpoint);
+
+         /* Note that this will cause original insns to be written back
+            to where we jumped from, but that's OK because we're jumping
+            back to the next whole instruction.  This will go badly if
+            instruction restoration is not atomic though.  */
+         if (stopping_tracepoint
+             || trace_buffer_is_full
+             || expr_eval_result != expr_eval_no_error)
+           {
+             stop_tracing ();
+             break;
+           }
+       }
+      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 ();
+             break;
+           }
+       }
     }
 }
 
@@ -4964,1130 +5857,1482 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
 
 #ifndef IN_PROCESS_AGENT
 
-/* Bytecode compilation.  */
-
-CORE_ADDR current_insn_ptr;
-
-int emit_error;
-
-struct bytecode_address
-{
-  int pc;
-  CORE_ADDR address;
-  int goto_pc;
-  /* Offset and size of field to be modified in the goto block.  */
-  int from_offset, from_size;
-  struct bytecode_address *next;
-} *bytecode_address_table;
-
 CORE_ADDR
 get_raw_reg_func_addr (void)
 {
   return ipa_sym_addrs.addr_get_raw_reg;
 }
 
-static void
-emit_prologue (void)
+CORE_ADDR
+get_get_tsv_func_addr (void)
 {
-  target_emit_ops ()->emit_prologue ();
+  return ipa_sym_addrs.addr_get_trace_state_variable_value;
 }
 
-static void
-emit_epilogue (void)
+CORE_ADDR
+get_set_tsv_func_addr (void)
 {
-  target_emit_ops ()->emit_epilogue ();
+  return ipa_sym_addrs.addr_set_trace_state_variable_value;
 }
 
 static void
-emit_add (void)
+compile_tracepoint_condition (struct tracepoint *tpoint,
+                             CORE_ADDR *jump_entry)
 {
-  target_emit_ops ()->emit_add ();
-}
+  CORE_ADDR entry_point = *jump_entry;
+  enum eval_result_type err;
 
-static void
-emit_sub (void)
-{
-  target_emit_ops ()->emit_sub ();
-}
+  trace_debug ("Starting condition compilation for tracepoint %d\n",
+              tpoint->number);
 
-static void
-emit_mul (void)
-{
-  target_emit_ops ()->emit_mul ();
-}
+  /* Initialize the global pointer to the code being built.  */
+  current_insn_ptr = *jump_entry;
 
-static void
-emit_lsh (void)
-{
-  target_emit_ops ()->emit_lsh ();
-}
+  emit_prologue ();
 
-static void
-emit_rsh_signed (void)
-{
-  target_emit_ops ()->emit_rsh_signed ();
-}
+  err = compile_bytecodes (tpoint->cond);
 
-static void
-emit_rsh_unsigned (void)
-{
-  target_emit_ops ()->emit_rsh_unsigned ();
-}
+  if (err == expr_eval_no_error)
+    {
+      emit_epilogue ();
 
-static void
-emit_ext (int arg)
-{
-  target_emit_ops ()->emit_ext (arg);
-}
+      /* Record the beginning of the compiled code.  */
+      tpoint->compiled_cond = entry_point;
 
-static void
-emit_log_not (void)
-{
-  target_emit_ops ()->emit_log_not ();
-}
+      trace_debug ("Condition compilation for tracepoint %d complete\n",
+                  tpoint->number);
+    }
+  else
+    {
+      /* Leave the unfinished code in situ, but don't point to it.  */
 
-static void
-emit_bit_and (void)
-{
-  target_emit_ops ()->emit_bit_and ();
-}
+      tpoint->compiled_cond = 0;
 
-static void
-emit_bit_or (void)
-{
-  target_emit_ops ()->emit_bit_or ();
-}
+      trace_debug ("Condition compilation for tracepoint %d failed, "
+                  "error code %d",
+                  tpoint->number, err);
+    }
 
-static void
-emit_bit_xor (void)
-{
-  target_emit_ops ()->emit_bit_xor ();
-}
+  /* Update the code pointer passed in.  Note that we do this even if
+     the compile fails, so that we can look at the partial results
+     instead of letting them be overwritten.  */
+  *jump_entry = current_insn_ptr;
 
-static void
-emit_bit_not (void)
-{
-  target_emit_ops ()->emit_bit_not ();
+  /* Leave a gap, to aid dump decipherment.  */
+  *jump_entry += 16;
 }
 
-static void
-emit_equal (void)
+/* We'll need to adjust these when we consider bi-arch setups, and big
+   endian machines.  */
+
+static int
+write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr)
 {
-  target_emit_ops ()->emit_equal ();
+  return write_inferior_memory (where,
+                               (unsigned char *) &ptr, sizeof (void *));
 }
 
-static void
-emit_less_signed (void)
-{
-  target_emit_ops ()->emit_less_signed ();
-}
+/* The base pointer of the IPA's heap.  This is the only memory the
+   IPA is allowed to use.  The IPA should _not_ call the inferior's
+   `malloc' during operation.  That'd be slow, and, most importantly,
+   it may not be safe.  We may be collecting a tracepoint in a signal
+   handler, for example.  */
+static CORE_ADDR target_tp_heap;
 
-static void
-emit_less_unsigned (void)
-{
-  target_emit_ops ()->emit_less_unsigned ();
-}
+/* Allocate at least SIZE bytes of memory from the IPA heap, aligned
+   to 8 bytes.  */
 
-static void
-emit_ref (int size)
+static CORE_ADDR
+target_malloc (ULONGEST size)
 {
-  target_emit_ops ()->emit_ref (size);
-}
+  CORE_ADDR ptr;
 
-static void
-emit_if_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_if_goto (offset_p, size_p);
-}
+  if (target_tp_heap == 0)
+    {
+      /* We have the pointer *address*, need what it points to.  */
+      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_tp_heap_buffer,
+                                     &target_tp_heap))
+       {
+         internal_error (__FILE__, __LINE__,
+                         "couldn't get target heap head pointer");
+       }
+    }
 
-static void
-emit_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_goto (offset_p, size_p);
-}
+  ptr = target_tp_heap;
+  target_tp_heap += size;
 
-static void
-write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
-{
-  target_emit_ops ()->write_goto_address (from, to, size);
-}
+  /* Pad to 8-byte alignment.  */
+  target_tp_heap = ((target_tp_heap + 7) & ~0x7);
 
-static void
-emit_const (int64_t num)
-{
-  target_emit_ops ()->emit_const (num);
+  return ptr;
 }
 
-static void
-emit_reg (int reg)
+static CORE_ADDR
+download_agent_expr (struct agent_expr *expr)
 {
-  target_emit_ops ()->emit_reg (reg);
-}
+  CORE_ADDR expr_addr;
+  CORE_ADDR expr_bytes;
 
-static void
-emit_pop (void)
-{
-  target_emit_ops ()->emit_pop ();
-}
+  expr_addr = target_malloc (sizeof (*expr));
+  write_inferior_memory (expr_addr, (unsigned char *) expr, sizeof (*expr));
 
-static void
-emit_stack_flush (void)
-{
-  target_emit_ops ()->emit_stack_flush ();
-}
+  expr_bytes = target_malloc (expr->length);
+  write_inferior_data_ptr (expr_addr + offsetof (struct agent_expr, bytes),
+                          expr_bytes);
+  write_inferior_memory (expr_bytes, expr->bytes, expr->length);
 
-static void
-emit_zero_ext (int arg)
-{
-  target_emit_ops ()->emit_zero_ext (arg);
+  return expr_addr;
 }
 
-static void
-emit_swap (void)
-{
-  target_emit_ops ()->emit_swap ();
-}
+/* Align V up to N bits.  */
+#define UALIGN(V, N) (((V) + ((N) - 1)) & ~((N) - 1))
+
+/* Sync tracepoint with IPA, but leave maintenance of linked list to caller.  */
 
 static void
-emit_stack_adjust (int n)
+download_tracepoint_1 (struct tracepoint *tpoint)
 {
-  target_emit_ops ()->emit_stack_adjust (n);
-}
+  struct tracepoint target_tracepoint;
+  CORE_ADDR tpptr = 0;
 
-/* FN's prototype is `LONGEST(*fn)(int)'.  */
+  gdb_assert (tpoint->type == fast_tracepoint
+             || tpoint->type == static_tracepoint);
 
-static void
-emit_int_call_1 (CORE_ADDR fn, int arg1)
-{
-  target_emit_ops ()->emit_int_call_1 (fn, arg1);
-}
+  if (tpoint->cond != NULL && target_emit_ops () != NULL)
+    {
+      CORE_ADDR jentry, jump_entry;
 
-/* FN's prototype is `void(*fn)(int,int64_t)'.  */
+      jentry = jump_entry = get_jump_space_head ();
 
-static void
-emit_void_call_2 (CORE_ADDR fn, int arg1)
-{
-  target_emit_ops ()->emit_void_call_2 (fn, arg1);
-}
+      if (tpoint->cond != NULL)
+       {
+         /* Pad to 8-byte alignment. (needed?)  */
+         /* Actually this should be left for the target to
+            decide.  */
+         jentry = UALIGN (jentry, 8);
+
+         compile_tracepoint_condition (tpoint, &jentry);
+       }
 
-static enum eval_result_type compile_bytecodes (struct agent_expr *aexpr);
+      /* Pad to 8-byte alignment.  */
+      jentry = UALIGN (jentry, 8);
+      claim_jump_space (jentry - jump_entry);
+    }
 
-static void
-compile_tracepoint_condition (struct tracepoint *tpoint, CORE_ADDR *jump_entry)
-{
-  CORE_ADDR entry_point = *jump_entry;
-  enum eval_result_type err;
+  target_tracepoint = *tpoint;
 
-  trace_debug ("Starting condition compilation for tracepoint %d\n",
-              tpoint->number);
+  tpptr = target_malloc (sizeof (*tpoint));
+  tpoint->obj_addr_on_target = tpptr;
 
-  /* Initialize the global pointer to the code being built.  */
-  current_insn_ptr = *jump_entry;
+  /* Write the whole object.  We'll fix up its pointers in a bit.
+     Assume no next for now.  This is fixed up above on the next
+     iteration, if there's any.  */
+  target_tracepoint.next = NULL;
+  /* Need to clear this here too, since we're downloading the
+     tracepoints before clearing our own copy.  */
+  target_tracepoint.hit_count = 0;
 
-  emit_prologue ();
+  write_inferior_memory (tpptr, (unsigned char *) &target_tracepoint,
+                        sizeof (target_tracepoint));
 
-  err = compile_bytecodes (tpoint->cond);
+  if (tpoint->cond)
+    write_inferior_data_ptr (tpptr + offsetof (struct tracepoint,
+                                              cond),
+                            download_agent_expr (tpoint->cond));
 
-  if (err == expr_eval_no_error)
+  if (tpoint->numactions)
     {
-      emit_epilogue ();
+      int i;
+      CORE_ADDR actions_array;
 
-      /* Record the beginning of the compiled code.  */
-      tpoint->compiled_cond = entry_point;
+      /* The pointers array.  */
+      actions_array
+       = target_malloc (sizeof (*tpoint->actions) * tpoint->numactions);
+      write_inferior_data_ptr (tpptr + offsetof (struct tracepoint,
+                                                actions),
+                              actions_array);
 
-      trace_debug ("Condition compilation for tracepoint %d complete\n",
-                  tpoint->number);
+      /* Now for each pointer, download the action.  */
+      for (i = 0; i < tpoint->numactions; i++)
+       {
+         struct tracepoint_action *action = tpoint->actions[i];
+         CORE_ADDR ipa_action = action->ops->download (action);
+
+         if (ipa_action != 0)
+           write_inferior_data_ptr
+             (actions_array + i * sizeof (*tpoint->actions),
+              ipa_action);
+       }
     }
-  else
-    {
-      /* Leave the unfinished code in situ, but don't point to it.  */
+}
 
-      tpoint->compiled_cond = 0;
+#define IPA_PROTO_FAST_TRACE_FLAG 0
+#define IPA_PROTO_FAST_TRACE_ADDR_ON_TARGET 2
+#define IPA_PROTO_FAST_TRACE_JUMP_PAD 10
+#define IPA_PROTO_FAST_TRACE_FJUMP_SIZE 18
+#define IPA_PROTO_FAST_TRACE_FJUMP_INSN 22
 
-      trace_debug ("Condition compilation for tracepoint %d failed, "
-                  "error code %d",
-                  tpoint->number, err);
+/* Send a command to agent to download and install tracepoint TPOINT.  */
+
+static int
+tracepoint_send_agent (struct tracepoint *tpoint)
+{
+  char buf[IPA_CMD_BUF_SIZE];
+  char *p;
+  int i, ret;
+
+  p = buf;
+  strcpy (p, "FastTrace:");
+  p += 10;
+
+  COPY_FIELD_TO_BUF (p, tpoint, number);
+  COPY_FIELD_TO_BUF (p, tpoint, address);
+  COPY_FIELD_TO_BUF (p, tpoint, type);
+  COPY_FIELD_TO_BUF (p, tpoint, enabled);
+  COPY_FIELD_TO_BUF (p, tpoint, step_count);
+  COPY_FIELD_TO_BUF (p, tpoint, pass_count);
+  COPY_FIELD_TO_BUF (p, tpoint, numactions);
+  COPY_FIELD_TO_BUF (p, tpoint, hit_count);
+  COPY_FIELD_TO_BUF (p, tpoint, traceframe_usage);
+  COPY_FIELD_TO_BUF (p, tpoint, compiled_cond);
+  COPY_FIELD_TO_BUF (p, tpoint, orig_size);
+
+  /* condition */
+  p = agent_expr_send (p, tpoint->cond);
+
+  /* tracepoint_action */
+  for (i = 0; i < tpoint->numactions; i++)
+    {
+      struct tracepoint_action *action = tpoint->actions[i];
+
+      p[0] = action->type;
+      p = action->ops->send (&p[1], action);
     }
 
-  /* Update the code pointer passed in.  Note that we do this even if
-     the compile fails, so that we can look at the partial results
-     instead of letting them be overwritten.  */
-  *jump_entry = current_insn_ptr;
+  get_jump_space_head ();
+  /* Copy the value of GDB_JUMP_PAD_HEAD to command buffer, so that
+     agent can use jump pad from it.  */
+  if (tpoint->type == fast_tracepoint)
+    {
+      memcpy (p, &gdb_jump_pad_head, 8);
+      p += 8;
+    }
 
-  /* Leave a gap, to aid dump decipherment.  */
-  *jump_entry += 16;
-}
+  ret = run_inferior_command (buf, (int) (ptrdiff_t) (p - buf));
+  if (ret)
+    return ret;
+
+  if (!startswith (buf, "OK"))
+    return 1;
+
+  /* The value of tracepoint's target address is stored in BUF.  */
+  memcpy (&tpoint->obj_addr_on_target,
+         &buf[IPA_PROTO_FAST_TRACE_ADDR_ON_TARGET], 8);
+
+  if (tpoint->type == fast_tracepoint)
+    {
+      unsigned char *insn
+       = (unsigned char *) &buf[IPA_PROTO_FAST_TRACE_FJUMP_INSN];
+      int fjump_size;
 
-/* Given an agent expression, turn it into native code.  */
+     trace_debug ("agent: read from cmd_buf 0x%x 0x%x\n",
+                 (unsigned int) tpoint->obj_addr_on_target,
+                 (unsigned int) gdb_jump_pad_head);
 
-static enum eval_result_type
-compile_bytecodes (struct agent_expr *aexpr)
+      memcpy (&gdb_jump_pad_head, &buf[IPA_PROTO_FAST_TRACE_JUMP_PAD], 8);
+
+      /* This has been done in agent.  We should also set up record for it.  */
+      memcpy (&fjump_size, &buf[IPA_PROTO_FAST_TRACE_FJUMP_SIZE], 4);
+      /* Wire it in.  */
+      tpoint->handle
+       = set_fast_tracepoint_jump (tpoint->address, insn, fjump_size);
+    }
+
+  return 0;
+}
+
+static void
+download_tracepoint (struct tracepoint *tpoint)
 {
-  int pc = 0;
-  int done = 0;
-  unsigned char op;
-  int arg;
-  /* This is only used to build 64-bit value for constants.  */
-  ULONGEST top;
-  struct bytecode_address *aentry, *aentry2;
+  struct tracepoint *tp, *tp_prev;
 
-#define UNHANDLED                                      \
-  do                                                   \
-    {                                                  \
-      trace_debug ("Cannot compile op 0x%x\n", op);    \
-      return expr_eval_unhandled_opcode;               \
-    } while (0)
+  if (tpoint->type != fast_tracepoint
+      && tpoint->type != static_tracepoint)
+    return;
+
+  download_tracepoint_1 (tpoint);
+
+  /* Find the previous entry of TPOINT, which is fast tracepoint or
+     static tracepoint.  */
+  tp_prev = NULL;
+  for (tp = tracepoints; tp != tpoint; tp = tp->next)
+    {
+      if (tp->type == fast_tracepoint || tp->type == static_tracepoint)
+       tp_prev = tp;
+    }
 
-  if (aexpr->length == 0)
+  if (tp_prev)
     {
-      trace_debug ("empty agent expression\n");
-      return expr_eval_empty_expression;
+      CORE_ADDR tp_prev_target_next_addr;
+
+      /* Insert TPOINT after TP_PREV in IPA.  */
+      if (read_inferior_data_pointer (tp_prev->obj_addr_on_target
+                                     + offsetof (struct tracepoint, next),
+                                     &tp_prev_target_next_addr))
+       {
+         internal_error (__FILE__, __LINE__,
+                         "error reading `tp_prev->next'");
+       }
+
+      /* tpoint->next = tp_prev->next */
+      write_inferior_data_ptr (tpoint->obj_addr_on_target
+                              + offsetof (struct tracepoint, next),
+                              tp_prev_target_next_addr);
+      /* tp_prev->next = tpoint */
+      write_inferior_data_ptr (tp_prev->obj_addr_on_target
+                              + offsetof (struct tracepoint, next),
+                              tpoint->obj_addr_on_target);
     }
+  else
+    /* First object in list, set the head pointer in the
+       inferior.  */
+    write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints,
+                            tpoint->obj_addr_on_target);
+
+}
+
+static void
+download_trace_state_variables (void)
+{
+  CORE_ADDR ptr = 0, prev_ptr = 0;
+  struct trace_state_variable *tsv;
 
-  bytecode_address_table = NULL;
+  /* Start out empty.  */
+  write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables, 0);
 
-  while (!done)
+  for (tsv = trace_state_variables; tsv != NULL; tsv = tsv->next)
     {
-      op = aexpr->bytes[pc];
+      struct trace_state_variable target_tsv;
 
-      trace_debug ("About to compile op 0x%x, pc=%d\n", op, pc);
+      /* TSV's with a getter have been initialized equally in both the
+        inferior and GDBserver.  Skip them.  */
+      if (tsv->getter != NULL)
+       continue;
 
-      /* Record the compiled-code address of the bytecode, for use by
-        jump instructions.  */
-      aentry = xmalloc (sizeof (struct bytecode_address));
-      aentry->pc = pc;
-      aentry->address = current_insn_ptr;
-      aentry->goto_pc = -1;
-      aentry->from_offset = aentry->from_size = 0;
-      aentry->next = bytecode_address_table;
-      bytecode_address_table = aentry;
+      target_tsv = *tsv;
 
-      ++pc;
+      prev_ptr = ptr;
+      ptr = target_malloc (sizeof (*tsv));
 
-      emit_error = 0;
+      if (tsv == trace_state_variables)
+       {
+         /* First object in list, set the head pointer in the
+            inferior.  */
 
-      switch (op)
+         write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables,
+                                  ptr);
+       }
+      else
        {
-       case gdb_agent_op_add:
-         emit_add ();
-         break;
+         write_inferior_data_ptr (prev_ptr
+                                  + offsetof (struct trace_state_variable,
+                                              next),
+                                  ptr);
+       }
 
-       case gdb_agent_op_sub:
-         emit_sub ();
-         break;
+      /* Write the whole object.  We'll fix up its pointers in a bit.
+        Assume no next, fixup when needed.  */
+      target_tsv.next = NULL;
 
-       case gdb_agent_op_mul:
-         emit_mul ();
-         break;
+      write_inferior_memory (ptr, (unsigned char *) &target_tsv,
+                            sizeof (target_tsv));
 
-       case gdb_agent_op_div_signed:
-         UNHANDLED;
-         break;
+      if (tsv->name != NULL)
+       {
+         size_t size = strlen (tsv->name) + 1;
+         CORE_ADDR name_addr = target_malloc (size);
+         write_inferior_memory (name_addr,
+                                (unsigned char *) tsv->name, size);
+         write_inferior_data_ptr (ptr
+                                  + offsetof (struct trace_state_variable,
+                                              name),
+                                  name_addr);
+       }
 
-       case gdb_agent_op_div_unsigned:
-         UNHANDLED;
-         break;
+      gdb_assert (tsv->getter == NULL);
+    }
 
-       case gdb_agent_op_rem_signed:
-         UNHANDLED;
-         break;
+  if (prev_ptr != 0)
+    {
+      /* Fixup the next pointer in the last item in the list.  */
+      write_inferior_data_ptr (prev_ptr
+                              + offsetof (struct trace_state_variable,
+                                          next), 0);
+    }
+}
 
-       case gdb_agent_op_rem_unsigned:
-         UNHANDLED;
-         break;
+/* Upload complete trace frames out of the IP Agent's trace buffer
+   into GDBserver's trace buffer.  This always uploads either all or
+   no trace frames.  This is the counter part of
+   `trace_alloc_trace_buffer'.  See its description of the atomic
+   synching mechanism.  */
 
-       case gdb_agent_op_lsh:
-         emit_lsh ();
-         break;
+static void
+upload_fast_traceframes (void)
+{
+  unsigned int ipa_traceframe_read_count, ipa_traceframe_write_count;
+  unsigned int ipa_traceframe_read_count_racy, ipa_traceframe_write_count_racy;
+  CORE_ADDR tf;
+  struct ipa_trace_buffer_control ipa_trace_buffer_ctrl;
+  unsigned int curr_tbctrl_idx;
+  unsigned int ipa_trace_buffer_ctrl_curr;
+  unsigned int ipa_trace_buffer_ctrl_curr_old;
+  CORE_ADDR ipa_trace_buffer_ctrl_addr;
+  struct breakpoint *about_to_request_buffer_space_bkpt;
+  CORE_ADDR ipa_trace_buffer_lo;
+  CORE_ADDR ipa_trace_buffer_hi;
 
-       case gdb_agent_op_rsh_signed:
-         emit_rsh_signed ();
-         break;
+  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_read_count,
+                             &ipa_traceframe_read_count_racy))
+    {
+      /* This will happen in most targets if the current thread is
+        running.  */
+      return;
+    }
 
-       case gdb_agent_op_rsh_unsigned:
-         emit_rsh_unsigned ();
-         break;
+  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_write_count,
+                             &ipa_traceframe_write_count_racy))
+    return;
 
-       case gdb_agent_op_trace:
-         UNHANDLED;
-         break;
+  trace_debug ("ipa_traceframe_count (racy area): %d (w=%d, r=%d)",
+              ipa_traceframe_write_count_racy
+              - ipa_traceframe_read_count_racy,
+              ipa_traceframe_write_count_racy,
+              ipa_traceframe_read_count_racy);
 
-       case gdb_agent_op_trace_quick:
-         UNHANDLED;
-         break;
+  if (ipa_traceframe_write_count_racy == ipa_traceframe_read_count_racy)
+    return;
+
+  about_to_request_buffer_space_bkpt
+    = set_breakpoint_at (ipa_sym_addrs.addr_about_to_request_buffer_space,
+                        NULL);
+
+  if (read_inferior_uinteger (ipa_sym_addrs.addr_trace_buffer_ctrl_curr,
+                             &ipa_trace_buffer_ctrl_curr))
+    return;
+
+  ipa_trace_buffer_ctrl_curr_old = ipa_trace_buffer_ctrl_curr;
+
+  curr_tbctrl_idx = ipa_trace_buffer_ctrl_curr & ~GDBSERVER_FLUSH_COUNT_MASK;
+
+  {
+    unsigned int prev, counter;
+
+    /* Update the token, with new counters, and the GDBserver stamp
+       bit.  Alway reuse the current TBC index.  */
+    prev = ipa_trace_buffer_ctrl_curr & GDBSERVER_FLUSH_COUNT_MASK_CURR;
+    counter = (prev + 0x100) & GDBSERVER_FLUSH_COUNT_MASK_CURR;
+
+    ipa_trace_buffer_ctrl_curr = (GDBSERVER_UPDATED_FLUSH_COUNT_BIT
+                                 | (prev << 12)
+                                 | counter
+                                 | curr_tbctrl_idx);
+  }
+
+  if (write_inferior_uinteger (ipa_sym_addrs.addr_trace_buffer_ctrl_curr,
+                              ipa_trace_buffer_ctrl_curr))
+    return;
+
+  trace_debug ("Lib: Committed %08x -> %08x",
+              ipa_trace_buffer_ctrl_curr_old,
+              ipa_trace_buffer_ctrl_curr);
+
+  /* Re-read these, now that we've installed the
+     `about_to_request_buffer_space' breakpoint/lock.  A thread could
+     have finished a traceframe between the last read of these
+     counters and setting the breakpoint above.  If we start
+     uploading, we never want to leave this function with
+     traceframe_read_count != 0, otherwise, GDBserver could end up
+     incrementing the counter tokens more than once (due to event loop
+     nesting), which would break the IP agent's "effective" detection
+     (see trace_alloc_trace_buffer).  */
+  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_read_count,
+                             &ipa_traceframe_read_count))
+    return;
+  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_write_count,
+                             &ipa_traceframe_write_count))
+    return;
+
+  if (debug_threads)
+    {
+      trace_debug ("ipa_traceframe_count (blocked area): %d (w=%d, r=%d)",
+                  ipa_traceframe_write_count - ipa_traceframe_read_count,
+                  ipa_traceframe_write_count, ipa_traceframe_read_count);
+
+      if (ipa_traceframe_write_count != ipa_traceframe_write_count_racy
+         || ipa_traceframe_read_count != ipa_traceframe_read_count_racy)
+       trace_debug ("note that ipa_traceframe_count's parts changed");
+    }
+
+  /* Get the address of the current TBC object (the IP agent has an
+     array of 3 such objects).  The index is stored in the TBC
+     token.  */
+  ipa_trace_buffer_ctrl_addr = ipa_sym_addrs.addr_trace_buffer_ctrl;
+  ipa_trace_buffer_ctrl_addr
+    += sizeof (struct ipa_trace_buffer_control) * curr_tbctrl_idx;
+
+  if (read_inferior_memory (ipa_trace_buffer_ctrl_addr,
+                           (unsigned char *) &ipa_trace_buffer_ctrl,
+                           sizeof (struct ipa_trace_buffer_control)))
+    return;
+
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_trace_buffer_lo,
+                                 &ipa_trace_buffer_lo))
+    return;
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_trace_buffer_hi,
+                                 &ipa_trace_buffer_hi))
+    return;
+
+  /* Offsets are easier to grok for debugging than raw addresses,
+     especially for the small trace buffer sizes that are useful for
+     testing.  */
+  trace_debug ("Lib: Trace buffer [%d] start=%d free=%d "
+              "endfree=%d wrap=%d hi=%d",
+              curr_tbctrl_idx,
+              (int) (ipa_trace_buffer_ctrl.start - ipa_trace_buffer_lo),
+              (int) (ipa_trace_buffer_ctrl.free - ipa_trace_buffer_lo),
+              (int) (ipa_trace_buffer_ctrl.end_free - ipa_trace_buffer_lo),
+              (int) (ipa_trace_buffer_ctrl.wrap - ipa_trace_buffer_lo),
+              (int) (ipa_trace_buffer_hi - ipa_trace_buffer_lo));
+
+  /* Note that the IPA's buffer is always circular.  */
+
+#define IPA_FIRST_TRACEFRAME() (ipa_trace_buffer_ctrl.start)
+
+#define IPA_NEXT_TRACEFRAME_1(TF, TFOBJ)               \
+  ((TF) + sizeof (struct traceframe) + (TFOBJ)->data_size)
+
+#define IPA_NEXT_TRACEFRAME(TF, TFOBJ)                                 \
+  (IPA_NEXT_TRACEFRAME_1 (TF, TFOBJ)                                   \
+   - ((IPA_NEXT_TRACEFRAME_1 (TF, TFOBJ) >= ipa_trace_buffer_ctrl.wrap) \
+      ? (ipa_trace_buffer_ctrl.wrap - ipa_trace_buffer_lo)             \
+      : 0))
+
+  tf = IPA_FIRST_TRACEFRAME ();
+
+  while (ipa_traceframe_write_count - ipa_traceframe_read_count)
+    {
+      struct tracepoint *tpoint;
+      struct traceframe *tframe;
+      unsigned char *block;
+      struct traceframe ipa_tframe;
+
+      if (read_inferior_memory (tf, (unsigned char *) &ipa_tframe,
+                               offsetof (struct traceframe, data)))
+       error ("Uploading: couldn't read traceframe at %s\n", paddress (tf));
+
+      if (ipa_tframe.tpnum == 0)
+       {
+         internal_error (__FILE__, __LINE__,
+                         "Uploading: No (more) fast traceframes, but"
+                         " ipa_traceframe_count == %u??\n",
+                         ipa_traceframe_write_count
+                         - ipa_traceframe_read_count);
+       }
+
+      /* Note that this will be incorrect for multi-location
+        tracepoints...  */
+      tpoint = find_next_tracepoint_by_number (NULL, ipa_tframe.tpnum);
+
+      tframe = add_traceframe (tpoint);
+      if (tframe == NULL)
+       {
+         trace_buffer_is_full = 1;
+         trace_debug ("Uploading: trace buffer is full");
+       }
+      else
+       {
+         /* Copy the whole set of blocks in one go for now.  FIXME:
+            split this in smaller blocks.  */
+         block = add_traceframe_block (tframe, tpoint,
+                                       ipa_tframe.data_size);
+         if (block != NULL)
+           {
+             if (read_inferior_memory (tf
+                                       + offsetof (struct traceframe, data),
+                                       block, ipa_tframe.data_size))
+               error ("Uploading: Couldn't read traceframe data at %s\n",
+                      paddress (tf + offsetof (struct traceframe, data)));
+           }
+
+         trace_debug ("Uploading: traceframe didn't fit");
+         finish_traceframe (tframe);
+       }
+
+      tf = IPA_NEXT_TRACEFRAME (tf, &ipa_tframe);
+
+      /* If we freed the traceframe that wrapped around, go back
+        to the non-wrap case.  */
+      if (tf < ipa_trace_buffer_ctrl.start)
+       {
+         trace_debug ("Lib: Discarding past the wraparound");
+         ipa_trace_buffer_ctrl.wrap = ipa_trace_buffer_hi;
+       }
+      ipa_trace_buffer_ctrl.start = tf;
+      ipa_trace_buffer_ctrl.end_free = ipa_trace_buffer_ctrl.start;
+      ++ipa_traceframe_read_count;
+
+      if (ipa_trace_buffer_ctrl.start == ipa_trace_buffer_ctrl.free
+         && ipa_trace_buffer_ctrl.start == ipa_trace_buffer_ctrl.end_free)
+       {
+         trace_debug ("Lib: buffer is fully empty.  "
+                      "Trace buffer [%d] start=%d free=%d endfree=%d",
+                      curr_tbctrl_idx,
+                      (int) (ipa_trace_buffer_ctrl.start
+                             - ipa_trace_buffer_lo),
+                      (int) (ipa_trace_buffer_ctrl.free
+                             - ipa_trace_buffer_lo),
+                      (int) (ipa_trace_buffer_ctrl.end_free
+                             - ipa_trace_buffer_lo));
+
+         ipa_trace_buffer_ctrl.start = ipa_trace_buffer_lo;
+         ipa_trace_buffer_ctrl.free = ipa_trace_buffer_lo;
+         ipa_trace_buffer_ctrl.end_free = ipa_trace_buffer_hi;
+         ipa_trace_buffer_ctrl.wrap = ipa_trace_buffer_hi;
+       }
+
+      trace_debug ("Uploaded a traceframe\n"
+                  "Lib: Trace buffer [%d] start=%d free=%d "
+                  "endfree=%d wrap=%d hi=%d",
+                  curr_tbctrl_idx,
+                  (int) (ipa_trace_buffer_ctrl.start - ipa_trace_buffer_lo),
+                  (int) (ipa_trace_buffer_ctrl.free - ipa_trace_buffer_lo),
+                  (int) (ipa_trace_buffer_ctrl.end_free
+                         - ipa_trace_buffer_lo),
+                  (int) (ipa_trace_buffer_ctrl.wrap - ipa_trace_buffer_lo),
+                  (int) (ipa_trace_buffer_hi - ipa_trace_buffer_lo));
+    }
+
+  if (write_inferior_memory (ipa_trace_buffer_ctrl_addr,
+                            (unsigned char *) &ipa_trace_buffer_ctrl,
+                            sizeof (struct ipa_trace_buffer_control)))
+    return;
+
+  write_inferior_integer (ipa_sym_addrs.addr_traceframe_read_count,
+                         ipa_traceframe_read_count);
+
+  trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx);
+
+  pause_all (1);
+
+  delete_breakpoint (about_to_request_buffer_space_bkpt);
+  about_to_request_buffer_space_bkpt = NULL;
+
+  unpause_all (1);
+
+  if (trace_buffer_is_full)
+    stop_tracing ();
+}
+#endif
+
+#ifdef IN_PROCESS_AGENT
+
+IP_AGENT_EXPORT_VAR int ust_loaded;
+IP_AGENT_EXPORT_VAR char cmd_buf[IPA_CMD_BUF_SIZE];
+
+#ifdef HAVE_UST
+
+/* 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
+{
+  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;
+}
+
+/* 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->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 (ipa_tdesc->registers_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;
+    }
+
+  if (!tpoint->enabled)
+    {
+      trace_debug ("gdb_probe: tracepoint disabled");
+      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);
 
-       case gdb_agent_op_log_not:
-         emit_log_not ();
-         break;
+      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 ();
+    }
+}
 
-       case gdb_agent_op_bit_and:
-         emit_bit_and ();
-         break;
+/* 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:
 
-       case gdb_agent_op_bit_or:
-         emit_bit_or ();
-         break;
+     trace_mark (ust, bar33, "str %s", "FOOBAZ");
 
-       case gdb_agent_op_bit_xor:
-         emit_bit_xor ();
-         break;
+   the collected data is "str FOOBAZ".
+*/
 
-       case gdb_agent_op_bit_not:
-         emit_bit_not ();
-         break;
+static void
+collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
+                               struct traceframe *tframe)
+{
+  struct static_tracepoint_ctx *umd = (struct static_tracepoint_ctx *) ctx;
+  unsigned char *bufspace;
+  int size;
+  va_list copy;
+  unsigned short blocklen;
 
-       case gdb_agent_op_equal:
-         emit_equal ();
-         break;
+  if (umd == NULL)
+    {
+      trace_debug ("Wanted to collect static trace data, "
+                  "but there's no static trace data");
+      return;
+    }
 
-       case gdb_agent_op_less_signed:
-         emit_less_signed ();
-         break;
+  va_copy (copy, *umd->args);
+  size = USTF(serialize_to_text) (NULL, 0, umd->fmt, copy);
+  va_end (copy);
 
-       case gdb_agent_op_less_unsigned:
-         emit_less_unsigned ();
-         break;
+  trace_debug ("Want to collect ust data");
 
-       case gdb_agent_op_ext:
-         arg = aexpr->bytes[pc++];
-         if (arg < (sizeof (LONGEST) * 8))
-           emit_ext (arg);
-         break;
+  /* 'S' + size + string */
+  bufspace = add_traceframe_block (tframe, umd->tpoint,
+                                  1 + sizeof (blocklen) + size + 1);
+  if (bufspace == NULL)
+    {
+      trace_debug ("Trace buffer block allocation failed, skipping");
+      return;
+    }
 
-       case gdb_agent_op_ref8:
-         emit_ref (1);
-         break;
+  /* Identify a static trace data block.  */
+  *bufspace = 'S';
 
-       case gdb_agent_op_ref16:
-         emit_ref (2);
-         break;
+  blocklen = size + 1;
+  memcpy (bufspace + 1, &blocklen, sizeof (blocklen));
 
-       case gdb_agent_op_ref32:
-         emit_ref (4);
-         break;
+  va_copy (copy, *umd->args);
+  USTF(serialize_to_text) ((char *) bufspace + 1 + sizeof (blocklen),
+                          size + 1, umd->fmt, copy);
+  va_end (copy);
 
-       case gdb_agent_op_ref64:
-         emit_ref (8);
-         break;
+  trace_debug ("Storing static tracepoint data in regblock: %s",
+              bufspace + 1 + sizeof (blocklen));
+}
 
-       case gdb_agent_op_if_goto:
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         aentry->goto_pc = arg;
-         emit_if_goto (&(aentry->from_offset), &(aentry->from_size));
-         break;
+/* The probe to register with lttng/ust.  */
+static struct ltt_available_probe gdb_ust_probe =
+  {
+    GDB_PROBE_NAME,
+    NULL,
+    gdb_probe,
+  };
 
-       case gdb_agent_op_goto:
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         aentry->goto_pc = arg;
-         emit_goto (&(aentry->from_offset), &(aentry->from_size));
-         break;
+#endif /* HAVE_UST */
+#endif /* IN_PROCESS_AGENT */
 
-       case gdb_agent_op_const8:
-         emit_stack_flush ();
-         top = aexpr->bytes[pc++];
-         emit_const (top);
-         break;
+#ifndef IN_PROCESS_AGENT
 
-       case gdb_agent_op_const16:
-         emit_stack_flush ();
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         emit_const (top);
-         break;
+/* 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.  */
 
-       case gdb_agent_op_const32:
-         emit_stack_flush ();
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         emit_const (top);
-         break;
+static int
+run_inferior_command (char *cmd, int len)
+{
+  int err = -1;
+  int pid = ptid_get_pid (current_ptid);
 
-       case gdb_agent_op_const64:
-         emit_stack_flush ();
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         emit_const (top);
-         break;
+  trace_debug ("run_inferior_command: running: %s", cmd);
 
-       case gdb_agent_op_reg:
-         emit_stack_flush ();
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         emit_reg (arg);
-         break;
+  pause_all (0);
+  uninsert_all_breakpoints ();
 
-       case gdb_agent_op_end:
-         trace_debug ("At end of expression\n");
+  err = agent_run_command (pid, (const char *) cmd, len);
 
-         /* Assume there is one stack element left, and that it is
-            cached in "top" where emit_epilogue can get to it.  */
-         emit_stack_adjust (1);
+  reinsert_all_breakpoints ();
+  unpause_all (0);
 
-         done = 1;
-         break;
+  return err;
+}
 
-       case gdb_agent_op_dup:
-         /* In our design, dup is equivalent to stack flushing.  */
-         emit_stack_flush ();
-         break;
+#else /* !IN_PROCESS_AGENT */
 
-       case gdb_agent_op_pop:
-         emit_pop ();
-         break;
+#include <sys/socket.h>
+#include <sys/un.h>
 
-       case gdb_agent_op_zero_ext:
-         arg = aexpr->bytes[pc++];
-         if (arg < (sizeof (LONGEST) * 8))
-           emit_zero_ext (arg);
-         break;
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
+#endif
 
-       case gdb_agent_op_swap:
-         emit_swap ();
-         break;
+/* Where we put the socked used for synchronization.  */
+#define SOCK_DIR P_tmpdir
 
-       case gdb_agent_op_getv:
-         emit_stack_flush ();
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         emit_int_call_1 (ipa_sym_addrs.addr_get_trace_state_variable_value,
-                          arg);
-         break;
+/* Thread ID of the helper thread.  GDBserver reads this to know which
+   is the help thread.  This is an LWP id on Linux.  */
+EXTERN_C_PUSH
+IP_AGENT_EXPORT_VAR int helper_thread_id;
+EXTERN_C_POP
 
-       case gdb_agent_op_setv:
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         emit_void_call_2 (ipa_sym_addrs.addr_set_trace_state_variable_value,
-                           arg);
-         break;
+static int
+init_named_socket (const char *name)
+{
+  int result, fd;
+  struct sockaddr_un addr;
 
-       case gdb_agent_op_tracev:
-         UNHANDLED;
-         break;
+  result = fd = socket (PF_UNIX, SOCK_STREAM, 0);
+  if (result == -1)
+    {
+      warning ("socket creation failed: %s", strerror (errno));
+      return -1;
+    }
 
-         /* GDB never (currently) generates any of these ops.  */
-       case gdb_agent_op_float:
-       case gdb_agent_op_ref_float:
-       case gdb_agent_op_ref_double:
-       case gdb_agent_op_ref_long_double:
-       case gdb_agent_op_l_to_d:
-       case gdb_agent_op_d_to_l:
-       case gdb_agent_op_trace16:
-         UNHANDLED;
-         break;
+  addr.sun_family = AF_UNIX;
 
-       default:
-         trace_debug ("Agent expression op 0x%x not recognized\n", op);
-         /* Don't struggle on, things will just get worse.  */
-         return expr_eval_unrecognized_opcode;
-       }
+  strncpy (addr.sun_path, name, UNIX_PATH_MAX);
+  addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
 
-      /* This catches errors that occur in target-specific code
-        emission.  */
-      if (emit_error)
+  result = access (name, F_OK);
+  if (result == 0)
+    {
+      /* File exists.  */
+      result = unlink (name);
+      if (result == -1)
        {
-         trace_debug ("Error %d while emitting code for %s\n",
-                      emit_error, gdb_agent_op_names[op]);
-         return expr_eval_unhandled_opcode;
+         warning ("unlink failed: %s", strerror (errno));
+         close (fd);
+         return -1;
        }
-
-      trace_debug ("Op %s compiled\n", gdb_agent_op_names[op]);
+      warning ("socket %s already exists; overwriting", name);
     }
 
-  /* Now fill in real addresses as goto destinations.  */
-  for (aentry = bytecode_address_table; aentry; aentry = aentry->next)
+  result = bind (fd, (struct sockaddr *) &addr, sizeof (addr));
+  if (result == -1)
     {
-      int written = 0;
-
-      if (aentry->goto_pc < 0)
-       continue;
-
-      /* Find the location that we are going to, and call back into
-        target-specific code to write the actual address or
-        displacement.  */
-      for (aentry2 = bytecode_address_table; aentry2; aentry2 = aentry2->next)
-       {
-         if (aentry2->pc == aentry->goto_pc)
-           {
-             trace_debug ("Want to jump from %s to %s\n",
-                          paddress (aentry->address),
-                          paddress (aentry2->address));
-             write_goto_address (aentry->address + aentry->from_offset,
-                                 aentry2->address, aentry->from_size);
-             written = 1;
-             break;
-           }
-       }
+      warning ("bind failed: %s", strerror (errno));
+      close (fd);
+      return -1;
+    }
 
-      /* Error out if we didn't find a destination.  */
-      if (!written)
-       {
-         trace_debug ("Destination of goto %d not found\n",
-                      aentry->goto_pc);
-         return expr_eval_invalid_goto;
-       }
+  result = listen (fd, 1);
+  if (result == -1)
+    {
+      warning ("listen: %s", strerror (errno));
+      close (fd);
+      return -1;
     }
 
-  return expr_eval_no_error;
+  return fd;
 }
 
-/* We'll need to adjust these when we consider bi-arch setups, and big
-   endian machines.  */
+static char agent_socket_name[UNIX_PATH_MAX];
 
 static int
-write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr)
-{
-  return write_inferior_memory (where,
-                               (unsigned char *) &ptr, sizeof (void *));
-}
-
-/* The base pointer of the IPA's heap.  This is the only memory the
-   IPA is allowed to use.  The IPA should _not_ call the inferior's
-   `malloc' during operation.  That'd be slow, and, most importantly,
-   it may not be safe.  We may be collecting a tracepoint in a signal
-   handler, for example.  */
-static CORE_ADDR target_tp_heap;
-
-/* Allocate at least SIZE bytes of memory from the IPA heap, aligned
-   to 8 bytes.  */
-
-static CORE_ADDR
-target_malloc (ULONGEST size)
+gdb_agent_socket_init (void)
 {
-  CORE_ADDR ptr;
+  int result, fd;
 
-  if (target_tp_heap == 0)
+  result = xsnprintf (agent_socket_name, UNIX_PATH_MAX, "%s/gdb_ust%d",
+                     SOCK_DIR, getpid ());
+  if (result >= UNIX_PATH_MAX)
     {
-      /* We have the pointer *address*, need what it points to.  */
-      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_tp_heap_buffer,
-                                     &target_tp_heap))
-       fatal ("could get target heap head pointer");
+      trace_debug ("string overflow allocating socket name");
+      return -1;
     }
 
-  ptr = target_tp_heap;
-  target_tp_heap += size;
-
-  /* Pad to 8-byte alignment.  */
-  target_tp_heap = ((target_tp_heap + 7) & ~0x7);
+  fd = init_named_socket (agent_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.", agent_socket_name);
 
-  return ptr;
+  return fd;
 }
 
-static CORE_ADDR
-download_agent_expr (struct agent_expr *expr)
-{
-  CORE_ADDR expr_addr;
-  CORE_ADDR expr_bytes;
-
-  expr_addr = target_malloc (sizeof (*expr));
-  write_inferior_memory (expr_addr, (unsigned char *) expr, sizeof (*expr));
-
-  expr_bytes = target_malloc (expr->length);
-  write_inferior_data_ptr (expr_addr + offsetof (struct agent_expr, bytes),
-                          expr_bytes);
-  write_inferior_memory (expr_bytes, expr->bytes, expr->length);
+#ifdef HAVE_UST
 
-  return expr_addr;
-}
+/* The next marker to be returned on a qTsSTM command.  */
+static const struct marker *next_st;
 
-/* Align V up to N bits.  */
-#define UALIGN(V, N) (((V) + ((N) - 1)) & ~((N) - 1))
+/* Returns the first known marker.  */
 
-static void
-download_tracepoints (void)
+struct marker *
+first_marker (void)
 {
-  CORE_ADDR tpptr = 0, prev_tpptr = 0;
-  struct tracepoint *tpoint;
-
-  /* Start out empty.  */
-  write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, 0);
-
-  for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
-    {
-      struct tracepoint target_tracepoint;
-
-      if (tpoint->type != fast_tracepoint)
-       continue;
-
-      /* Maybe download a compiled condition.  */
-      if (tpoint->cond != NULL && target_emit_ops () != NULL)
-       {
-         CORE_ADDR jentry, jump_entry;
-
-         jentry = jump_entry = get_jump_space_head ();
+  struct marker_iter iter;
 
-         if (tpoint->cond != NULL)
-           {
-             /* Pad to 8-byte alignment. (needed?)  */
-             /* Actually this should be left for the target to
-                decide.  */
-             jentry = UALIGN (jentry, 8);
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
 
-             compile_tracepoint_condition (tpoint, &jentry);
-           }
+  return iter.marker;
+}
 
-         /* Pad to 8-byte alignment.  */
-         jentry = UALIGN (jentry, 8);
-         claim_jump_space (jentry - jump_entry);
-       }
+/* Returns the marker following M.  */
 
-      target_tracepoint = *tpoint;
+const struct marker *
+next_marker (const struct marker *m)
+{
+  struct marker_iter iter;
 
-      prev_tpptr = tpptr;
-      tpptr = target_malloc (sizeof (*tpoint));
-      tpoint->obj_addr_on_target = tpptr;
+  USTF(marker_iter_reset) (&iter);
+  USTF(marker_iter_start) (&iter);
 
-      if (tpoint == tracepoints)
-       {
-         /* First object in list, set the head pointer in the
-            inferior.  */
-         write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, tpptr);
-       }
-      else
+  for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
+    {
+      if (iter.marker == m)
        {
-         write_inferior_data_ptr (prev_tpptr + offsetof (struct tracepoint,
-                                                         next),
-                                  tpptr);
+         USTF(marker_iter_next) (&iter);
+         return iter.marker;
        }
+    }
 
-      /* Write the whole object.  We'll fix up its pointers in a bit.
-        Assume no next for now.  This is fixed up above on the next
-        iteration, if there's any.  */
-      target_tracepoint.next = NULL;
-      /* Need to clear this here too, since we're downloading the
-        tracepoints before clearing our own copy.  */
-      target_tracepoint.hit_count = 0;
-
-      write_inferior_memory (tpptr, (unsigned char *) &target_tracepoint,
-                            sizeof (target_tracepoint));
-
-      if (tpoint->cond)
-       write_inferior_data_ptr (tpptr + offsetof (struct tracepoint,
-                                                  cond),
-                                download_agent_expr (tpoint->cond));
-
-      if (tpoint->numactions)
-       {
-         int i;
-         CORE_ADDR actions_array;
-
-         /* The pointers array.  */
-         actions_array
-           = target_malloc (sizeof (*tpoint->actions) * tpoint->numactions);
-         write_inferior_data_ptr (tpptr + offsetof (struct tracepoint,
-                                                    actions),
-                                  actions_array);
-
-         /* Now for each pointer, download the action.  */
-         for (i = 0; i < tpoint->numactions; i++)
-           {
-             CORE_ADDR ipa_action = 0;
-             struct tracepoint_action *action = tpoint->actions[i];
+  return NULL;
+}
 
-             switch (action->type)
-               {
-               case 'M':
-                 ipa_action
-                   = target_malloc (sizeof (struct collect_memory_action));
-                 write_inferior_memory (ipa_action,
-                                        (unsigned char *) action,
-                                        sizeof (struct collect_memory_action));
-                 break;
-               case 'R':
-                 ipa_action
-                   = target_malloc (sizeof (struct collect_registers_action));
-                 write_inferior_memory (ipa_action,
-                                        (unsigned char *) action,
-                                        sizeof (struct collect_registers_action));
-                 break;
-               case 'X':
-                 {
-                   CORE_ADDR expr;
-                   struct eval_expr_action *eaction
-                     = (struct eval_expr_action *) action;
-
-                   ipa_action = target_malloc (sizeof (*eaction));
-                   write_inferior_memory (ipa_action,
-                                          (unsigned char *) eaction,
-                                          sizeof (*eaction));
-
-                   expr = download_agent_expr (eaction->expr);
-                   write_inferior_data_ptr
-                     (ipa_action + offsetof (struct eval_expr_action, expr),
-                      expr);
-                   break;
-                 }
-               default:
-                 trace_debug ("unknown trace action '%c', ignoring",
-                              action->type);
-                 break;
-               }
+/* Return an hexstr version of the STR C string, fit for sending to
+   GDB.  */
 
-             if (ipa_action != 0)
-               write_inferior_data_ptr
-                 (actions_array + i * sizeof (sizeof (*tpoint->actions)),
-                  ipa_action);
-           }
-       }
-    }
+static char *
+cstr_to_hexstr (const char *str)
+{
+  int len = strlen (str);
+  char *hexstr = xmalloc (len * 2 + 1);
+  bin2hex ((gdb_byte *) str, hexstr, len);
+  return hexstr;
 }
 
+/* Compose packet that is the response to the qTsSTM/qTfSTM/qTSTMat
+   packets.  */
+
 static void
-download_trace_state_variables (void)
+response_ust_marker (char *packet, const struct marker *st)
 {
-  CORE_ADDR ptr = 0, prev_ptr = 0;
-  struct trace_state_variable *tsv;
+  char *strid, *format, *tmp;
 
-  /* Start out empty.  */
-  write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables, 0);
+  next_st = next_marker (st);
 
-  for (tsv = trace_state_variables; tsv != NULL; tsv = tsv->next)
-    {
-      struct trace_state_variable target_tsv;
+  tmp = xmalloc (strlen (st->channel) + 1 +
+                strlen (st->name) + 1);
+  sprintf (tmp, "%s/%s", st->channel, st->name);
 
-      /* TSV's with a getter have been initialized equally in both the
-        inferior and GDBserver.  Skip them.  */
-      if (tsv->getter != NULL)
-       continue;
+  strid = cstr_to_hexstr (tmp);
+  free (tmp);
 
-      target_tsv = *tsv;
+  format = cstr_to_hexstr (st->format);
 
-      prev_ptr = ptr;
-      ptr = target_malloc (sizeof (*tsv));
+  sprintf (packet, "m%s:%s:%s",
+          paddress ((uintptr_t) st->location),
+          strid,
+          format);
 
-      if (tsv == trace_state_variables)
-       {
-         /* First object in list, set the head pointer in the
-            inferior.  */
+  free (strid);
+  free (format);
+}
 
-         write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables,
-                                  ptr);
-       }
-      else
-       {
-         write_inferior_data_ptr (prev_ptr
-                                  + offsetof (struct trace_state_variable,
-                                              next),
-                                  ptr);
-       }
+/* Return the first static tracepoint, and initialize the state
+   machine that will iterate through all the static tracepoints.  */
 
-      /* Write the whole object.  We'll fix up its pointers in a bit.
-        Assume no next, fixup when needed.  */
-      target_tsv.next = NULL;
+static void
+cmd_qtfstm (char *packet)
+{
+  trace_debug ("Returning first trace state variable definition");
 
-      write_inferior_memory (ptr, (unsigned char *) &target_tsv,
-                            sizeof (target_tsv));
+  if (first_marker ())
+    response_ust_marker (packet, first_marker ());
+  else
+    strcpy (packet, "l");
+}
 
-      if (tsv->name != NULL)
-       {
-         size_t size = strlen (tsv->name) + 1;
-         CORE_ADDR name_addr = target_malloc (size);
-         write_inferior_memory (name_addr,
-                                (unsigned char *) tsv->name, size);
-         write_inferior_data_ptr (ptr
-                                  + offsetof (struct trace_state_variable,
-                                              name),
-                                  name_addr);
-       }
+/* Return additional trace state variable definitions. */
 
-      if (tsv->getter != NULL)
-       {
-         fatal ("what to do with these?");
-       }
-    }
+static void
+cmd_qtsstm (char *packet)
+{
+  trace_debug ("Returning static tracepoint");
 
-  if (prev_ptr != 0)
-    {
-      /* Fixup the next pointer in the last item in the list.  */
-      write_inferior_data_ptr (prev_ptr + offsetof (struct trace_state_variable,
-                                                   next), 0);
-    }
+  if (next_st)
+    response_ust_marker (packet, next_st);
+  else
+    strcpy (packet, "l");
 }
 
-/* Upload complete trace frames out of the IP Agent's trace buffer
-   into GDBserver's trace buffer.  This always uploads either all or
-   no trace frames.  This is the counter part of
-   `trace_alloc_trace_buffer'.  See its description of the atomic
-   synching mechanism.  */
+/* Disconnect the GDB probe from a marker at a given address.  */
 
 static void
-upload_fast_traceframes (void)
+unprobe_marker_at (char *packet)
 {
-  unsigned int ipa_traceframe_read_count, ipa_traceframe_write_count;
-  unsigned int ipa_traceframe_read_count_racy, ipa_traceframe_write_count_racy;
-  CORE_ADDR tf;
-  struct ipa_trace_buffer_control ipa_trace_buffer_ctrl;
-  unsigned int curr_tbctrl_idx;
-  unsigned int ipa_trace_buffer_ctrl_curr;
-  unsigned int ipa_trace_buffer_ctrl_curr_old;
-  CORE_ADDR ipa_trace_buffer_ctrl_addr;
-  struct breakpoint *about_to_request_buffer_space_bkpt;
-  CORE_ADDR ipa_trace_buffer_lo;
-  CORE_ADDR ipa_trace_buffer_hi;
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+
+  p += sizeof ("unprobe_marker_at:") - 1;
 
-  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_read_count,
-                             &ipa_traceframe_read_count_racy))
-    {
-      /* This will happen in most targets if the current thread is
-        running.  */
-      return;
-    }
+  p = unpack_varlen_hex (p, &address);
 
-  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_write_count,
-                             &ipa_traceframe_write_count_racy))
-    return;
+  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;
+      }
+}
 
-  trace_debug ("ipa_traceframe_count (racy area): %d (w=%d, r=%d)",
-              ipa_traceframe_write_count_racy - ipa_traceframe_read_count_racy,
-              ipa_traceframe_write_count_racy, ipa_traceframe_read_count_racy);
+/* Connect the GDB probe to a marker at a given address.  */
 
-  if (ipa_traceframe_write_count_racy == ipa_traceframe_read_count_racy)
-    return;
+static int
+probe_marker_at (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+  struct marker *m;
 
-  about_to_request_buffer_space_bkpt
-    = set_breakpoint_at (ipa_sym_addrs.addr_about_to_request_buffer_space,
-                        NULL);
+  p += sizeof ("probe_marker_at:") - 1;
 
-  if (read_inferior_uinteger (ipa_sym_addrs.addr_trace_buffer_ctrl_curr,
-                             &ipa_trace_buffer_ctrl_curr))
-    return;
+  p = unpack_varlen_hex (p, &address);
 
-  ipa_trace_buffer_ctrl_curr_old = ipa_trace_buffer_ctrl_curr;
+  USTF(marker_iter_reset) (&iter);
 
-  curr_tbctrl_idx = ipa_trace_buffer_ctrl_curr & ~GDBSERVER_FLUSH_COUNT_MASK;
+  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;
 
-  {
-    unsigned int prev, counter;
+       trace_debug ("found marker for address.  "
+                    "ltt_marker_connect (marker = %s/%s)",
+                    m->channel, m->name);
 
-    /* Update the token, with new counters, and the GDBserver stamp
-       bit.  Alway reuse the current TBC index.  */
-    prev = ipa_trace_buffer_ctrl_curr & 0x0007ff00;
-    counter = (prev + 0x100) & 0x0007ff00;
+       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);
 
-    ipa_trace_buffer_ctrl_curr = (0x80000000
-                                 | (prev << 12)
-                                 | counter
-                                 | curr_tbctrl_idx);
-  }
+       if (result < 0)
+         {
+           sprintf (packet, "E.could not connect marker: channel=%s, name=%s",
+                    m->channel, m->name);
+           return -1;
+         }
 
-  if (write_inferior_uinteger (ipa_sym_addrs.addr_trace_buffer_ctrl_curr,
-                              ipa_trace_buffer_ctrl_curr))
-    return;
+       strcpy (packet, "OK");
+       return 0;
+      }
 
-  trace_debug ("Lib: Committed %08x -> %08x",
-              ipa_trace_buffer_ctrl_curr_old,
-              ipa_trace_buffer_ctrl_curr);
+  sprintf (packet, "E.no marker found at 0x%s", paddress (address));
+  return -1;
+}
 
-  /* Re-read these, now that we've installed the
-     `about_to_request_buffer_space' breakpoint/lock.  A thread could
-     have finished a traceframe between the last read of these
-     counters and setting the breakpoint above.  If we start
-     uploading, we never want to leave this function with
-     traceframe_read_count != 0, otherwise, GDBserver could end up
-     incrementing the counter tokens more than once (due to event loop
-     nesting), which would break the IP agent's "effective" detection
-     (see trace_alloc_trace_buffer).  */
-  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_read_count,
-                             &ipa_traceframe_read_count))
-    return;
-  if (read_inferior_uinteger (ipa_sym_addrs.addr_traceframe_write_count,
-                             &ipa_traceframe_write_count))
-    return;
+static int
+cmd_qtstmat (char *packet)
+{
+  char *p = packet;
+  ULONGEST address;
+  struct marker_iter iter;
+  struct marker *m;
 
-  if (debug_threads)
-    {
-      trace_debug ("ipa_traceframe_count (blocked area): %d (w=%d, r=%d)",
-                  ipa_traceframe_write_count - ipa_traceframe_read_count,
-                  ipa_traceframe_write_count, ipa_traceframe_read_count);
+  p += sizeof ("qTSTMat:") - 1;
 
-      if (ipa_traceframe_write_count != ipa_traceframe_write_count_racy
-         || ipa_traceframe_read_count != ipa_traceframe_read_count_racy)
-       trace_debug ("note that ipa_traceframe_count's parts changed");
-    }
+  p = unpack_varlen_hex (p, &address);
 
-  /* Get the address of the current TBC object (the IP agent has an
-     array of 3 such objects).  The index is stored in the TBC
-     token.  */
-  ipa_trace_buffer_ctrl_addr = ipa_sym_addrs.addr_trace_buffer_ctrl;
-  ipa_trace_buffer_ctrl_addr
-    += sizeof (struct ipa_trace_buffer_control) * curr_tbctrl_idx;
+  USTF(marker_iter_reset) (&iter);
 
-  if (read_inferior_memory (ipa_trace_buffer_ctrl_addr,
-                           (unsigned char *) &ipa_trace_buffer_ctrl,
-                           sizeof (struct ipa_trace_buffer_control)))
-    return;
+  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;
+      }
 
-  if (read_inferior_data_pointer (ipa_sym_addrs.addr_trace_buffer_lo,
-                                 &ipa_trace_buffer_lo))
-    return;
-  if (read_inferior_data_pointer (ipa_sym_addrs.addr_trace_buffer_hi,
-                                 &ipa_trace_buffer_hi))
-    return;
+  strcpy (packet, "l");
+  return -1;
+}
 
-  /* Offsets are easier to grok for debugging than raw addresses,
-     especially for the small trace buffer sizes that are useful for
-     testing.  */
-  trace_debug ("Lib: Trace buffer [%d] start=%d free=%d "
-              "endfree=%d wrap=%d hi=%d",
-              curr_tbctrl_idx,
-              (int) (ipa_trace_buffer_ctrl.start - ipa_trace_buffer_lo),
-              (int) (ipa_trace_buffer_ctrl.free - ipa_trace_buffer_lo),
-              (int) (ipa_trace_buffer_ctrl.end_free - ipa_trace_buffer_lo),
-              (int) (ipa_trace_buffer_ctrl.wrap - ipa_trace_buffer_lo),
-              (int) (ipa_trace_buffer_hi - ipa_trace_buffer_lo));
+static void
+gdb_ust_init (void)
+{
+  if (!dlsym_ust ())
+    return;
 
-  /* Note that the IPA's buffer is always circular.  */
+  USTF(ltt_probe_register) (&gdb_ust_probe);
+}
 
-#define IPA_FIRST_TRACEFRAME() (ipa_trace_buffer_ctrl.start)
+#endif /* HAVE_UST */
 
-#define IPA_NEXT_TRACEFRAME_1(TF, TFOBJ)               \
-  ((TF) + sizeof (struct traceframe) + (TFOBJ)->data_size)
+#include <sys/syscall.h>
 
-#define IPA_NEXT_TRACEFRAME(TF, TFOBJ)                                 \
-  (IPA_NEXT_TRACEFRAME_1 (TF, TFOBJ)                                   \
-   - ((IPA_NEXT_TRACEFRAME_1 (TF, TFOBJ) >= ipa_trace_buffer_ctrl.wrap) \
-      ? (ipa_trace_buffer_ctrl.wrap - ipa_trace_buffer_lo)             \
-      : 0))
+static void
+gdb_agent_remove_socket (void)
+{
+  unlink (agent_socket_name);
+}
 
-  tf = IPA_FIRST_TRACEFRAME ();
+/* Helper thread of agent.  */
 
-  while (ipa_traceframe_write_count - ipa_traceframe_read_count)
-    {
-      struct tracepoint *tpoint;
-      struct traceframe *tframe;
-      unsigned char *block;
-      struct traceframe ipa_tframe;
+static void *
+gdb_agent_helper_thread (void *arg)
+{
+  int listen_fd;
 
-      if (read_inferior_memory (tf, (unsigned char *) &ipa_tframe,
-                               offsetof (struct traceframe, data)))
-       error ("Uploading: couldn't read traceframe at %s\n", paddress (tf));
+  atexit (gdb_agent_remove_socket);
 
-      if (ipa_tframe.tpnum == 0)
-       fatal ("Uploading: No (more) fast traceframes, but "
-              "ipa_traceframe_count == %u??\n",
-              ipa_traceframe_write_count - ipa_traceframe_read_count);
+  while (1)
+    {
+      listen_fd = gdb_agent_socket_init ();
 
-      /* Note that this will be incorrect for multi-location
-        tracepoints...  */
-      tpoint = find_next_tracepoint_by_number (NULL, ipa_tframe.tpnum);
+      if (helper_thread_id == 0)
+       helper_thread_id = syscall (SYS_gettid);
 
-      tframe = add_traceframe (tpoint);
-      if (tframe == NULL)
+      if (listen_fd == -1)
        {
-         trace_buffer_is_full = 1;
-         trace_debug ("Uploading: trace buffer is full");
+         warning ("could not create sync socket\n");
+         break;
        }
-      else
+
+      while (1)
        {
-         /* Copy the whole set of blocks in one go for now.  FIXME:
-            split this in smaller blocks.  */
-         block = add_traceframe_block (tframe, ipa_tframe.data_size);
-         if (block != NULL)
+         socklen_t tmp;
+         struct sockaddr_un sockaddr;
+         int fd;
+         char buf[1];
+         int ret;
+         int stop_loop = 0;
+
+         tmp = sizeof (sockaddr);
+
+         do
            {
-             if (read_inferior_memory (tf + offsetof (struct traceframe, data),
-                                       block, ipa_tframe.data_size))
-               error ("Uploading: Couldn't read traceframe data at %s\n",
-                      paddress (tf + offsetof (struct traceframe, data)));
+             fd = accept (listen_fd, (struct sockaddr *) &sockaddr, &tmp);
            }
+         /* It seems an ERESTARTSYS can escape out of accept.  */
+         while (fd == -512 || (fd == -1 && errno == EINTR));
 
-         trace_debug ("Uploading: traceframe didn't fit");
-         finish_traceframe (tframe);
-       }
+         if (fd < 0)
+           {
+             warning ("Accept returned %d, error: %s\n",
+                      fd, strerror (errno));
+             break;
+           }
 
-      tf = IPA_NEXT_TRACEFRAME (tf, &ipa_tframe);
+         do
+           {
+             ret = read (fd, buf, 1);
+           } while (ret == -1 && errno == EINTR);
 
-      /* If we freed the traceframe that wrapped around, go back
-        to the non-wrap case.  */
-      if (tf < ipa_trace_buffer_ctrl.start)
-       {
-         trace_debug ("Lib: Discarding past the wraparound");
-         ipa_trace_buffer_ctrl.wrap = ipa_trace_buffer_hi;
-       }
-      ipa_trace_buffer_ctrl.start = tf;
-      ipa_trace_buffer_ctrl.end_free = ipa_trace_buffer_ctrl.start;
-      ++ipa_traceframe_read_count;
+         if (ret == -1)
+           {
+             warning ("reading socket (fd=%d) failed with %s",
+                      fd, strerror (errno));
+             close (fd);
+             break;
+           }
 
-      if (ipa_trace_buffer_ctrl.start == ipa_trace_buffer_ctrl.free
-         && ipa_trace_buffer_ctrl.start == ipa_trace_buffer_ctrl.end_free)
-       {
-         trace_debug ("Lib: buffer is fully empty.  "
-                      "Trace buffer [%d] start=%d free=%d endfree=%d",
-                      curr_tbctrl_idx,
-                      (int) (ipa_trace_buffer_ctrl.start
-                             - ipa_trace_buffer_lo),
-                      (int) (ipa_trace_buffer_ctrl.free
-                             - ipa_trace_buffer_lo),
-                      (int) (ipa_trace_buffer_ctrl.end_free
-                             - ipa_trace_buffer_lo));
+         if (cmd_buf[0])
+           {
+             if (startswith (cmd_buf, "close"))
+               {
+                 stop_loop = 1;
+               }
+#ifdef HAVE_UST
+             else if (strcmp ("qTfSTM", cmd_buf) == 0)
+               {
+                 cmd_qtfstm (cmd_buf);
+               }
+             else if (strcmp ("qTsSTM", cmd_buf) == 0)
+               {
+                 cmd_qtsstm (cmd_buf);
+               }
+             else if (startswith (cmd_buf, "unprobe_marker_at:"))
+               {
+                 unprobe_marker_at (cmd_buf);
+               }
+             else if (startswith (cmd_buf, "probe_marker_at:"))
+               {
+                 probe_marker_at (cmd_buf);
+               }
+             else if (startswith (cmd_buf, "qTSTMat:"))
+               {
+                 cmd_qtstmat (cmd_buf);
+               }
+#endif /* HAVE_UST */
+           }
 
-         ipa_trace_buffer_ctrl.start = ipa_trace_buffer_lo;
-         ipa_trace_buffer_ctrl.free = ipa_trace_buffer_lo;
-         ipa_trace_buffer_ctrl.end_free = ipa_trace_buffer_hi;
-         ipa_trace_buffer_ctrl.wrap = ipa_trace_buffer_hi;
-       }
+         /* Fix compiler's warning: ignoring return value of 'write'.  */
+         ret = write (fd, buf, 1);
+         close (fd);
 
-      trace_debug ("Uploaded a traceframe\n"
-                  "Lib: Trace buffer [%d] start=%d free=%d "
-                  "endfree=%d wrap=%d hi=%d",
-                  curr_tbctrl_idx,
-                  (int) (ipa_trace_buffer_ctrl.start - ipa_trace_buffer_lo),
-                  (int) (ipa_trace_buffer_ctrl.free - ipa_trace_buffer_lo),
-                  (int) (ipa_trace_buffer_ctrl.end_free - ipa_trace_buffer_lo),
-                  (int) (ipa_trace_buffer_ctrl.wrap - ipa_trace_buffer_lo),
-                  (int) (ipa_trace_buffer_hi - ipa_trace_buffer_lo));
+         if (stop_loop)
+           {
+             close (listen_fd);
+             unlink (agent_socket_name);
+
+             /* Sleep endlessly to wait the whole inferior stops.  This
+                thread can not exit because GDB or GDBserver may still need
+                'current_thread' (representing this thread) to access
+                inferior memory.  Otherwise, this thread exits earlier than
+                other threads, and 'current_thread' is set to NULL.  */
+             while (1)
+               sleep (10);
+           }
+       }
     }
 
-  if (write_inferior_memory (ipa_trace_buffer_ctrl_addr,
-                            (unsigned char *) &ipa_trace_buffer_ctrl,
-                            sizeof (struct ipa_trace_buffer_control)))
-    return;
+  return NULL;
+}
 
-  write_inferior_integer (ipa_sym_addrs.addr_traceframe_read_count,
-                         ipa_traceframe_read_count);
+#include <signal.h>
+#include <pthread.h>
 
-  trace_debug ("Done uploading traceframes [%d]\n", curr_tbctrl_idx);
+EXTERN_C_PUSH
+IP_AGENT_EXPORT_VAR int gdb_agent_capability = AGENT_CAPA_STATIC_TRACE;
+EXTERN_C_POP
 
-  pause_all (1);
-  cancel_breakpoints ();
+static void
+gdb_agent_init (void)
+{
+  int res;
+  pthread_t thread;
+  sigset_t new_mask;
+  sigset_t orig_mask;
 
-  delete_breakpoint (about_to_request_buffer_space_bkpt);
-  about_to_request_buffer_space_bkpt = NULL;
+  /* We want the helper thread to be as transparent as possible, so
+     have it inherit an all-signals-blocked mask.  */
 
-  unpause_all (1);
+  sigfillset (&new_mask);
+  res = pthread_sigmask (SIG_SETMASK, &new_mask, &orig_mask);
+  if (res)
+    perror_with_name ("pthread_sigmask (1)");
 
-  if (trace_buffer_is_full)
-    stop_tracing ();
-}
-#endif
+  res = pthread_create (&thread,
+                       NULL,
+                       gdb_agent_helper_thread,
+                       NULL);
 
-#ifdef IN_PROCESS_AGENT
+  res = pthread_sigmask (SIG_SETMASK, &orig_mask, NULL);
+  if (res)
+    perror_with_name ("pthread_sigmask (2)");
+
+  while (helper_thread_id == 0)
+    usleep (1);
+
+#ifdef HAVE_UST
+  gdb_ust_init ();
+#endif
+}
 
 #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;
+IP_AGENT_EXPORT_VAR char *gdb_tp_heap_buffer;
+IP_AGENT_EXPORT_VAR char *gdb_jump_pad_buffer;
+IP_AGENT_EXPORT_VAR char *gdb_jump_pad_buffer_end;
+IP_AGENT_EXPORT_VAR char *gdb_trampoline_buffer;
+IP_AGENT_EXPORT_VAR char *gdb_trampoline_buffer_end;
+IP_AGENT_EXPORT_VAR char *gdb_trampoline_buffer_error;
+
+/* Record the result of getting buffer space for fast tracepoint
+   trampolines.  Any error message is copied, since caller may not be
+   using persistent storage.  */
+
+void
+set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end, char *errmsg)
+{
+  gdb_trampoline_buffer = (char *) (uintptr_t) begin;
+  gdb_trampoline_buffer_end = (char *) (uintptr_t) end;
+  if (errmsg)
+    strncpy (gdb_trampoline_buffer_error, errmsg, 99);
+  else
+    strcpy (gdb_trampoline_buffer_error, "no buffer passed");
+}
 
 static void __attribute__ ((constructor))
 initialize_tracepoint_ftlib (void)
 {
   initialize_tracepoint ();
+
+  gdb_agent_init ();
 }
 
-#endif
+#endif /* IN_PROCESS_AGENT */
+
+/* Return a timestamp, expressed as microseconds of the usual Unix
+   time.  (As the result is a 64-bit number, it will not overflow any
+   time soon.)  */
 
 static LONGEST
-tsv_get_timestamp (void)
+get_timestamp (void)
 {
    struct timeval tv;
 
@@ -6100,10 +7345,8 @@ tsv_get_timestamp (void)
 void
 initialize_tracepoint (void)
 {
-  /* There currently no way to change the buffer size.  */
-  const int sizeOfBuffer = 5 * 1024 * 1024;
-  unsigned char *buf = xmalloc (sizeOfBuffer);
-  init_trace_buffer (buf, sizeOfBuffer);
+  /* Start with the default size.  */
+  init_trace_buffer (DEFAULT_TRACE_BUFFER_SIZE);
 
   /* Wire trace state variable 1 to be the timestamp.  This will be
      uploaded to GDB upon connection and become one of its trace state
@@ -6111,29 +7354,49 @@ initialize_tracepoint (void)
      variable numbered 1, it will be renumbered.)  */
   create_trace_state_variable (1, 0);
   set_trace_state_variable_name (1, "trace_timestamp");
-  set_trace_state_variable_getter (1, tsv_get_timestamp);
+  set_trace_state_variable_getter (1, get_timestamp);
 
 #ifdef IN_PROCESS_AGENT
   {
+    uintptr_t addr;
     int pagesize;
+
     pagesize = sysconf (_SC_PAGE_SIZE);
     if (pagesize == -1)
-      fatal ("sysconf");
+      perror_with_name ("sysconf");
 
     gdb_tp_heap_buffer = xmalloc (5 * 1024 * 1024);
 
-    /* Allocate scratch buffer aligned on a page boundary.  */
-    gdb_jump_pad_buffer = memalign (pagesize, pagesize * 20);
-    gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + pagesize * 20;
+#define SCRATCH_BUFFER_NPAGES 20
 
-    /* Make it writable and executable.  */
-    if (mprotect (gdb_jump_pad_buffer, pagesize * 20,
-                 PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
-      fatal ("\
-initialize_tracepoint: mprotect(%p, %d, PROT_READ|PROT_EXEC) failed with %s",
-            gdb_jump_pad_buffer, pagesize * 20, strerror (errno));
+    /* Allocate scratch buffer aligned on a page boundary, at a low
+       address (close to the main executable's code).  */
+    for (addr = pagesize; addr != 0; addr += pagesize)
+      {
+       gdb_jump_pad_buffer = mmap ((void *) addr, pagesize * SCRATCH_BUFFER_NPAGES,
+                                   PROT_READ | PROT_WRITE | PROT_EXEC,
+                                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+                                   -1, 0);
+       if (gdb_jump_pad_buffer != MAP_FAILED)
+         break;
+      }
+
+    if (addr == 0)
+      perror_with_name ("mmap");
+
+    gdb_jump_pad_buffer_end = gdb_jump_pad_buffer + pagesize * SCRATCH_BUFFER_NPAGES;
   }
 
+  gdb_trampoline_buffer = gdb_trampoline_buffer_end = 0;
+
+  /* It's not a fatal error for something to go wrong with trampoline
+     buffer setup, but it can be mysterious, so create a channel to
+     report back on what went wrong, using a fixed size since we may
+     not be able to allocate space later when the problem occurs.  */
+  gdb_trampoline_buffer_error = xmalloc (IPA_BUFSIZ);
+
+  strcpy (gdb_trampoline_buffer_error, "No errors reported");
+
   initialize_low_tracepoint ();
 #endif
 }
This page took 0.096354 seconds and 4 git commands to generate.