Use new to_xfer_partial interface in ctf and tfile target
authorYao Qi <yao@codesourcery.com>
Tue, 11 Feb 2014 04:20:05 +0000 (12:20 +0800)
committerYao Qi <yao@codesourcery.com>
Sun, 23 Feb 2014 03:44:27 +0000 (11:44 +0800)
This patch adjust both ctf and tfile target implementation of to_xfer_partial,
to return TARGET_XFER_E_UNAVAILABLE and set *XFERED_LEN if data is
unavailable.  Note that some code on xfer in exec.c can be shared, but
we can do it in a separate pass later.

gdb:

2014-02-23  Yao Qi  <yao@codesourcery.com>

* exec.c (section_table_read_available_memory): New function.
* exec.h (section_table_read_available_memory): Declare.
* ctf.c (ctf_xfer_partial): Call
section_table_read_available_memory.
* tracefile-tfile.c (tfile_xfer_partial): Likewise.

gdb/ChangeLog
gdb/ctf.c
gdb/exec.c
gdb/exec.h
gdb/tracefile-tfile.c

index 11b70b8..55745af 100644 (file)
@@ -1,5 +1,13 @@
 2014-02-23  Yao Qi  <yao@codesourcery.com>
 
+       * exec.c (section_table_read_available_memory): New function.
+       * exec.h (section_table_read_available_memory): Declare.
+       * ctf.c (ctf_xfer_partial): Call
+       section_table_read_available_memory.
+       * tracefile-tfile.c (tfile_xfer_partial): Likewise.
+
+2014-02-23  Yao Qi  <yao@codesourcery.com>
+
        * ctf.c (ctf_xfer_partial): Move code to ...
        * exec.c (exec_read_partial_read_only): ... it.  New function.
        * tracefile-tfile.c (tfile_xfer_partial): Likewise.
index 9c8f4d7..95fd31f 100644 (file)
--- a/gdb/ctf.c
+++ b/gdb/ctf.c
@@ -1465,9 +1465,14 @@ ctf_xfer_partial (struct target_ops *ops, enum target_object object,
 
       /* Restore the position.  */
       bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos);
-    }
 
-  return exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+      return exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+    }
+  else
+    {
+      /* Fallback to reading from read-only sections.  */
+      return section_table_read_available_memory (readbuf, offset, len, xfered_len);
+    }
 }
 
 /* This is the implementation of target_ops method
index 74c61eb..607f5ac 100644 (file)
@@ -615,6 +615,60 @@ section_table_available_memory (VEC(mem_range_s) *memory,
 }
 
 enum target_xfer_status
+section_table_read_available_memory (gdb_byte *readbuf, ULONGEST offset,
+                                    ULONGEST len, ULONGEST *xfered_len)
+{
+  VEC(mem_range_s) *available_memory = NULL;
+  struct target_section_table *table;
+  struct cleanup *old_chain;
+  mem_range_s *r;
+  int i;
+
+  table = target_get_section_table (&exec_ops);
+  available_memory = section_table_available_memory (available_memory,
+                                                    offset, len,
+                                                    table->sections,
+                                                    table->sections_end);
+
+  old_chain = make_cleanup (VEC_cleanup(mem_range_s),
+                           &available_memory);
+
+  normalize_mem_ranges (available_memory);
+
+  for (i = 0;
+       VEC_iterate (mem_range_s, available_memory, i, r);
+       i++)
+    {
+      if (mem_ranges_overlap (r->start, r->length, offset, len))
+       {
+         CORE_ADDR end;
+         enum target_xfer_status status;
+
+         /* Get the intersection window.  */
+         end = min (offset + len, r->start + r->length);
+
+         gdb_assert (end - offset <= len);
+
+         if (offset >= r->start)
+           status = exec_read_partial_read_only (readbuf, offset,
+                                                 end - offset,
+                                                 xfered_len);
+         else
+           {
+             *xfered_len = r->start - offset;
+             status = TARGET_XFER_E_UNAVAILABLE;
+           }
+         do_cleanups (old_chain);
+         return status;
+       }
+    }
+  do_cleanups (old_chain);
+
+  *xfered_len = len;
+  return TARGET_XFER_E_UNAVAILABLE;
+}
+
+enum target_xfer_status
 section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
                                   ULONGEST offset, ULONGEST len,
                                   ULONGEST *xfered_len,
index 960c585..84dc40f 100644 (file)
@@ -91,6 +91,14 @@ extern enum target_xfer_status
                                     struct target_section *,
                                     const char *);
 
+/* Read from mappable read-only sections of BFD executable files.
+   Similar to exec_read_partial_read_only, but return
+   TARGET_XFER_E_UNAVAILABLE if data is unavailable.  */
+
+extern enum target_xfer_status
+  section_table_read_available_memory (gdb_byte *readbuf, ULONGEST offset,
+                                      ULONGEST len, ULONGEST *xfered_len);
+
 /* Set the loaded address of a section.  */
 extern void exec_set_section_address (const char *, int, CORE_ADDR);
 
index 02122eb..cbf746d 100644 (file)
@@ -936,9 +936,15 @@ tfile_xfer_partial (struct target_ops *ops, enum target_object object,
          /* Skip over this block.  */
          pos += (8 + 2 + mlen);
        }
-    }
 
-  return exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+      return exec_read_partial_read_only (readbuf, offset, len, xfered_len);
+    }
+  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'