gdb/
[deliverable/binutils-gdb.git] / gdb / gdbserver / tracepoint.c
index 139e30e0141817a8cb31274bbad82697348eccea..280c281d65ddad19df3eb0e21740e9622f14afbc 100644 (file)
@@ -1,5 +1,5 @@
 /* Tracepoint code for remote server for GDB.
-   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2009-2012 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 "agent.h"
+
 #include <ctype.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/time.h>
 #include <stddef.h>
-#if HAVE_STDINT_H
 #include <stdint.h>
-#endif
+
+#include "ax.h"
 
 /* This file is built for both GDBserver, and the in-process
    agent (IPA), a shared library that includes a tracing agent that is
@@ -63,13 +65,13 @@ 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)
 
@@ -110,6 +112,9 @@ trace_vdebug (const char *fmt, ...)
 # 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 gdb_trampoline_buffer gdb_agent_gdb_trampoline_buffer
+# define gdb_trampoline_buffer_end gdb_agent_gdb_trampoline_buffer_end
+# define gdb_trampoline_buffer_error gdb_agent_gdb_trampoline_buffer_error
 # define collecting gdb_agent_collecting
 # define gdb_collect gdb_agent_gdb_collect
 # define stop_tracing gdb_agent_stop_tracing
@@ -148,6 +153,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;
@@ -171,18 +179,8 @@ struct ipa_sym_addresses
   CORE_ADDR addr_get_trace_state_variable_value;
   CORE_ADDR addr_set_trace_state_variable_value;
   CORE_ADDR addr_ust_loaded;
-  CORE_ADDR addr_helper_thread_id;
-  CORE_ADDR addr_cmd_buf;
 };
 
-#define STRINGIZE_1(STR) #STR
-#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;
@@ -192,6 +190,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),
@@ -215,43 +216,41 @@ static struct
   IPA_SYM(get_trace_state_variable_value),
   IPA_SYM(set_trace_state_variable_value),
   IPA_SYM(ust_loaded),
-  IPA_SYM(helper_thread_id),
-  IPA_SYM(cmd_buf),
 };
 
-struct ipa_sym_addresses ipa_sym_addrs;
-
-int all_tracepoint_symbols_looked_up;
-
-int
-in_process_agent_loaded (void)
-{
-  return all_tracepoint_symbols_looked_up;
-}
+static struct ipa_sym_addresses ipa_sym_addrs;
 
 static int read_inferior_integer (CORE_ADDR symaddr, int *val);
 
 /* Returns true if both the in-process agent library and the static
-   tracepoints libraries are loaded in the inferior.  */
+   tracepoints libraries are loaded in the inferior, and agent has
+   capability on static tracepoints.  */
 
 static int
-in_process_agent_loaded_ust (void)
+in_process_agent_supports_ust (void)
 {
   int loaded = 0;
 
-  if (!in_process_agent_loaded ())
+  if (!agent_loaded_p ())
     {
       warning ("In-process agent not loaded");
       return 0;
     }
 
-  if (read_inferior_integer (ipa_sym_addrs.addr_ust_loaded, &loaded))
+  if (agent_capability_check (AGENT_CAPA_STATIC_TRACE))
     {
-      warning ("Error reading ust_loaded in lib");
-      return 0;
-    }
+      /* 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;
+      return loaded;
+    }
+  else
+    return 0;
 }
 
 static void
@@ -283,7 +282,7 @@ write_e_ust_not_loaded (char *buffer)
 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;
@@ -298,12 +297,12 @@ maybe_write_ipa_not_loaded (char *buffer)
 static int
 maybe_write_ipa_ust_not_loaded (char *buffer)
 {
-  if (!in_process_agent_loaded ())
+  if (!agent_loaded_p ())
     {
       write_e_ipa_not_loaded (buffer);
       return 1;
     }
-  else if (!in_process_agent_loaded_ust ())
+  else if (!in_process_agent_supports_ust ())
     {
       write_e_ust_not_loaded (buffer);
       return 1;
@@ -322,7 +321,7 @@ tracepoint_look_up_symbols (void)
 {
   int i;
 
-  if (all_tracepoint_symbols_looked_up)
+  if (agent_loaded_p ())
     return;
 
   for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
@@ -338,7 +337,7 @@ tracepoint_look_up_symbols (void)
        }
     }
 
-  all_tracepoint_symbols_looked_up = 1;
+  agent_look_up_symbols (NULL);
 }
 
 #endif
@@ -357,8 +356,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)
 {
@@ -461,47 +458,28 @@ write_inferior_uinteger (CORE_ADDR symaddr, unsigned int val)
   return write_inferior_memory (symaddr, (unsigned char *) &val, sizeof (val));
 }
 
+static CORE_ADDR target_malloc (ULONGEST size);
+static int write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr);
 #endif
 
-/* This enum must exactly match what is documented in
-   gdb/doc/agentexpr.texi, including all the numerical values.  */
-
-enum gdb_agent_op
-  {
-#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE)  \
-    gdb_agent_op_ ## NAME = VALUE,
-#include "ax.def"
-#undef DEFOP
-    gdb_agent_op_last
-  };
-
-static const char *gdb_agent_op_names [gdb_agent_op_last] =
-  {
-    "?undef?"
-#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE)  , # NAME
-#include "ax.def"
-#undef DEFOP
-  };
+/* Operations on various types of tracepoint actions.  */
 
-static const unsigned char gdb_agent_op_sizes [gdb_agent_op_last] =
-  {
-    0
-#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE)  , SIZE
-#include "ax.def"
-#undef DEFOP
-  };
+struct tracepoint_action;
 
-struct agent_expr
+struct tracepoint_action_ops
 {
-  int length;
-
-  unsigned char *bytes;
+  /* Download tracepoint action ACTION to IPA.  Return the address of action
+     in IPA/inferior.  */
+  CORE_ADDR (*download) (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;
 };
 
@@ -537,6 +515,87 @@ 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 const struct tracepoint_action_ops m_tracepoint_action_ops =
+{
+  m_tracepoint_action_download,
+};
+
+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 const struct tracepoint_action_ops r_tracepoint_action_ops =
+{
+  r_tracepoint_action_download,
+};
+
+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;
+}
+
+static const struct tracepoint_action_ops x_tracepoint_action_ops =
+{
+  x_tracepoint_action_download,
+};
+
+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 const struct tracepoint_action_ops l_tracepoint_action_ops =
+{
+  l_tracepoint_action_download,
+};
+#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.  */
@@ -623,6 +682,9 @@ struct tracepoint
      Note that while-stepping steps are not counted as "hits".  */
   long hit_count;
 
+  /* Cached sum of the sizes of traceframes created by this point.  */
+  long traceframe_usage;
+
   CORE_ADDR compiled_cond;
 
   /* Link to the next tracepoint in the list.  */
@@ -658,6 +720,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;
@@ -720,22 +788,6 @@ IP_AGENT_EXPORT struct tracepoint *stopping_tracepoint;
 
 IP_AGENT_EXPORT int trace_buffer_is_full;
 
-/* Enumeration of the different kinds of things that can happen during
-   agent 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
-  };
-
 static enum eval_result_type expr_eval_result = expr_eval_no_error;
 
 #ifndef IN_PROCESS_AGENT
@@ -1129,6 +1181,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.  */
@@ -1198,21 +1271,11 @@ 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_mem_read_string (struct traceframe *tframe,
-                                 unsigned char *to, CORE_ADDR from,
-                                 ULONGEST len);
-static int agent_tsv_read (struct traceframe *tframe, int n);
+static enum eval_result_type
+eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx,
+                           struct traceframe *tframe,
+                           struct agent_expr *aexpr,
+                           ULONGEST *rslt);
 
 #ifndef IN_PROCESS_AGENT
 static CORE_ADDR traceframe_get_pc (struct traceframe *tframe);
