Use memmove to copy overlap memory.
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
index fc364f35e0202b265ac97f9fdc4bff6d58728a3f..ae0e040e53cf7433bdf94021656a922da12f6668 100644 (file)
@@ -202,9 +202,6 @@ char *stop_reason_names[] = {
 struct trace_status *
 current_trace_status ()
 {
-  /* Ensure this is never NULL.  */
-  if (!trace_status.error_desc)
-    trace_status.error_desc = "";
   return &trace_status;
 }
 
@@ -925,10 +922,11 @@ collect_symbol (struct collection_list *collect,
        }
       add_memrange (collect, reg, offset, len);
       break;
+
     case LOC_UNRESOLVED:
-      printf_filtered ("Don't know LOC_UNRESOLVED %s\n", 
-                      SYMBOL_PRINT_NAME (sym));
+      treat_as_expr = 1;
       break;
+
     case LOC_OPTIMIZED_OUT:
       printf_filtered ("%s has been optimized out of existence.\n",
                       SYMBOL_PRINT_NAME (sym));
@@ -1452,24 +1450,43 @@ start_tracing (void)
   int ix;
   struct breakpoint *t;
   struct trace_state_variable *tsv;
-  int any_downloaded = 0;
-
-  target_trace_init ();
+  int any_enabled = 0;
   
   tp_vec = all_tracepoints ();
+
+  /* No point in tracing without any tracepoints... */
+  if (VEC_length (breakpoint_p, tp_vec) == 0)
+    {
+      VEC_free (breakpoint_p, tp_vec);
+      error (_("No tracepoints defined, not starting trace"));
+    }
+
+  for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
+    {
+      if (t->enable_state == bp_enabled)
+       {
+         any_enabled = 1;
+         break;
+       }
+    }
+
+  /* No point in tracing with only disabled tracepoints.  */
+  if (!any_enabled)
+    {
+      VEC_free (breakpoint_p, tp_vec);
+      error (_("No tracepoints enabled, not starting trace"));
+    }
+
+  target_trace_init ();
+
   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
     {
       t->number_on_target = 0;
       target_download_tracepoint (t);
       t->number_on_target = t->number;
-      any_downloaded = 1;
     }
   VEC_free (breakpoint_p, tp_vec);
-  
-  /* No point in tracing without any tracepoints... */
-  if (!any_downloaded)
-    error ("No tracepoints downloaded, not starting trace");
-  
+
   /* Send down all the trace state variables too.  */
   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
     {
@@ -1748,6 +1765,13 @@ disconnect_or_stop_tracing (int from_tty)
       if (!cont)
        stop_tracing ();
     }
+
+  /* Also we want to be out of tfind mode, otherwise things can get
+     confusing upon reconnection.  Just use these calls instead of
+     full tfind_1 behavior because we're in the middle of detaching,
+     and there's no point to updating current stack frame etc.  */
+  set_traceframe_number (-1);
+  set_traceframe_context (NULL);
 }
 
 /* Worker function for the various flavors of the tfind command.  */
@@ -2019,33 +2043,16 @@ trace_find_line_command (char *args, int from_tty)
       sals.sals[0] = sal;
     }
   else
