Add PowerPC64 ld --tls-get-addr-optimize.
[deliverable/binutils-gdb.git] / gdb / tracefile-tfile.c
index a36596f00842c4d854facaa75c32348cc6bd013d..8cc36b82695e82f56a5f3e26421482fdb4b66d83 100644 (file)
@@ -1,6 +1,6 @@
 /* Trace file TFILE format support in GDB.
 
-   Copyright (C) 1997-2014 Free Software Foundation, Inc.
+   Copyright (C) 1997-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -327,7 +327,7 @@ struct trace_file_writer *
 tfile_trace_file_writer_new (void)
 {
   struct tfile_trace_file_writer *writer
-    = xmalloc (sizeof (struct tfile_trace_file_writer));
+    = XNEW (struct tfile_trace_file_writer);
 
   writer->base.ops = &tfile_write_ops;
   writer->fp = NULL;
@@ -376,9 +376,8 @@ tfile_read (gdb_byte *readbuf, int size)
 }
 
 static void
-tfile_open (char *filename, int from_tty)
+tfile_open (const char *arg, int from_tty)
 {
-  volatile struct gdb_exception ex;
   char *temp;
   struct cleanup *old_chain;
   int flags;
@@ -390,12 +389,13 @@ tfile_open (char *filename, int from_tty)
   struct trace_status *ts;
   struct uploaded_tp *uploaded_tps = NULL;
   struct uploaded_tsv *uploaded_tsvs = NULL;
+  char *filename;
 
   target_preopen (from_tty);
-  if (!filename)
+  if (!arg)
     error (_("No trace file specified."));
 
-  filename = tilde_expand (filename);
+  filename = tilde_expand (arg);
   if (!IS_ABSOLUTE_PATH(filename))
     {
       temp = concat (current_directory, "/", filename, (char *) NULL);
@@ -425,7 +425,7 @@ tfile_open (char *filename, int from_tty)
 
   bytes += TRACE_HEADER_SIZE;
   if (!(header[0] == 0x7f
-       && (strncmp (header + 1, "TRACE0\n", 7) == 0)))
+       && (startswith (header + 1, "TRACE0\n"))))
     error (_("File is not a valid trace file."));
 
   push_target (&tfile_ops);
@@ -442,7 +442,7 @@ tfile_open (char *filename, int from_tty)
   ts->disconnected_tracing = 0;
   ts->circular_buffer = 0;
 
-  TRY_CATCH (ex, RETURN_MASK_ALL)
+  TRY
     {
       /* Read through a section of newline-terminated lines that
         define things like tracepoints.  */
@@ -475,12 +475,13 @@ tfile_open (char *filename, int from_tty)
       if (trace_regblock_size == 0)
        error (_("No register block size recorded in trace file"));
     }
-  if (ex.reason < 0)
+  CATCH (ex, RETURN_MASK_ALL)
     {
       /* Remove the partially set up target.  */
       unpush_target (&tfile_ops);
       throw_exception (ex);
     }
+  END_CATCH
 
   inferior_appeared (current_inferior (), TFILE_PID);
   inferior_ptid = pid_to_ptid (TFILE_PID);
