Add tiny memory model GD test cases.
[deliverable/binutils-gdb.git] / gdb / tracefile-tfile.c
index 02122eb35b2442db78c2f8b719c8881fee964ced..44c6189f824668e40960a5cfebd2ace50a551b08 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.
 
@@ -376,7 +376,7 @@ 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;
@@ -390,12 +390,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);
@@ -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
@@ -900,6 +853,10 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
   if (get_traceframe_number () != -1)
     {
       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.  */
@@ -933,12 +890,37 @@ 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);
        }
-    }
 
-  return exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+      /* Requested memory is unavailable in the context of traceframes,
+        and this address falls within a read-only section, fallback
+        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)
+       return TARGET_XFER_OK;
+      else
+       {
+         /* No use trying further, we know some memory starting
+            at MEMADDR isn't available.  */
+         *xfered_len = len;
+         return TARGET_XFER_UNAVAILABLE;
+       }
+    }
+  else
+    {
+      /* Fallback to reading from read-only sections.  */
+      return section_table_read_available_memory (readbuf, offset, len,
+                                                 xfered_len);
+    }
 }
 
 /* Iterate through the blocks of a trace frame, looking for a 'V'
This page took 0.046018 seconds and 4 git commands to generate.