-      {
+    {
       sals = decode_line_spec (args, 1);
       sal = sals.sals[0];
     }
   
   old_chain = make_cleanup (xfree, sals.sals);
   if (sal.symtab == 0)
-    {
-      printf_filtered ("TFIND: No line number information available");
-      if (sal.pc != 0)
-       {
-         /* This is useful for "info line *0x7f34".  If we can't
-            tell the user about a source line, at least let them
-            have the symbolic address.  */
-         printf_filtered (" for address ");
-         wrap_here ("  ");
-         print_address (get_current_arch (), sal.pc, gdb_stdout);
-         printf_filtered (";\n -- will attempt to find by PC. \n");
-       }
-        else
-       {
-         printf_filtered (".\n");
-         return;               /* No line, no PC; what can we do?  */
-       }
-    }
-  else if (sal.line > 0
-          && find_line_pc_range (sal, &start_pc, &end_pc))
+    error (_("No line number information available."));
+
+  if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc))
     {
       if (start_pc == end_pc)
        {
@@ -2422,6 +2429,25 @@ trace_dump_command (char *args, int from_tty)
   discard_cleanups (old_cleanups);
 }
 
+/* Encode a piece of a tracepoint's source-level definition in a form
+   that is suitable for both protocol and saving in files.  */
+/* This version does not do multiple encodes for long strings; it should
+   return an offset to the next piece to encode.  FIXME  */
+
+extern int
+encode_source_string (int tpnum, ULONGEST addr,
+                     char *srctype, char *src, char *buf, int buf_size)
+{
+  if (80 + strlen (srctype) > buf_size)
+    error (_("Buffer too small for source encoding"));
+  sprintf (buf, "%x:%s:%s:%x:%x:",
+          tpnum, phex_nz (addr, sizeof (addr)), srctype, 0, (int) strlen (src));
+  if (strlen (buf) + strlen (src) * 2 >= buf_size)
+    error (_("Source string too long for buffer"));
+  bin2hex (src, buf + strlen (buf), 0);
+  return -1;
+}
+
 extern int trace_regblock_size;
 
 /* Save tracepoint data to file named FILENAME.  If TARGET_DOES_SAVE is
@@ -2439,6 +2465,7 @@ trace_save (const char *filename, int target_does_save)
   struct uploaded_tp *uploaded_tps = NULL, *utp;
   struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
   int a;
+  struct uploaded_string *cmd;
   LONGEST gotten = 0;
   ULONGEST offset = 0;
 #define MAX_TRACE_UPLOAD 2000
@@ -2473,7 +2500,7 @@ trace_save (const char *filename, int target_does_save)
      binary file, plus a hint as what this file is, and a version
      number in case of future needs.  */
   written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
-  if (written < 8)
+  if (written < 1)
     perror_with_name (pathname);
 
   /* Write descriptive info.  */
@@ -2484,12 +2511,11 @@ trace_save (const char *filename, int target_does_save)
   /* Write out status of the tracing run (aka "tstatus" info).  */
   fprintf (fp, "status %c;%s",
           (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
-  /* Encode the error message in hex, might have weird chars.  */
   if (ts->stop_reason == tracepoint_error)
     {
       char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1);
       bin2hex ((gdb_byte *) ts->error_desc, buf, 0);
-      fprintf (fp, ":X%s", buf);
+      fprintf (fp, ":%s", buf);
     }
   fprintf (fp, ":%x", ts->stopping_tracepoint);
   if (ts->traceframe_count >= 0)
@@ -2555,6 +2581,24 @@ trace_save (const char *filename, int target_does_save)
        fprintf (fp, "tp S%x:%s:%s\n",
                 utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
                 utp->step_actions[a]);
+      if (utp->at_string)
+       {
+         encode_source_string (utp->number, utp->addr,
+                               "at", utp->at_string, buf, MAX_TRACE_UPLOAD);
+         fprintf (fp, "tp Z%s\n", buf);
+       }
+      if (utp->cond_string)
+       {
+         encode_source_string (utp->number, utp->addr,
+                               "cond", utp->cond_string, buf, MAX_TRACE_UPLOAD);
+         fprintf (fp, "tp Z%s\n", buf);
+       }
+      for (cmd = utp->cmd_strings; cmd; cmd = cmd->next)
+       {
+         encode_source_string (utp->number, utp->addr, "cmd", cmd->str,
+                               buf, MAX_TRACE_UPLOAD);
+         fprintf (fp, "tp Z%s\n", buf);
+       }
     }
 
   free_uploaded_tps (&uploaded_tps);
@@ -2574,14 +2618,14 @@ trace_save (const char *filename, int target_does_save)
       if (gotten == 0)
        break;
       written = fwrite (buf, gotten, 1, fp);
-      if (written < gotten)
+      if (written < 1)
        perror_with_name (pathname);
       offset += gotten;
     }
 
