aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2014-02-25 20:45:50 -0500
committerJoel Brobecker <brobecker@adacore.com>2014-02-25 20:53:23 -0500
commitd16461aeef555da47e358b0f81c75912e4ea07e2 (patch)
treedabc7899c6eebfd229f6a8f51a2c89bbfd058036
parenta8b1622022a0fb3531bfd4ce77e69f6b15312745 (diff)
downloadgdb-d16461aeef555da47e358b0f81c75912e4ea07e2.zip
gdb-d16461aeef555da47e358b0f81c75912e4ea07e2.tar.gz
gdb-d16461aeef555da47e358b0f81c75912e4ea07e2.tar.bz2
Re-implement ia64-linux-nat.c::ia64_linux_xfer_partial
[description of this patch and ChangeLog entry by Joel Brobecker] The recent implementation was questionable, and if it worked, it was only by chance because the requested length is large enough that only one read was sufficient. Note that the implementation before that also made that assumption, in the form of only handling TARGET_OBJECT_UNWIND_TABLE xfer requests when offset was zero. gdb/ChangeLog: * ia64-linux-nat.c (ia64_linux_xfer_partial): Reimplement handling of object == TARGET_OBJECT_UNWIND_TABLE.
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/ia64-linux-nat.c35
2 files changed, 28 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e60ec1c..16f4619 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-25 Pedro Alves <palves@redhat.com>
+
+ * ia64-linux-nat.c (ia64_linux_xfer_partial): Reimplement
+ handling of object == TARGET_OBJECT_UNWIND_TABLE.
+
2014-02-25 Stan Shebs <stan@codesourcery.com>
* defs.h: Annotate comments for Doxygen.
diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c
index c057b55..3cfbd76 100644
--- a/gdb/ia64-linux-nat.c
+++ b/gdb/ia64-linux-nat.c
@@ -850,20 +850,31 @@ ia64_linux_xfer_partial (struct target_ops *ops,
{
if (object == TARGET_OBJECT_UNWIND_TABLE && readbuf != NULL)
{
- gdb_byte *tmp_buf = alloca (offset + len);
- ULONGEST xfered;
-
- xfered = syscall (__NR_getunwind, readbuf, offset + len);
- if (xfered <= 0)
+ static long gate_table_size;
+ gdb_byte *tmp_buf;
+ long res;
+
+ /* Probe for the table size once. */
+ if (gate_table_size == 0)
+ gate_table_size = syscall (__NR_getunwind, NULL, 0);
+ if (gate_table_size < 0)
return TARGET_XFER_E_IO;
- else if (xfered <= offset)
+
+ if (offset >= gate_table_size)
return TARGET_XFER_EOF;
- else
- {
- memcpy (readbuf, tmp_buf + offset, xfered - offset);
- *xfered_len = xfered - offset;
- return TARGET_XFER_OK;
- }
+
+ tmp_buf = alloca (gate_table_size);
+ res = syscall (__NR_getunwind, tmp_buf, gate_table_size);
+ if (res < 0)
+ return TARGET_XFER_E_IO;
+ gdb_assert (res == gate_table_size);
+
+ if (offset + len > gate_table_size)
+ len = gate_table_size - offset;
+
+ memcpy (readbuf, tmp_buf + offset, len);
+ *xfered_len = len;
+ return TARGET_XFER_OK;
}
return super_xfer_partial (ops, object, annex, readbuf, writebuf,