Module: wine
Branch: master
Commit: f18c0db314d8fe3f724a7bd3642b718fbefb6439
URL: https://source.winehq.org/git/wine.git/?a=commit;h=f18c0db314d8fe3f724a7bd3…
Author: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Date: Wed Nov 24 00:11:08 2021 +0900
winedbg: Cache GDB qXfer command result for chunked fetching.
GDB does not retrieve the result of a qXfer command at once; instead, it
issues a series of requests to obtain the result one "chunk" at a time,
and concatenates those chunks internally. Each request contains offset
and length variables that specify which portion of the result shall be
retrieved.
Today, Winedbg handles this by generating the entire result data each
time a request is received and slicing out the requested range for the
response. This is not only inefficient due to repeated computation,
but also prone to race condition since the result may change between
successive chunk requests due to the dynamic nature of some commands
such as "libraries" and "threads."
Fix this by cacheing the result into a buffer at the first request, and
use the buffer to serve successive chunk requests. The cache is
invalidated when the remote requests a different object, or the debugger
reaches the end of the result cache buffer.
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
programs/winedbg/gdbproxy.c | 42 ++++++++++++++++++++++++++++++++----------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index 0f5d9df35b8..c21fed43b48 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -931,15 +931,17 @@ static inline void packet_reply_register_hex_to(struct gdb_context* gdbctx, dbg_
packet_reply_hex_to(gdbctx, cpu_register_ptr(gdbctx, ctx, idx), cpu_register_map[idx].length);
}
-static void packet_reply_xfer(struct gdb_context* gdbctx, size_t off, size_t len)
+static void packet_reply_xfer(struct gdb_context* gdbctx, size_t off, size_t len, BOOL* more_p)
{
+ BOOL more;
size_t data_len, trunc_len;
packet_reply_open(gdbctx);
data_len = gdbctx->qxfer_buffer.len;
/* check if off + len would overflow */
- if (off < data_len && off + len < data_len)
+ more = off < data_len && off + len < data_len;
+ if (more)
packet_reply_add(gdbctx, "m");
else
packet_reply_add(gdbctx, "l");
@@ -951,6 +953,8 @@ static void packet_reply_xfer(struct gdb_context* gdbctx, size_t off, size_t len
}
packet_reply_close(gdbctx);
+
+ *more_p = more;
}
/* =============================================== *
@@ -2071,6 +2075,7 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
{
enum packet_return result;
int i;
+ BOOL more;
for (i = 0; i < ARRAY_SIZE(qxfer_handlers); i++)
{
@@ -2086,21 +2091,38 @@ static enum packet_return packet_query(struct gdb_context* gdbctx)
TRACE("qXfer %s read %s %u,%u\n", debugstr_a(object_name), debugstr_a(annex), off, len);
- gdbctx->qxfer_object_idx = i;
- strcpy(gdbctx->qxfer_object_annex, annex);
+ if (off > 0 &&
+ gdbctx->qxfer_buffer.len > 0 &&
+ gdbctx->qxfer_object_idx == i &&
+ strcmp(gdbctx->qxfer_object_annex, annex) == 0)
+ {
+ result = packet_send_buffer;
+ TRACE("qXfer read result = %d (cached)\n", result);
+ }
+ else
+ {
+ reply_buffer_clear(&gdbctx->qxfer_buffer);
+
+ gdbctx->qxfer_object_idx = i;
+ strcpy(gdbctx->qxfer_object_annex, annex);
- result = (*qxfer_handlers[i].handler)(gdbctx);
- TRACE("qXfer read result = %d\n", result);
+ result = (*qxfer_handlers[i].handler)(gdbctx);
+ TRACE("qXfer read result = %d\n", result);
+ }
+ more = FALSE;
if ((result & ~packet_last_f) == packet_send_buffer)
{
- packet_reply_xfer(gdbctx, off, len);
+ packet_reply_xfer(gdbctx, off, len, &more);
result = (result & packet_last_f) | packet_done;
}
- gdbctx->qxfer_object_idx = -1;
- gdbctx->qxfer_object_annex[0] = '\0';
- reply_buffer_clear(&gdbctx->qxfer_buffer);
+ if (!more)
+ {
+ gdbctx->qxfer_object_idx = -1;
+ gdbctx->qxfer_object_annex[0] = '\0';
+ reply_buffer_clear(&gdbctx->qxfer_buffer);
+ }
return result;
}
Module: wine
Branch: master
Commit: 26aee726fb3dcf7615824cb51231964c04648eaa
URL: https://source.winehq.org/git/wine.git/?a=commit;h=26aee726fb3dcf7615824cb5…
Author: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Date: Wed Nov 24 00:10:01 2021 +0900
winedbg: Buffer output of GDB qXfer commands for proper slicing.
Today, gdbproxy reuses the same buffer for both the qXfer reply and the
actual GDB packet reply. This worked well, since each byte in the qXfer
reply buffer matched 1:1 to each byte in the actual GDB reply packet.
Since we escape special characters now, this property no longer holds
and a single byte in qXfer reply will take up to two bytes in the GDB
reply packet. This causes offsets to shift, preventing the
offset/length response slicing (part of GDB protocol) from working
correctly.
Fix this by writing the qXfer reply data in a separate buffer, and
performing slicing out of it.
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
programs/winedbg/gdbproxy.c | 264 +++++++++++++++++++++++---------------------
1 file changed, 137 insertions(+), 127 deletions(-)
Diff: https://source.winehq.org/git/wine.git/?a=commitdiff;h=26aee726fb3dcf761582…