@@ -509,22 +510,22 @@ tfile_interp_line (char *line, struct uploaded_tp **utpp,
 {
   char *p = line;
 
-  if (strncmp (p, "R ", strlen ("R ")) == 0)
+  if (startswith (p, "R "))
     {
       p += strlen ("R ");
       trace_regblock_size = strtol (p, &p, 16);
     }
-  else if (strncmp (p, "status ", strlen ("status ")) == 0)
+  else if (startswith (p, "status "))
     {
       p += strlen ("status ");
       parse_trace_status (p, current_trace_status ());
     }
-  else if (strncmp (p, "tp ", strlen ("tp ")) == 0)
+  else if (startswith (p, "tp "))
     {
       p += strlen ("tp ");
       parse_tracepoint_definition (p, utpp);
     }
-  else if (strncmp (p, "tsv ", strlen ("tsv ")) == 0)
+  else if (startswith (p, "tsv "))
     {
       p += strlen ("tsv ");
       parse_tsv_definition (p, utsvp);
@@ -795,18 +796,17 @@ tfile_fetch_registers (struct target_ops *ops,
                       struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int offset, regn, regsize, pc_regno;
-  gdb_byte *regs;
+  int offset, regn, regsize;
 
   /* An uninitialized reg size says we're not going to be
      successful at getting register blocks.  */
   if (!trace_regblock_size)
     return;
 
-  regs = alloca (trace_regblock_size);
-
   if (traceframe_find_block_type ('R', 0) >= 0)
     {
+      gdb_byte *regs = alloca (trace_regblock_size);
+
       tfile_read (regs, trace_regblock_size);
 
       /* Assume the block is laid out in GDB register number order,
@@ -832,56 +832,9 @@ tfile_fetch_registers (struct target_ops *ops,
            }
          offset += regsize;
        }
-      return;
-    }
-
-  /* We get here if no register data has been found.  Mark registers
-     as unavailable.  */
-  for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
-    regcache_raw_supply (regcache, regn, NULL);
-
-  /* We can often usefully guess that the PC is going to be the same
-     as the address of the tracepoint.  */
-  pc_regno = gdbarch_pc_regnum (gdbarch);
-
-  /* XXX This guessing code below only works if the PC register isn't
-     a pseudo-register.  The value of a pseudo-register isn't stored
-     in the (non-readonly) regcache -- instead it's recomputed
-     (probably from some other cached raw register) whenever the
-     register is read.  This guesswork should probably move to some
-     higher layer.  */
-  if (pc_regno < 0 || pc_regno >= gdbarch_num_regs (gdbarch))
-    return;
-
-  if (regno == -1 || regno == pc_regno)
-    {
-      struct tracepoint *tp = get_tracepoint (get_tracepoint_number ());
-
-      if (tp && tp->base.loc)
-       {
-         /* But don't try to guess if tracepoint is multi-location...  */
-         if (tp->base.loc->next)
-           {
-             warning (_("Tracepoint %d has multiple "
-                        "locations, cannot infer $pc"),
-                      tp->base.number);
-             return;
-           }
-         /* ... or does while-stepping.  */
-         if (tp->step_count > 0)
-           {
-             warning (_("Tracepoint %d does while-stepping, "
-                        "cannot infer $pc"),
-                      tp->base.number);
-             return;
-           }
-
-         store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
-                                 gdbarch_byte_order (gdbarch),
-                                 tp->base.loc->address);
-         regcache_raw_supply (regcache, pc_regno, regs);
-       }
     }
+  else
+    tracefile_fetch_registers (regcache, regno);
 }
 
 static enum target_xfer_status
@@ -901,6 +854,9 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
     {
       int pos = 0;
       enum target_xfer_status res;
+      /* Records the lowest available address of all blocks that
+        intersects the requested range.  */
+      ULONGEST low_addr_available = 0;
 
       /* Iterate through the traceframe's blocks, looking for
         memory.  */
@@ -934,13 +890,19 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
              return TARGET_XFER_OK;
            }
 
+         if (offset < maddr && maddr < (offset + len))
+           if (low_addr_available == 0 || low_addr_available > maddr)
+             low_addr_available = maddr;
+
          /* Skip over this block.  */
          pos += (8 + 2 + mlen);
        }
 
       /* Requested memory is unavailable in the context of traceframes,
         and this address falls within a read-only section, fallback
-        to reading from executable.  */
+        to reading from executable, up to LOW_ADDR_AVAILABLE.  */
+      if (offset < low_addr_available)
+       len = min (len, low_addr_available - offset);
       res = exec_read_partial_read_only (readbuf, offset, len, xfered_len);
 
       if (res == TARGET_XFER_OK)
This page took 0.026571 seconds and 4 git commands to generate.