-  /* Mark the end of trace data.  */
+  /* Mark the end of trace data.  (We know that gotten is 0 at this point.)  */
   written = fwrite (&gotten, 4, 1, fp);
-  if (written < 4)
+  if (written < 1)
     perror_with_name (pathname);
 
   do_cleanups (cleanup);
@@ -3158,7 +3202,8 @@ parse_trace_status (char *line, struct trace_status *ts)
   ts->running_known = 1;
   ts->running = (*p++ == '1');
   ts->stop_reason = trace_stop_reason_unknown;
-  ts->error_desc = "";
+  xfree (ts->error_desc);
+  ts->error_desc = NULL;
   ts->traceframe_count = -1;
   ts->traceframes_created = -1;
   ts->buffer_free = -1;
@@ -3202,6 +3247,9 @@ Status line: '%s'\n"), p, line);
              end = hex2bin (p1, ts->error_desc, (p2 - p1) / 2);
              ts->error_desc[end] = '\0';
            }
+         else
+           ts->error_desc = xstrdup ("");
+
          p = unpack_varlen_hex (++p2, &val);
          ts->stopping_tracepoint = val;
          ts->stop_reason = tracepoint_error;
@@ -3239,18 +3287,18 @@ Status line: '%s'\n"), p, line);
     }
 }
 
-/* Given a line of text defining a tracepoint or tracepoint action, parse
-   it into an "uploaded tracepoint".  */
+/* Given a line of text defining a part of a tracepoint, parse it into
+   an "uploaded tracepoint".  */
 
 void
 parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
 {
   char *p;
   char piece;
-  ULONGEST num, addr, step, pass, orig_size, xlen;
-  int enabled, i;
+  ULONGEST num, addr, step, pass, orig_size, xlen, start;
+  int enabled, i, end;
   enum bptype type;
-  char *cond;
+  char *cond, *srctype, *src, *buf;
   struct uploaded_tp *utp = NULL;
 
   p = line;
@@ -3291,7 +3339,7 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
              p += 2 * xlen;
            }
          else
-           warning ("Unrecognized char '%c' in tracepoint definition, skipping rest", *p);
+           warning (_("Unrecognized char '%c' in tracepoint definition, skipping rest"), *p);
        }
       utp = get_uploaded_tp (num, addr, utpp);
       utp->type = type;
@@ -3310,9 +3358,49 @@ parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
       utp = get_uploaded_tp (num, addr, utpp);
       utp->step_actions[utp->num_step_actions++] = xstrdup (p);
     }
+  else if (piece == 'Z')
+    {
+      /* Parse a chunk of source form definition.  */
+      utp = get_uploaded_tp (num, addr, utpp);
+      srctype = p;
+      p = strchr (p, ':');
+      p++;  /* skip a colon */
+      p = unpack_varlen_hex (p, &start);
+      p++;  /* skip a colon */
+      p = unpack_varlen_hex (p, &xlen);
+      p++;  /* skip a colon */
+
+      buf = alloca (strlen (line));
+
+      end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
+      buf[end] = '\0';
+
+      if (strncmp (srctype, "at:", strlen ("at:")) == 0)
+       utp->at_string = xstrdup (buf);
+      else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
+       utp->cond_string = xstrdup (buf);
+      else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
+       {
+         /* FIXME consider using a vector? */
+         struct uploaded_string *last, *newlast;
+         newlast = (struct uploaded_string *) xmalloc (sizeof (struct uploaded_string));
+         newlast->str = xstrdup (buf);
+         newlast->next = NULL;
+         if (utp->cmd_strings)
+           {
+             for (last = utp->cmd_strings; last->next; last = last->next)
+               ;
+             last->next = newlast;
+           }
+         else
+           utp->cmd_strings = newlast;
+       }
+    }
   else
     {
-      error ("Invalid tracepoint piece");
+      /* Don't error out, the target might be sending us optional
+        info that we don't care about.  */
+      warning (_("Unrecognized tracepoint piece '%c', ignoring"), piece);
     }
 }
 
This page took 0.0271130000000001 seconds and 4 git commands to generate.