aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/mi/mi-main.c4
-rw-r--r--gdb/target.c66
-rw-r--r--gdb/target.h5
-rw-r--r--gdb/testsuite/gdb.mi/mi-async.exp2
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 (&current_target, TARGET_OBJECT_MEMORY, NULL,
- mbuf, addr, total_bytes);
+ nr_bytes = target_read_until_error (&current_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