[Windows]Fix a bug which cause GDB.exe assert when try to run the inferior

asmwarrior
2014-02-20T14:35:42Z

I see GDB.exe(build from GIT HEAD) can't run any inferior now, it just stops and assert. See the log:

[debug]Starting program:
E:\code\lex\lessons\001_upn_calculator\bin\Debug\test.exe
[debug]../../binutils-gdb/gdb/target.c:1483: internal-error:
target_xfer_partial: Assertion `*xfered_len > 0' failed.
[debug]A problem internal to GDB has been detected,
[debug]further debugging may prove unreliable.
[debug]This application has requested the Runtime to terminate it in an
unusual way.
[debug]Please contact the application's support team for more information.

I found that the assert is here:

/* Check implementations of to_xfer_partial update *XFERED_LEN
properly. Do assertion after printing debug messages, so that we
can find more clues on assertion failure from debugging messages. */
if (retval == TARGET_XFER_OK || retval == TARGET_XFER_E_UNAVAILABLE)
gdb_assert (*xfered_len > 0);

Track down, I found that it is a bug introduced in this commit:
SHA-1: 9b409511d07fe375284701af34909fb539029caf
2014-02-11 Yao Qi <yao@codesourcery.com>

* Return target_xfer_status in to_xfer_partial

This patch does the conversion of to_xfer_partial from

LONGEST (*to_xfer_partial) (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len);

to

enum target_xfer_status (*to_xfer_partial) (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len);

It changes to_xfer_partial return the transfer status and the transfered
length by *XFERED_LEN. Generally, the return status has three stats,

- TARGET_XFER_OK,
- TARGET_XFER_EOF,
- TARGET_XFER_E_XXXX,

Especially the change on windows-nat.c
@@ -2536,27 +2538,30 @@ windows_xfer_shared_libraries (struct target_ops *ops,
}

obstack_free (&obstack, NULL);
- return len;
+ *xfered_len = (ULONGEST) len;
+ return TARGET_XFER_OK;
}

The original code return len(len could be 0), but the new code just return TARGET_XFER_OK.
If len is 0, it should return TARGET_XFER_EOF(it is 0 in enum target_xfer_status declaration.

So, a patch below is confirmed to fix the assert issue, an obvious fix, right?

gdb/windows-nat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index a570a1a..b76d94d 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2480,7 +2480,7 @@ windows_xfer_shared_libraries (struct target_ops *ops,

obstack_free (&obstack, NULL);
*xfered_len = (ULONGEST) len;
- return TARGET_XFER_OK;
+ return len ? TARGET_XFER_OK : TARGET_XFER_EOF;
}

static enum target_xfer_status

Thanks Yao for the hint, so cc to him.

Yuanhui Zhang