[PATCH 3/3] winedbg/gdbproxy: Replace memory read over a breakpoint with the real value.

Zebediah Figura z.figura12 at gmail.com
Sun Jan 14 19:01:15 CST 2018


Fixes bug #44349.

Normally, when we hit a breakpoint, we remove it before stopping and add it
after continuing. gdb, however, reads the process memory before requesting
that the breakpoint be removed, and apparently caches it until the `stepi`
instruction is executed; as a result, it thinks that the interrupt byte that
is present in the code is an actual interrupt and not a breakpoint, and so
tries to step over it as one byte instead of executing the real instruction
at that location.

Fix this problem by reporting the real bytes when they are requested, which
is what gdb's native backend does as well.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 programs/winedbg/gdbproxy.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c
index c02ad3b..7b9a476 100644
--- a/programs/winedbg/gdbproxy.c
+++ b/programs/winedbg/gdbproxy.c
@@ -1568,6 +1568,28 @@ static enum packet_return packet_thread(struct gdb_context* gdbctx)
     }
 }
 
+static BOOL read_memory(struct gdb_context *gdbctx, char *addr, char *buffer, SIZE_T blk_len, SIZE_T *r)
+{
+    /* Wrapper around process_io->read() that replaces values displaced by breakpoints. */
+
+    BOOL ret;
+
+    ret = gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, r);
+    if (ret)
+    {
+        struct gdb_ctx_Xpoint *xpt;
+
+        for (xpt = &gdbctx->Xpoints[NUM_XPOINT - 1]; xpt >= gdbctx->Xpoints; xpt--)
+        {
+            char *xpt_addr = xpt->addr;
+
+            if (xpt->type != -1 && xpt_addr >= addr && xpt_addr < addr + blk_len)
+                buffer[xpt_addr - addr] = xpt->val;
+        }
+    }
+    return ret;
+}
+
 static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
 {
     char               *addr;
@@ -1584,8 +1606,7 @@ static enum packet_return packet_read_memory(struct gdb_context* gdbctx)
     for (nread = 0; nread < len; nread += r, addr += r)
     {
         blk_len = min(sizeof(buffer), len - nread);
-        if (!gdbctx->process->process_io->read(gdbctx->process->handle, addr, buffer, blk_len, &r) ||
-            r == 0)
+        if (!read_memory(gdbctx, addr, buffer, blk_len, &r) || r == 0)
         {
             /* fail at first address, return error */
             if (nread == 0) return packet_reply_error(gdbctx, EFAULT);
-- 
2.7.4




More information about the wine-devel mailing list