aboutsummaryrefslogtreecommitdiff
path: root/gdb/target.c
diff options
context:
space:
mode:
authorVladimir Prus <vladimir@codesourcery.com>2008-06-26 15:10:48 +0000
committerVladimir Prus <vladimir@codesourcery.com>2008-06-26 15:10:48 +0000
commitd50867903fea3ec5cb9a85874aa45a08844952a7 (patch)
treed2799565753bb10d8972b1126d5cc4ad0a887abe /gdb/target.c
parent54cde457963e524c3e8656dead262525a3d00130 (diff)
downloadgdb-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.c66
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