@@ -1245,8 +1308,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
@@ -1259,10 +1330,6 @@ static struct tracepoint *fast_tracepoint_from_ipa_tpoint_address (CORE_ADDR);
 #define cmpxchg(mem, oldval, newval) \
   __sync_val_compare_and_swap (mem, oldval, newval)
 
-/* The size in bytes of the buffer used to talk to the IPA helper
-   thread.  */
-#define CMD_BUF_SIZE 1024
-
 /* Record that an error occurred during expression evaluation.  */
 
 static void
@@ -1543,8 +1610,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);
 
@@ -1576,8 +1644,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, "
@@ -1640,12 +1708,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;
@@ -1665,10 +1734,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;
@@ -1692,6 +1782,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
@@ -1757,6 +1869,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;
@@ -1782,6 +1895,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");
@@ -1797,6 +1911,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
            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");
@@ -1813,10 +1928,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:
@@ -1960,6 +2076,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)
 {
@@ -2199,7 +2327,7 @@ cmd_qtinit (char *packet)
 static void
 unprobe_marker_at (CORE_ADDR address)
 {
-  char cmd[CMD_BUF_SIZE];
+  char cmd[IPA_CMD_BUF_SIZE];
 
   sprintf (cmd, "unprobe_marker_at:%s", paddress (address));
   run_inferior_command (cmd);
@@ -2268,6 +2396,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;
@@ -2334,7 +2464,7 @@ cmd_qtdp (char *own_buf)
          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 == '-')
@@ -2345,12 +2475,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",
                   tpoint->type == fast_tracepoint ? "fast "
-                  : "",
+                  : tpoint->type == static_tracepoint ? "static " : "",
                   tpoint->number, paddress (tpoint->address), tpoint->enabled,
                   tpoint->step_count, tpoint->pass_count);
     }
@@ -2364,6 +2497,60 @@ 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;
+           }
+       }
+
+      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);
 }
 
@@ -2657,57 +2844,83 @@ 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))
+       {
+         fatal ("error extracting trampoline_buffer");
+         return 0;
+       }
 
-  if (tracepoints == NULL)
-    return;
+      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+                                     &trampoline_buffer_head))
+       {
+         fatal ("error extracting trampoline_buffer_end");
+         return 0;
+       }
+    }
 
-  /* 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))
+    {
+      fatal ("error extracting trampoline_buffer_end");
+      return 0;
+    }
+  
+  if (buf)
+    {
+      buf[0] = '\0';
+      strcpy (buf, "was claiming");
+      if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_error,
+                                 &errbuf))
+       {
+         fatal ("error extracting errbuf");
+         return 0;
+       }
+
+      read_inferior_memory (errbuf, (unsigned char *) buf, 100);
+    }
+
+  return trampoline_end != 0;
 }
 
 /* Ask the IPA to probe the marker at ADDRESS.  Returns -1 if running
@@ -2719,7 +2932,7 @@ sort_tracepoints (void)
 static int
 probe_marker_at (CORE_ADDR address, char *errout)
 {
-  char cmd[CMD_BUF_SIZE];
+  char cmd[IPA_CMD_BUF_SIZE];
   int err;
 
   sprintf (cmd, "probe_marker_at:%s", paddress (address));
@@ -2737,24 +2950,149 @@ probe_marker_at (CORE_ADDR address, char *errout)
   return err;
 }
 
-#define MAX_JUMP_SIZE 20
-
 static void
-cmd_qtstart (char *packet)
+clone_fast_tracepoint (struct tracepoint *to, const struct tracepoint *from)
 {
-  struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint;
-  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);
 
-  /* Sort tracepoints by ascending address.  This makes installing
-     fast tracepoints at the same address easier to handle. */
-  sort_tracepoints ();
+  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");
+
+  if (tpoint->handle == NULL)
+    {
+      if (*own_buf == '\0')
+       write_enn (own_buf);
+    }
+  else
+    write_ok (own_buf);
+}
+
+static void
+cmd_qtstart (char *packet)
+{
+  struct tracepoint *tpoint, *prev_ftpoint, *prev_stpoint;
+
+  trace_debug ("Starting the trace");
 
   /* Pause all threads temporarily while we patch tracepoints.  */
   pause_all (0);
@@ -2769,7 +3107,7 @@ cmd_qtstart (char *packet)
   pause_all (1);
 
   /* Sync the fast tracepoints list in the inferior ftlib.  */
-  if (in_process_agent_loaded ())
+  if (agent_loaded_p ())
     {
       download_tracepoints ();
       download_trace_state_variables ();
@@ -2788,6 +3126,7 @@ cmd_qtstart (char *packet)
     {
       /* Ensure all the hit counts start at zero.  */
       tpoint->hit_count = 0;
+      tpoint->traceframe_usage = 0;
 
       if (tpoint->type == trap_tracepoint)
        {
@@ -2808,55 +3147,11 @@ cmd_qtstart (char *packet)
            }
 
          if (prev_ftpoint != NULL && prev_ftpoint->address == tpoint->address)
-           {
-             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;
-           }
+           clone_fast_tracepoint (tpoint, prev_ftpoint);
          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)
-               {
-                 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);
-
-                 /* So that we can handle multiple fast tracepoints
-                    at the same address easily.  */
-                 prev_ftpoint = tpoint;
-               }
+             if (install_fast_tracepoint (tpoint, packet) == 0)
+               prev_ftpoint = tpoint;
            }
        }
       else if (tpoint->type == static_tracepoint)
@@ -2908,11 +3203,12 @@ 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");
@@ -2971,12 +3267,13 @@ stop_tracing (void)
   /* 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");
     }
 
+  tracing_stop_time = get_timestamp ();
   tracing_stop_reason = "t???";
   tracing_stop_tpnum = 0;
   if (stopping_tracepoint)
@@ -3018,7 +3315,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,
@@ -3157,11 +3454,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);
+  hexify (buf1, str, slen);
+
+  str = (tracing_notes ? tracing_notes : "");
+  slen = strlen (str);
+  buf2 = (char *) alloca (slen * 2 + 1);
+  hexify (buf2, str, slen);
+
+  str = (tracing_stop_note ? tracing_stop_note : "");
+  slen = strlen (str);
+  buf3 = (char *) alloca (slen * 2 + 1);
+  hexify (buf3, str, 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);
 
@@ -3173,7 +3490,7 @@ 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)
     {
@@ -3189,27 +3506,66 @@ cmd_qtstatus (char *packet)
       convert_int_to_ascii ((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,
           "T%d;"
           "%s:%x;"
           "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,
+          plongest (tracing_start_time), plongest (tracing_stop_time),
+          buf1, buf2);
 }
 
-/* State variables to help return all the tracepoint bits.  */
-static struct tracepoint *cur_tpoint;
-static int cur_action;
-static int cur_step_action;
-static struct source_string *cur_source_string;
-static struct trace_state_variable *cur_tsv;
+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%lx:%lx", 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 struct source_string *cur_source_string;
+static struct trace_state_variable *cur_tsv;
 
 /* Compose a response that is an imitation of the syntax by which the
    tracepoint was originally downloaded.  */
