Re-implement ia64-linux-nat.c::ia64_linux_xfer_partial
authorPedro Alves <palves@redhat.com>
Wed, 26 Feb 2014 01:45:50 +0000 (20:45 -0500)
committerJoel Brobecker <brobecker@adacore.com>
Wed, 26 Feb 2014 01:53:23 +0000 (20:53 -0500)
[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.

gdb/ChangeLog
gdb/ia64-linux-nat.c

index e60ec1c9aaaddf07aae7429f7174bea5ea485dad..16f4619180953e61915aac0ab957139e2ff453c9 100644 (file)
@@ -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.
index c057b55f8131464eb72d62252f457bce90981753..3cfbd7642b63504553b5d7b0a31f42df5bb5c80f 100644 (file)
@@ -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,