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/target.c | |
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/target.c')
-rw-r--r-- | gdb/target.c | 66 |
1 files changed, 66 insertions, 0 deletions
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 |