@@ -3230,7 +3586,7 @@ response_tracepoint (char *packet, struct tracepoint *tpoint)
 
   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);
@@ -3431,6 +3787,22 @@ cmd_qtstmat (char *packet)
     run_inferior_command (packet);
 }
 
+/* Return the minimum instruction size needed for fast tracepoints as a
+   hexadecimal number.  */
+
+static void
+cmd_qtminftpilen (char *packet)
+{
+  if (current_inferior == 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.  */
@@ -3486,24 +3858,75 @@ cmd_qtbuffer (char *own_buf)
 }
 
 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_qtnotes (char *own_buf)
+{
+  size_t nbytes;
+  char *saved, *user, *notes, *stopnote;
+  char *packet = own_buf;
+
+  packet += strlen ("QTNotes:");
 
-  if (strncmp ("circular:", packet, strlen ("circular:")) == 0)
+  while (*packet)
     {
-      packet += strlen ("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);
+      if (strncmp ("user:", packet, strlen ("user:")) == 0)
+       {
+         packet += strlen ("user:");
+         saved = packet;
+         packet = strchr (packet, ';');
+         nbytes = (packet - saved) / 2;
+         user = xmalloc (nbytes + 1);
+         nbytes = unhexify (user, saved, nbytes);
+         user[nbytes] = '\0';
+         ++packet; /* skip the semicolon */
+         trace_debug ("User is '%s'", user);
+         tracing_user_name = user;
+       }
+      else if (strncmp ("notes:", packet, strlen ("notes:")) == 0)
+       {
+         packet += strlen ("notes:");
+         saved = packet;
+         packet = strchr (packet, ';');
+         nbytes = (packet - saved) / 2;
+         notes = xmalloc (nbytes + 1);
+         nbytes = unhexify (notes, saved, nbytes);
+         notes[nbytes] = '\0';
+         ++packet; /* skip the semicolon */
+         trace_debug ("Notes is '%s'", notes);
+         tracing_notes = notes;
+       }
+      else if (strncmp ("tstop:", packet, strlen ("tstop:")) == 0)
+       {
+         packet += strlen ("tstop:");
+         saved = packet;
+         packet = strchr (packet, ';');
+         nbytes = (packet - saved) / 2;
+         stopnote = xmalloc (nbytes + 1);
+         nbytes = unhexify (stopnote, saved, nbytes);
+         stopnote[nbytes] = '\0';
+         ++packet; /* skip the semicolon */
+         trace_debug ("tstop note is '%s'", stopnote);
+         tracing_stop_note = stopnote;
+       }
+      else
+       break;
     }
-  else
-    write_enn (own_buf);
+
+  write_ok (own_buf);
 }
 
 int
@@ -3565,9 +3988,14 @@ handle_tracepoint_general_set (char *packet)
       cmd_qtframe (packet);
       return 1;
     }
-  else if (strncmp ("QTBuffer:", packet, strlen ("QTBuffer:")) == 0)
+  else if (strncmp ("QTBuffer:circular:", packet, strlen ("QTBuffer:circular:")) == 0)
     {
-      cmd_bigqtbuffer (packet);
+      cmd_bigqtbuffer_circular (packet);
+      return 1;
+    }
+  else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0)
+    {
+      cmd_qtnotes (packet);
       return 1;
     }
 
@@ -3582,6 +4010,11 @@ handle_tracepoint_query (char *packet)
       cmd_qtstatus (packet);
       return 1;
     }
+  else if (strncmp ("qTP:", packet, strlen ("qTP:")) == 0)
+    {
+      cmd_qtp (packet);
+      return 1;
+    }
   else if (strcmp ("qTfP", packet) == 0)
     {
       cmd_qtfp (packet);
@@ -3627,6 +4060,11 @@ handle_tracepoint_query (char *packet)
       cmd_qtstmat (packet);
       return 1;
     }
+  else if (strcmp ("qTMinFTPILen", packet) == 0)
+    {
+      cmd_qtminftpilen (packet);
+      return 1;
+    }
 
   return 0;
 }
@@ -3708,7 +4146,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
@@ -3809,7 +4247,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 ();
@@ -3903,8 +4341,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),
@@ -3944,8 +4386,6 @@ tracepoint_was_hit (struct thread_info *tinfo, CORE_ADDR stop_pc)
 #if defined IN_PROCESS_AGENT && defined HAVE_UST
 struct ust_marker_data;
 static void collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
-                                           CORE_ADDR stop_pc,
-                                           struct tracepoint *tpoint,
                                            struct traceframe *tframe);
 #endif
 
@@ -4155,7 +4595,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.  */
@@ -4171,7 +4611,7 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
 
        trace_debug ("Want to evaluate expression");
 
