diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/ctf.c | 9 | ||||
-rw-r--r-- | gdb/exec.c | 54 | ||||
-rw-r--r-- | gdb/exec.h | 8 | ||||
-rw-r--r-- | gdb/tracefile-tfile.c | 10 |
5 files changed, 85 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 11b70b8..55745af 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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. @@ -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 @@ -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, @@ -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); diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c index 02122eb..cbf746d 100644 --- a/gdb/tracefile-tfile.c +++ b/gdb/tracefile-tfile.c @@ -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' |