diff options
author | Vladimir Prus <vladimir@codesourcery.com> | 2008-06-26 15:10:48 +0000 |
---|---|---|
committer | Vladimir Prus <vladimir@codesourcery.com> | 2008-06-26 15:10:48 +0000 |
commit | d50867903fea3ec5cb9a85874aa45a08844952a7 (patch) | |
tree | d2799565753bb10d8972b1126d5cc4ad0a887abe /gdb | |
parent | 54cde457963e524c3e8656dead262525a3d00130 (diff) | |
download | gdb-d50867903fea3ec5cb9a85874aa45a08844952a7.zip gdb-d50867903fea3ec5cb9a85874aa45a08844952a7.tar.gz gdb-d50867903fea3ec5cb9a85874aa45a08844952a7.tar.bz2 |
* target.c (target_read_until_error): New.
* target.h (target_read_until_error): Declare.
* mi/mi-main.c (mi_cmd_data_read_memory): Use
target_read_until_error.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/mi/mi-main.c | 4 | ||||
-rw-r--r-- | gdb/target.c | 66 | ||||
-rw-r--r-- | gdb/target.h | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-async.exp | 2 |
5 files changed, 81 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 868989f..24d6b75 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2008-06-26 Vladimir Prus <vladimir@codesourcery.com> + + * target.c (target_read_until_error): New. + * target.h (target_read_until_error): Declare. + * mi/mi-main.c (mi_cmd_data_read_memory): Use + target_read_until_error. + 2008-06-25 Jan Kratochvil <jan.kratochvil@redhat.com> Fix a memory leak found by Hui Zhu <teawater@gmail.com>. diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 5d90c75..40e6cf5 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -782,8 +782,8 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) mbuf = xcalloc (total_bytes, 1); make_cleanup (xfree, mbuf); - nr_bytes = target_read (¤t_target, TARGET_OBJECT_MEMORY, NULL, - mbuf, addr, total_bytes); + nr_bytes = target_read_until_error (¤t_target, TARGET_OBJECT_MEMORY, + NULL, mbuf, addr, total_bytes); if (nr_bytes <= 0) error ("Unable to read memory."); diff --git a/gdb/target.c b/gdb/target.c index 6b009a8..b2f7be7 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1451,6 +1451,72 @@ target_read (struct target_ops *ops, return len; } +LONGEST +target_read_until_error (struct target_ops *ops, + enum target_object object, + const char *annex, gdb_byte *buf, + ULONGEST offset, LONGEST len) +{ + LONGEST xfered = 0; + while (xfered < len) + { + LONGEST xfer = target_read_partial (ops, object, annex, + (gdb_byte *) buf + xfered, + offset + xfered, len - xfered); + /* Call an observer, notifying them of the xfer progress? */ + if (xfer == 0) + return xfered; + if (xfer < 0) + { + /* We've got an error. Try to read in smaller blocks. */ + ULONGEST start = offset + xfered; + ULONGEST remaining = len - xfered; + ULONGEST half; + + /* If an attempt was made to read a random memory address, + it's likely that the very first byte is not accessible. + Try reading the first byte, to avoid doing log N tries + below. */ + xfer = target_read_partial (ops, object, annex, + (gdb_byte *) buf + xfered, start, 1); + if (xfer <= 0) + return xfered; + start += 1; + remaining -= 1; + half = remaining/2; + + while (half > 0) + { + xfer = target_read_partial (ops, object, annex, + (gdb_byte *) buf + xfered, + start, half); + if (xfer == 0) + return xfered; + if (xfer < 0) + { + remaining = half; + } + else + { + /* We have successfully read the first half. So, the + error must be in the second half. Adjust start and + remaining to point at the second half. */ + xfered += xfer; + start += xfer; + remaining -= xfer; + } + half = remaining/2; + } + + return xfered; + } + xfered += xfer; + QUIT; + } + return len; +} + + /* An alternative to target_write with progress callbacks. */ LONGEST diff --git a/gdb/target.h b/gdb/target.h index 902d428..9641f0d 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -230,6 +230,11 @@ extern LONGEST target_read (struct target_ops *ops, const char *annex, gdb_byte *buf, ULONGEST offset, LONGEST len); +extern LONGEST target_read_until_error (struct target_ops *ops, + enum target_object object, + const char *annex, gdb_byte *buf, + ULONGEST offset, LONGEST len); + extern LONGEST target_write (struct target_ops *ops, enum target_object object, const char *annex, const gdb_byte *buf, diff --git a/gdb/testsuite/gdb.mi/mi-async.exp b/gdb/testsuite/gdb.mi/mi-async.exp index 9ac91fd..a730698 100644 --- a/gdb/testsuite/gdb.mi/mi-async.exp +++ b/gdb/testsuite/gdb.mi/mi-async.exp @@ -27,7 +27,7 @@ if { !([isnative] && [istarget *-linux*]) \ # The plan is for async mode to become the default but toggle for now. set saved_gdbflags $GDBFLAGS -set GDBFLAGS [concat $GDBFLAGS " -ex \"maint set linux-async on\""] +#set GDBFLAGS [concat $GDBFLAGS " -ex \"maint set linux-async on\""] load_lib mi-support.exp |