-       err = eval_agent_expr (ctx, tframe, eaction->expr, NULL);
+       err = eval_tracepoint_agent_expr (ctx, tframe, eaction->expr, NULL);
 
        if (err != expr_eval_no_error)
          {
@@ -4184,8 +4624,7 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
       {
 #if defined IN_PROCESS_AGENT && defined HAVE_UST
        trace_debug ("Want to collect static trace data");
-       collect_ust_data_at_tracepoint (ctx, stop_pc,
-                                       tpoint, tframe);
+       collect_ust_data_at_tracepoint (ctx, tframe);
 #else
        trace_debug ("warning: collecting static trace data, "
                     "but static tracepoints are not supported");
@@ -4224,7 +4663,7 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
     err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
   else
 #endif
-    err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
+    err = eval_tracepoint_agent_expr (ctx, NULL, tpoint->cond, &value);
 
   if (err != expr_eval_no_error)
     {
@@ -4239,463 +4678,26 @@ 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.  */
-
-static struct agent_expr *
-parse_agent_expr (char **actparm)
-{
-  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;
-}
-
-/* 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.  */
-
-static char *
-unparse_agent_expr (struct agent_expr *aexpr)
-{
-  char *rslt;
-
-  rslt = xmalloc (2 * aexpr->length + 1);
-  convert_int_to_ascii (aexpr->bytes, rslt, aexpr->length);
-  return rslt;
-}
-
-#endif
-
-/* A wrapper for gdb_agent_op_names that does some bounds-checking.  */
-
-static const char *
-gdb_agent_op_name (int op)
-{
-  if (op < 0 || op >= gdb_agent_op_last || gdb_agent_op_names[op] == NULL)
-    return "?undef?";
-  return gdb_agent_op_names[op];
-}
-
-/* The agent expression evaluator, as specified by the GDB docs. It
-   returns 0 if everything went OK, and a nonzero error code
-   otherwise.  */
+/* Evaluates a tracepoint agent expression with context CTX,
+   traceframe TFRAME, agent expression AEXPR and store the
+   result in RSLT.  */
 
 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
-    {
-      unsigned char bytes[8];
-      ULONGEST val;
-    } u64;
-  } cnv;
-
-  if (aexpr->length == 0)
-    {
-      trace_debug ("empty agent expression");
-      return expr_eval_empty_expression;
-    }
-
-  /* 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;
-
-  while (1)
-    {
-      op = aexpr->bytes[pc++];
-
-      trace_debug ("About to interpret byte 0x%x", op);
-
-      switch (op)
-       {
-       case gdb_agent_op_add:
-         top += stack[--sp];
-         break;
-
-       case gdb_agent_op_sub:
-         top = stack[--sp] - top;
-         break;
-
-       case gdb_agent_op_mul:
-         top *= stack[--sp];
-         break;
-
-       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;
-
-       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_pick:
-         arg = aexpr->bytes[pc++];
-         stack[sp] = top;
-         top = stack[sp - arg];
-         ++sp;
-         break;
-
-       case gdb_agent_op_rot:
-         {
-           ULONGEST tem = stack[sp - 1];
-
-           stack[sp - 1] = stack[sp - 2];
-           stack[sp - 2] = top;
-           top = tem;
-         }
-         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;
-
-       case gdb_agent_op_tracenz:
-         agent_mem_read_string (tframe, NULL, (CORE_ADDR) stack[--sp],
-                                (ULONGEST) top);
-         if (--sp >= 0)
-           top = stack[sp];
-         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;
-       }
+eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx,
+                           struct traceframe *tframe,
+                           struct agent_expr *aexpr,
+                           ULONGEST *rslt)
+{
+  struct regcache *regcache;
+  regcache = get_context_regcache (ctx);
 
-      trace_debug ("Op %s -> sp=%d, top=0x%s",
-                  gdb_agent_op_name (op), sp, pulongest (top));
-    }
+  return gdb_eval_agent_expr (regcache, tframe, aexpr, rslt);
 }
 
 /* Do memory copies for bytecodes.  */
 /* Do the recording of memory blocks for actions and bytecodes.  */
 
-static int
+int
 agent_mem_read (struct traceframe *tframe,
                unsigned char *to, CORE_ADDR from, ULONGEST len)
 {
@@ -4737,7 +4739,7 @@ agent_mem_read (struct traceframe *tframe,
   return 0;
 }
 
-static int
+int
 agent_mem_read_string (struct traceframe *tframe,
                       unsigned char *to, CORE_ADDR from, ULONGEST len)
 {
@@ -4799,7 +4801,7 @@ agent_mem_read_string (struct traceframe *tframe,
 
 /* Record the value of a trace state variable.  */
 
-static int
+int
 agent_tsv_read (struct traceframe *tframe, int n)
 {
   unsigned char *vspace;
@@ -5243,6 +5245,23 @@ fast_tracepoint_from_jump_pad_address (CORE_ADDR pc)
   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.  */
@@ -5305,6 +5324,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;
 
@@ -5343,6 +5364,13 @@ fast_tracepoint_collecting (CORE_ADDR thread_area,
                                  &ipa_gdb_jump_pad_buffer_end))
     fatal ("error extracting `gdb_jump_pad_buffer_end'");
 
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer,
+                                 &ipa_gdb_trampoline_buffer))
+    fatal ("error extracting `gdb_trampoline_buffer'");
+  if (read_inferior_data_pointer (ipa_sym_addrs.addr_gdb_trampoline_buffer_end,
+                                 &ipa_gdb_trampoline_buffer_end))
+    fatal ("error extracting `gdb_trampoline_buffer_end'");
+
   if (ipa_gdb_jump_pad_buffer <= stop_pc
       && stop_pc < ipa_gdb_jump_pad_buffer_end)
     {
@@ -5371,14 +5399,38 @@ fast_tracepoint_collecting (CORE_ADDR thread_area,
          && stop_pc < tpoint->adjusted_insn_addr)
        needs_breakpoint =  1;
     }
-  else
+  else if (ipa_gdb_trampoline_buffer <= stop_pc
+          && stop_pc < ipa_gdb_trampoline_buffer_end)
     {
-      collecting_t ipa_collecting_obj;
-
-      /* If `collecting' is set/locked, then the THREAD_AREA thread
-        may or not be the one holding the lock.  We have to read the
-        lock to find out.  */
-
+      /* 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;
+
+      /* If `collecting' is set/locked, then the THREAD_AREA thread
+        may or not be the one holding the lock.  We have to read the
+        lock to find out.  */
+
       if (read_inferior_data_pointer (ipa_sym_addrs.addr_collecting,
                                      &ipa_collecting))
        {
@@ -5480,14 +5532,9 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
   if (!tracing)
     return;
 
-  if (!tpoint->enabled)
-    return;
-
   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 ());
@@ -5497,30 +5544,49 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
       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;
+           }
+       }
     }
 }
 
@@ -5528,250 +5594,24 @@ 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)
-{
-  target_emit_ops ()->emit_prologue ();
-}
-
-static void
-emit_epilogue (void)
-{
-  target_emit_ops ()->emit_epilogue ();
-}
-
-static void
-emit_add (void)
-{
-  target_emit_ops ()->emit_add ();
-}
-
-static void
-emit_sub (void)
-{
-  target_emit_ops ()->emit_sub ();
-}
-
-static void
-emit_mul (void)
-{
-  target_emit_ops ()->emit_mul ();
-}
-
-static void
-emit_lsh (void)
-{
-  target_emit_ops ()->emit_lsh ();
-}
-
-static void
-emit_rsh_signed (void)
-{
-  target_emit_ops ()->emit_rsh_signed ();
-}
-
-static void
-emit_rsh_unsigned (void)
-{
-  target_emit_ops ()->emit_rsh_unsigned ();
-}
-
-static void
-emit_ext (int arg)
-{
-  target_emit_ops ()->emit_ext (arg);
-}
-
-static void
-emit_log_not (void)
-{
-  target_emit_ops ()->emit_log_not ();
-}
-
-static void
-emit_bit_and (void)
-{
-  target_emit_ops ()->emit_bit_and ();
-}
-
-static void
-emit_bit_or (void)
-{
-  target_emit_ops ()->emit_bit_or ();
-}
-
-static void
-emit_bit_xor (void)
-{
-  target_emit_ops ()->emit_bit_xor ();
-}
-
-static void
-emit_bit_not (void)
-{
-  target_emit_ops ()->emit_bit_not ();
-}
-
-static void
-emit_equal (void)
-{
-  target_emit_ops ()->emit_equal ();
-}
-
-static void
-emit_less_signed (void)
-{
-  target_emit_ops ()->emit_less_signed ();
-}
-
-static void
-emit_less_unsigned (void)
-{
-  target_emit_ops ()->emit_less_unsigned ();
-}
-
-static void
-emit_ref (int size)
-{
-  target_emit_ops ()->emit_ref (size);
-}
-
-static void
-emit_if_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_if_goto (offset_p, size_p);
-}
-
-static void
-emit_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_goto (offset_p, size_p);
-}
-
-static void
-write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
-{
-  target_emit_ops ()->write_goto_address (from, to, size);
-}
-
-static void
-emit_const (LONGEST num)
-{
-  target_emit_ops ()->emit_const (num);
-}
-
-static void
-emit_reg (int reg)
-{
-  target_emit_ops ()->emit_reg (reg);
-}
-
-static void
-emit_pop (void)
-{
-  target_emit_ops ()->emit_pop ();
-}
-
-static void
-emit_stack_flush (void)
-{
-  target_emit_ops ()->emit_stack_flush ();
-}
-
-static void
-emit_zero_ext (int arg)
-{
-  target_emit_ops ()->emit_zero_ext (arg);
-}
-
-static void
-emit_swap (void)
-{
-  target_emit_ops ()->emit_swap ();
-}
-
-static void
-emit_stack_adjust (int n)
-{
-  target_emit_ops ()->emit_stack_adjust (n);
-}
-
-/* FN's prototype is `LONGEST(*fn)(int)'.  */
-
-static void
-emit_int_call_1 (CORE_ADDR fn, int arg1)
-{
-  target_emit_ops ()->emit_int_call_1 (fn, arg1);
-}
-
-/* FN's prototype is `void(*fn)(int,LONGEST)'.  */
-
-static void
-emit_void_call_2 (CORE_ADDR fn, int arg1)
-{
-  target_emit_ops ()->emit_void_call_2 (fn, arg1);
-}
-
-static void
-emit_eq_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_eq_goto (offset_p, size_p);
-}
-
-static void
-emit_ne_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_ne_goto (offset_p, size_p);
-}
-
-static void
-emit_lt_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_lt_goto (offset_p, size_p);
-}
-
-static void
-emit_ge_goto (int *offset_p, int *size_p)
-{
-  target_emit_ops ()->emit_ge_goto (offset_p, size_p);
-}
-
-static void
-emit_gt_goto (int *offset_p, int *size_p)
+CORE_ADDR
+get_get_tsv_func_addr (void)
 {
-  target_emit_ops ()->emit_gt_goto (offset_p, size_p);
+  return ipa_sym_addrs.addr_get_trace_state_variable_value;
 }
 
-static void
-emit_le_goto (int *offset_p, int *size_p)
+CORE_ADDR
+get_set_tsv_func_addr (void)
 {
-  target_emit_ops ()->emit_le_goto (offset_p, size_p);
+  return ipa_sym_addrs.addr_set_trace_state_variable_value;
 }
 
-static enum eval_result_type compile_bytecodes (struct agent_expr *aexpr);
-
 static void
 compile_tracepoint_condition (struct tracepoint *tpoint,
                              CORE_ADDR *jump_entry)
@@ -5812,441 +5652,11 @@ compile_tracepoint_condition (struct tracepoint *tpoint,
 
   /* 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;
-
-  /* Leave a gap, to aid dump decipherment.  */
-  *jump_entry += 16;
-}
-
-/* Scan an agent expression for any evidence that the given PC is the
-   target of a jump bytecode in the expression.  */
-
-int
-is_goto_target (struct agent_expr *aexpr, int pc)
-{
-  int i;
-  unsigned char op;
-
-  for (i = 0; i < aexpr->length; i += 1 + gdb_agent_op_sizes[op])
-    {
-      op = aexpr->bytes[i];
-
-      if (op == gdb_agent_op_goto || op == gdb_agent_op_if_goto)
-       {
-         int target = (aexpr->bytes[i + 1] << 8) + aexpr->bytes[i + 2];
-         if (target == pc)
-           return 1;
-       }
-    }
-
-  return 0;
-}
-
-/* Given an agent expression, turn it into native code.  */
-
-static enum eval_result_type
-compile_bytecodes (struct agent_expr *aexpr)
-{
-  int pc = 0;
-  int done = 0;
-  unsigned char op, next_op;
-  int arg;
-  /* This is only used to build 64-bit value for constants.  */
-  ULONGEST top;
-  struct bytecode_address *aentry, *aentry2;
-
-#define UNHANDLED                                      \
-  do                                                   \
-    {                                                  \
-      trace_debug ("Cannot compile op 0x%x\n", op);    \
-      return expr_eval_unhandled_opcode;               \
-    } while (0)
-
-  if (aexpr->length == 0)
-    {
-      trace_debug ("empty agent expression\n");
-      return expr_eval_empty_expression;
-    }
-
-  bytecode_address_table = NULL;
-
-  while (!done)
-    {
-      op = aexpr->bytes[pc];
-
-      trace_debug ("About to compile op 0x%x, pc=%d\n", op, pc);
-
-      /* 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;
-
-      ++pc;
-
-      emit_error = 0;
-
-      switch (op)
-       {
-       case gdb_agent_op_add:
-         emit_add ();
-         break;
-
-       case gdb_agent_op_sub:
-         emit_sub ();
-         break;
-
-       case gdb_agent_op_mul:
-         emit_mul ();
-         break;
-
-       case gdb_agent_op_div_signed:
-         UNHANDLED;
-         break;
-
-       case gdb_agent_op_div_unsigned:
-         UNHANDLED;
-         break;
-
-       case gdb_agent_op_rem_signed:
-         UNHANDLED;
-         break;
-
-       case gdb_agent_op_rem_unsigned:
-         UNHANDLED;
-         break;
-
-       case gdb_agent_op_lsh:
-         emit_lsh ();
-         break;
-
-       case gdb_agent_op_rsh_signed:
-         emit_rsh_signed ();
-         break;
-
-       case gdb_agent_op_rsh_unsigned:
-         emit_rsh_unsigned ();
-         break;
-
-       case gdb_agent_op_trace:
-         UNHANDLED;
-         break;
-
-       case gdb_agent_op_trace_quick:
-         UNHANDLED;
-         break;
-
-       case gdb_agent_op_log_not:
-         emit_log_not ();
-         break;
-
-       case gdb_agent_op_bit_and:
-         emit_bit_and ();
-         break;
-
-       case gdb_agent_op_bit_or:
-         emit_bit_or ();
-         break;
-
-       case gdb_agent_op_bit_xor:
-         emit_bit_xor ();
-         break;
-
-       case gdb_agent_op_bit_not:
-         emit_bit_not ();
-         break;
-
-       case gdb_agent_op_equal:
-         next_op = aexpr->bytes[pc];
-         if (next_op == gdb_agent_op_if_goto
-             && !is_goto_target (aexpr, pc)
-             && target_emit_ops ()->emit_eq_goto)
-           {
-             trace_debug ("Combining equal & if_goto");
-             pc += 1;
-             aentry->pc = pc;
-             arg = aexpr->bytes[pc++];
-             arg = (arg << 8) + aexpr->bytes[pc++];
-             aentry->goto_pc = arg;
-             emit_eq_goto (&(aentry->from_offset), &(aentry->from_size));
-           }
-         else if (next_op == gdb_agent_op_log_not
-                  && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto)
-                  && !is_goto_target (aexpr, pc + 1)
-                  && target_emit_ops ()->emit_ne_goto)
-           {
-             trace_debug ("Combining equal & log_not & if_goto");
-             pc += 2;
-             aentry->pc = pc;
-             arg = aexpr->bytes[pc++];
-             arg = (arg << 8) + aexpr->bytes[pc++];
-             aentry->goto_pc = arg;
-             emit_ne_goto (&(aentry->from_offset), &(aentry->from_size));
-           }
-         else
-           emit_equal ();
-         break;
-
-       case gdb_agent_op_less_signed:
-         next_op = aexpr->bytes[pc];
-         if (next_op == gdb_agent_op_if_goto
-             && !is_goto_target (aexpr, pc))
-           {
-             trace_debug ("Combining less_signed & if_goto");
-             pc += 1;
-             aentry->pc = pc;
-             arg = aexpr->bytes[pc++];
-             arg = (arg << 8) + aexpr->bytes[pc++];
-             aentry->goto_pc = arg;
-             emit_lt_goto (&(aentry->from_offset), &(aentry->from_size));
-           }
-         else if (next_op == gdb_agent_op_log_not
-                  && !is_goto_target (aexpr, pc)
-                  && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto)
-                  && !is_goto_target (aexpr, pc + 1))
-           {
-             trace_debug ("Combining less_signed & log_not & if_goto");
-             pc += 2;
-             aentry->pc = pc;
-             arg = aexpr->bytes[pc++];
-             arg = (arg << 8) + aexpr->bytes[pc++];
-             aentry->goto_pc = arg;
-             emit_ge_goto (&(aentry->from_offset), &(aentry->from_size));
-           }
-         else
-           emit_less_signed ();
-         break;
-
-       case gdb_agent_op_less_unsigned:
-         emit_less_unsigned ();
-         break;
-
-       case gdb_agent_op_ext:
-         arg = aexpr->bytes[pc++];
-         if (arg < (sizeof (LONGEST) * 8))
-           emit_ext (arg);
-         break;
-
-       case gdb_agent_op_ref8:
-         emit_ref (1);
-         break;
-
-       case gdb_agent_op_ref16:
-         emit_ref (2);
-         break;
-
-       case gdb_agent_op_ref32:
-         emit_ref (4);
-         break;
-
-       case gdb_agent_op_ref64:
-         emit_ref (8);
-         break;
-
-       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;
-
-       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;
-
-       case gdb_agent_op_const8:
-         emit_stack_flush ();
-         top = aexpr->bytes[pc++];
-         emit_const (top);
-         break;
-
-       case gdb_agent_op_const16:
-         emit_stack_flush ();
-         top = aexpr->bytes[pc++];
-         top = (top << 8) + aexpr->bytes[pc++];
-         emit_const (top);
-         break;
-
-       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;
-
-       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;
-
-       case gdb_agent_op_reg:
-         emit_stack_flush ();
-         arg = aexpr->bytes[pc++];
-         arg = (arg << 8) + aexpr->bytes[pc++];
-         emit_reg (arg);
-         break;
-
-       case gdb_agent_op_end:
-         trace_debug ("At end of expression\n");
-
-         /* 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);
-
-         done = 1;
-         break;
-
-       case gdb_agent_op_dup:
-         /* In our design, dup is equivalent to stack flushing.  */
-         emit_stack_flush ();
-         break;
-
-       case gdb_agent_op_pop:
-         emit_pop ();
-         break;
-
-       case gdb_agent_op_zero_ext:
-         arg = aexpr->bytes[pc++];
-         if (arg < (sizeof (LONGEST) * 8))
-           emit_zero_ext (arg);
-         break;
-
-       case gdb_agent_op_swap:
-         next_op = aexpr->bytes[pc];
-         /* Detect greater-than comparison sequences.  */
-         if (next_op == gdb_agent_op_less_signed
-             && !is_goto_target (aexpr, pc)
-             && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto)
-             && !is_goto_target (aexpr, pc + 1))
-           {
-             trace_debug ("Combining swap & less_signed & if_goto");
-             pc += 2;
-             aentry->pc = pc;
-             arg = aexpr->bytes[pc++];
-             arg = (arg << 8) + aexpr->bytes[pc++];
-             aentry->goto_pc = arg;
-             emit_gt_goto (&(aentry->from_offset), &(aentry->from_size));
-           }
-         else if (next_op == gdb_agent_op_less_signed
-                  && !is_goto_target (aexpr, pc)
-                  && (aexpr->bytes[pc + 1] == gdb_agent_op_log_not)
-                  && !is_goto_target (aexpr, pc + 1)
-                  && (aexpr->bytes[pc + 2] == gdb_agent_op_if_goto)
-                  && !is_goto_target (aexpr, pc + 2))
-           {
-             trace_debug ("Combining swap & less_signed & log_not & if_goto");
-             pc += 3;
-             aentry->pc = pc;
-             arg = aexpr->bytes[pc++];
-             arg = (arg << 8) + aexpr->bytes[pc++];
-             aentry->goto_pc = arg;
-             emit_le_goto (&(aentry->from_offset), &(aentry->from_size));
-           }
-         else
-           emit_swap ();
-         break;
-
-       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;
-
-       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;
-
-       case gdb_agent_op_tracev:
-         UNHANDLED;
-         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:
-         UNHANDLED;
-         break;
-
-       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;
-       }
-
-      /* This catches errors that occur in target-specific code
-        emission.  */
-      if (emit_error)
-       {
-         trace_debug ("Error %d while emitting code for %s\n",
-                      emit_error, gdb_agent_op_name (op));
-         return expr_eval_unhandled_opcode;
-       }
-
-      trace_debug ("Op %s compiled\n", gdb_agent_op_name (op));
-    }
-
-  /* Now fill in real addresses as goto destinations.  */
-  for (aentry = bytecode_address_table; aentry; aentry = aentry->next)
-    {
-      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;
-           }
-       }
-
-      /* 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;
-       }
-    }
+     instead of letting them be overwritten.  */
+  *jump_entry = current_insn_ptr;
 
-  return expr_eval_no_error;
+  /* Leave a gap, to aid dump decipherment.  */
+  *jump_entry += 16;
 }
 
 /* We'll need to adjust these when we consider bi-arch setups, and big
@@ -6311,6 +5721,132 @@ download_agent_expr (struct agent_expr *expr)
 /* 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
+download_tracepoint_1 (struct tracepoint *tpoint)
+{
+  struct tracepoint target_tracepoint;
+  CORE_ADDR tpptr = 0;
+
+  gdb_assert (tpoint->type == fast_tracepoint
+             || tpoint->type == static_tracepoint);
+
+  if (tpoint->cond != NULL && target_emit_ops () != NULL)
+    {
+      CORE_ADDR jentry, jump_entry;
+
+      jentry = jump_entry = get_jump_space_head ();
+
+      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);
+       }
+
+      /* Pad to 8-byte alignment.  */
+      jentry = UALIGN (jentry, 8);
+      claim_jump_space (jentry - jump_entry);
+    }
+
+  target_tracepoint = *tpoint;
+
+  tpptr = target_malloc (sizeof (*tpoint));
+  tpoint->obj_addr_on_target = tpptr;
+
+  /* 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++)
+       {
+         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 (sizeof (*tpoint->actions)),
+              ipa_action);
+       }
+    }
+}
+
+static void
+download_tracepoint (struct tracepoint *tpoint)
+{
+  struct tracepoint *tp, *tp_prev;
+
+  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 (tp_prev)
+    {
+      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))
+       fatal ("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_tracepoints (void)
 {
@@ -6322,39 +5858,15 @@ download_tracepoints (void)
 
   for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
     {
-      struct tracepoint target_tracepoint;
-
       if (tpoint->type != fast_tracepoint
          && tpoint->type != static_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 ();
-
-         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);
-           }
-
-         /* Pad to 8-byte alignment.  */
-         jentry = UALIGN (jentry, 8);
-         claim_jump_space (jentry - jump_entry);
-       }
+      prev_tpptr = tpptr;
 
-      target_tracepoint = *tpoint;
+      download_tracepoint_1 (tpoint);
 
-      prev_tpptr = tpptr;
-      tpptr = target_malloc (sizeof (*tpoint));
-      tpoint->obj_addr_on_target = tpptr;
+      tpptr = tpoint->obj_addr_on_target;
 
       if (tpoint == tracepoints)
        {
@@ -6368,94 +5880,6 @@ download_tracepoints (void)
                                                          next),
                                   tpptr);
        }
-
-      /* 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];
-
-             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;
-                 }
-               case 'L':
-                 ipa_action = target_malloc
-                   (sizeof (struct collect_static_trace_data_action));
-                 write_inferior_memory
-                   (ipa_action,
-                    (unsigned char *) action,
-                    sizeof (struct collect_static_trace_data_action));
-                 break;
-               default:
-                 trace_debug ("unknown trace action '%c', ignoring",
-                              action->type);
-                 break;
-               }
-
-             if (ipa_action != 0)
-               write_inferior_data_ptr
-                 (actions_array + i * sizeof (sizeof (*tpoint->actions)),
-                  ipa_action);
-           }
-       }
     }
 }
 
@@ -6591,10 +6015,10 @@ upload_fast_traceframes (void)
 
     /* 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;
+    prev = ipa_trace_buffer_ctrl_curr & GDBSERVER_FLUSH_COUNT_MASK_CURR;
+    counter = (prev + 0x100) & GDBSERVER_FLUSH_COUNT_MASK_CURR;
 
-    ipa_trace_buffer_ctrl_curr = (0x80000000
+    ipa_trace_buffer_ctrl_curr = (GDBSERVER_UPDATED_FLUSH_COUNT_BIT
                                  | (prev << 12)
                                  | counter
                                  | curr_tbctrl_idx);
@@ -6795,7 +6219,7 @@ upload_fast_traceframes (void)
 #ifdef IN_PROCESS_AGENT
 
 IP_AGENT_EXPORT int ust_loaded;
-IP_AGENT_EXPORT char cmd_buf[CMD_BUF_SIZE];
+IP_AGENT_EXPORT char cmd_buf[IPA_CMD_BUF_SIZE];
 
 #ifdef HAVE_UST
 
@@ -6988,8 +6412,6 @@ gdb_probe (const struct marker *mdata, void *probe_private,
 
 static void
 collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
-                               CORE_ADDR stop_pc,
-                               struct tracepoint *tpoint,
                                struct traceframe *tframe)
 {
   struct static_tracepoint_ctx *umd = (struct static_tracepoint_ctx *) ctx;
@@ -7046,94 +6468,8 @@ static struct ltt_available_probe gdb_ust_probe =
 #endif /* HAVE_UST */
 #endif /* IN_PROCESS_AGENT */
 
-#ifdef HAVE_UST
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#ifndef UNIX_PATH_MAX
-#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
-#endif
-
-/* Where we put the socked used for synchronization.  */
-#define SOCK_DIR P_tmpdir
-
-#endif /* HAVE_UST */
-
 #ifndef IN_PROCESS_AGENT
 
-#ifdef HAVE_UST
-
-static int
-gdb_ust_connect_sync_socket (int pid)
-{
-  struct sockaddr_un addr;
-  int res, fd;
-  char path[UNIX_PATH_MAX];
-
-  res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", SOCK_DIR, pid);
-  if (res >= UNIX_PATH_MAX)
-    {
-      trace_debug ("string overflow allocating socket name");
-      return -1;
-    }
-
-  res = fd = socket (PF_UNIX, SOCK_STREAM, 0);
-  if (res == -1)
-    {
-      warning ("error opening sync socket: %s\n", strerror (errno));
-      return -1;
-    }
-
-  addr.sun_family = AF_UNIX;
-
-  res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
-  if (res >= UNIX_PATH_MAX)
-    {
-      warning ("string overflow allocating socket name\n");
-      close (fd);
-      return -1;
-    }
-
-  res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
-  if (res == -1)
-    {
-      warning ("error connecting sync socket (%s): %s. "
-              "Make sure the directory exists and that it is writable.",
-              path, strerror (errno));
-      close (fd);
-      return -1;
-    }
-
-  return fd;
-}
-
-/* Resume thread PTID.  */
-
-static void
-resume_thread (ptid_t ptid)
-{
-  struct thread_resume resume_info;
-
-  resume_info.thread = ptid;
-  resume_info.kind = resume_continue;
-  resume_info.sig = TARGET_SIGNAL_0;
-  (*the_target->resume) (&resume_info, 1);
-}
-
-/* Stop thread PTID.  */
-
-static void
-stop_thread (ptid_t ptid)
-{
-  struct thread_resume resume_info;
-
-  resume_info.thread = ptid;
-  resume_info.kind = resume_stop;
-  resume_info.sig = TARGET_SIGNAL_0;
-  (*the_target->resume) (&resume_info, 1);
-}
-
 /* Ask the in-process agent to run a command.  Since we don't want to
    have to handle the IPA hitting breakpoints while running the
    command, we pause all threads, remove all breakpoints, and then set
@@ -7145,91 +6481,14 @@ static int
 run_inferior_command (char *cmd)
 {
   int err = -1;
-  int fd = -1;
   int pid = ptid_get_pid (current_inferior->entry.id);
-  int tid;
-  ptid_t ptid = null_ptid;
 
   trace_debug ("run_inferior_command: running: %s", cmd);
 
   pause_all (0);
   uninsert_all_breakpoints ();
 
-  if (read_inferior_integer (ipa_sym_addrs.addr_helper_thread_id, &tid))
-    {
-      warning ("Error reading helper thread's id in lib");
-      goto out;
-    }
-
-  if (tid == 0)
-    {
-      warning ("helper thread not initialized yet");
-      goto out;
-    }
-
-  if (write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
-                            (unsigned char *) cmd, strlen (cmd) + 1))
-    {
-      warning ("Error writing command");
-      goto out;
-    }
-
-  ptid = ptid_build (pid, tid, 0);
-
-  resume_thread (ptid);
-
-  fd = gdb_ust_connect_sync_socket (pid);
-  if (fd >= 0)
-    {
-      char buf[1] = "";
-      int ret;
-
-      trace_debug ("signalling helper thread");
-
-      do
-       {
-         ret = write (fd, buf, 1);
-       } while (ret == -1 && errno == EINTR);
-
-      trace_debug ("waiting for helper thread's response");
-
-      do
-       {
-         ret = read (fd, buf, 1);
-       } while (ret == -1 && errno == EINTR);
-
-      close (fd);
-
-      trace_debug ("helper thread's response received");
-    }
-
- out:
-
-  /* Need to read response with the inferior stopped.  */
-  if (!ptid_equal (ptid, null_ptid))
-    {
-      int was_non_stop = non_stop;
-      struct target_waitstatus status;
-
-      stop_thread (ptid);
-      non_stop = 1;
-      mywait (ptid, &status, 0, 0);
-      non_stop = was_non_stop;
-    }
-
-  if (fd >= 0)
-    {
-      if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
-                               (unsigned char *) cmd, CMD_BUF_SIZE))
-       {
-         warning ("Error reading command response");
-       }
-      else
-       {
-         err = 0;
-         trace_debug ("run_inferior_command: response: %s", cmd);
-       }
-    }
+  err = agent_run_command (pid, (const char *) cmd);
 
   reinsert_all_breakpoints ();
   unpause_all (0);
@@ -7237,24 +6496,22 @@ run_inferior_command (char *cmd)
   return err;
 }
 
-#else /* HAVE_UST */
+#else /* !IN_PROCESS_AGENT */
 
-static int
-run_inferior_command (char *cmd)
-{
-  return -1;
-}
+#include <sys/socket.h>
+#include <sys/un.h>
 
-#endif /* HAVE_UST */
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
+#endif
 
-#else /* !IN_PROCESS_AGENT */
+/* Where we put the socked used for synchronization.  */
+#define SOCK_DIR P_tmpdir
 
 /* Thread ID of the helper thread.  GDBserver reads this to know which
    is the help thread.  This is an LWP id on Linux.  */
 int helper_thread_id;
 
-#ifdef HAVE_UST
-
 static int
 init_named_socket (const char *name)
 {
@@ -7307,7 +6564,7 @@ init_named_socket (const char *name)
 }
 
 static int
-gdb_ust_socket_init (void)
+gdb_agent_socket_init (void)
 {
   int result, fd;
   char name[UNIX_PATH_MAX];
@@ -7329,17 +6586,7 @@ gdb_ust_socket_init (void)
   return fd;
 }
 
-/* Return an hexstr version of the STR C string, fit for sending to
-   GDB.  */
-
-static char *
-cstr_to_hexstr (const char *str)
-{
-  int len = strlen (str);
-  char *hexstr = xmalloc (len * 2 + 1);
-  convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
-  return hexstr;
-}
+#ifdef HAVE_UST
 
 /* The next marker to be returned on a qTsSTM command.  */
 static const struct marker *next_st;
@@ -7379,6 +6626,18 @@ next_marker (const struct marker *m)
   return NULL;
 }
 
+/* Return an hexstr version of the STR C string, fit for sending to
+   GDB.  */
+
+static char *
+cstr_to_hexstr (const char *str)
+{
+  int len = strlen (str);
+  char *hexstr = xmalloc (len * 2 + 1);
+  convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
+  return hexstr;
+}
+
 /* Compose packet that is the response to the qTsSTM/qTfSTM/qTSTMat
    packets.  */
 
@@ -7539,19 +6798,32 @@ cmd_qtstmat (char *packet)
   return -1;
 }
 
+static void
+gdb_ust_init (void)
+{
+  if (!dlsym_ust ())
+    return;
+
+  USTF(ltt_probe_register) (&gdb_ust_probe);
+}
+
+#endif /* HAVE_UST */
+
+#include <sys/syscall.h>
+
+/* Helper thread of agent.  */
+
 static void *
-gdb_ust_thread (void *arg)
+gdb_agent_helper_thread (void *arg)
 {
   int listen_fd;
 
   while (1)
     {
-      listen_fd = gdb_ust_socket_init ();
+      listen_fd = gdb_agent_socket_init ();
 
-#ifdef SYS_gettid
       if (helper_thread_id == 0)
        helper_thread_id = syscall (SYS_gettid);
-#endif
 
       if (listen_fd == -1)
        {
@@ -7598,6 +6870,7 @@ gdb_ust_thread (void *arg)
 
          if (cmd_buf[0])
            {
+#ifdef HAVE_UST
              if (strcmp ("qTfSTM", cmd_buf) == 0)
                {
                  cmd_qtfstm (cmd_buf);
@@ -7624,15 +6897,11 @@ gdb_ust_thread (void *arg)
                {
                  cmd_qtstmat (cmd_buf);
                }
-             else if (strcmp (cmd_buf, "help") == 0)
-               {
-                 strcpy (cmd_buf, "for help, press F1\n");
-               }
-             else
-               strcpy (cmd_buf, "");
+#endif /* HAVE_UST */
            }
 
-         write (fd, buf, 1);
+         /* Fix compiler's warning: ignoring return value of 'write'.  */
+         ret = write (fd, buf, 1);
          close (fd);
        }
     }
@@ -7641,18 +6910,18 @@ gdb_ust_thread (void *arg)
 }
 
 #include <signal.h>
+#include <pthread.h>
+
+IP_AGENT_EXPORT int gdb_agent_capability = AGENT_CAPA_STATIC_TRACE;
 
 static void
-gdb_ust_init (void)
+gdb_agent_init (void)
 {
   int res;
   pthread_t thread;
   sigset_t new_mask;
   sigset_t orig_mask;
 
-  if (!dlsym_ust ())
-    return;
-
   /* We want the helper thread to be as transparent as possible, so
      have it inherit an all-signals-blocked mask.  */
 
@@ -7663,7 +6932,7 @@ gdb_ust_init (void)
 
   res = pthread_create (&thread,
                        NULL,
-                       gdb_ust_thread,
+                       gdb_agent_helper_thread,
                        NULL);
 
   res = pthread_sigmask (SIG_SETMASK, &orig_mask, NULL);
@@ -7673,32 +6942,52 @@ gdb_ust_init (void)
   while (helper_thread_id == 0)
     usleep (1);
 
-  USTF(ltt_probe_register) (&gdb_ust_probe);
+#ifdef HAVE_UST
+  gdb_ust_init ();
+#endif
 }
 
-#endif /* HAVE_UST */
-
 #include <sys/mman.h>
 #include <fcntl.h>
 
 IP_AGENT_EXPORT char *gdb_tp_heap_buffer;
 IP_AGENT_EXPORT char *gdb_jump_pad_buffer;
 IP_AGENT_EXPORT char *gdb_jump_pad_buffer_end;
+IP_AGENT_EXPORT char *gdb_trampoline_buffer;
+IP_AGENT_EXPORT char *gdb_trampoline_buffer_end;
+IP_AGENT_EXPORT 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 ();
 
-#ifdef HAVE_UST
-  gdb_ust_init ();
-#endif
+  gdb_agent_init ();
 }
 
 #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;
 
@@ -7722,29 +7011,51 @@ 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");
 
     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)
+    /* 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)
       fatal ("\
-initialize_tracepoint: mprotect(%p, %d, PROT_READ|PROT_EXEC) failed with %s",
-            gdb_jump_pad_buffer, pagesize * 20, strerror (errno));
+initialize_tracepoint: mmap'ing jump pad buffer failed with %s",
+            strerror (errno));
+
+    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.063985 seconds and 4 git commands to generate.