diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/GdbEventsListenerAdapter.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/GdbEventsListenerAdapter.java index 79d2c20cf7..5a911be917 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/GdbEventsListenerAdapter.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/GdbEventsListenerAdapter.java @@ -89,6 +89,13 @@ public interface GdbEventsListenerAdapter extends GdbEventsListener { default void breakpointDeleted(GdbBreakpointInfo info, GdbCause cause) { } + /** + * The target memory was changed by the user. + * + *

+ * This occurs when the user executes a {@code set} command. It does not (necessarily) occur + * from the target's execution. + */ @Override default void memoryChanged(GdbInferior inferior, long addr, int len, GdbCause cause) { } diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/AbstractGdbThreadGroupEvent.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/AbstractGdbThreadGroupEvent.java index a54c9ad838..4825e728ed 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/AbstractGdbThreadGroupEvent.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/AbstractGdbThreadGroupEvent.java @@ -27,6 +27,7 @@ public abstract class AbstractGdbThreadGroupEvent extends AbstractGdbEventWithFi /** * Construct a new event by parsing the tail for information * + *

* The thread group ID must be specified by GDB in the "id" field. * * @param tail the text following the event type in the GDB/MI event record diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/GdbMemoryChangedEvent.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/GdbMemoryChangedEvent.java index a3e4b53313..d944da4b00 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/GdbMemoryChangedEvent.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/evt/GdbMemoryChangedEvent.java @@ -29,6 +29,7 @@ public class GdbMemoryChangedEvent extends AbstractGdbEventWithFields { /** * Construct a new event by parsing the tail for information * + *

* The thread group, start address, and length must be specified by GDB. * * @param tail the text following the event type in the GDB/MI event record @@ -38,7 +39,7 @@ public class GdbMemoryChangedEvent extends AbstractGdbEventWithFields { super(tail); this.iid = GdbParsingUtils.parseInferiorId(getInfo().getString("thread-group")); this.addr = GdbParsingUtils.parsePrefixedHex(getInfo().getString("addr")); - this.len = Integer.parseInt(getInfo().getString("len")); + this.len = (int) GdbParsingUtils.parsePrefixedHex(getInfo().getString("len")); } /** diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/parsing/GdbParsingUtils.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/parsing/GdbParsingUtils.java index f1b7544361..44719850a5 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/parsing/GdbParsingUtils.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/manager/parsing/GdbParsingUtils.java @@ -111,6 +111,7 @@ public enum GdbParsingUtils { /** * Parse a hex string to a long * + *

* The string must have the {@code 0x} prefix * * @param hex the string @@ -126,6 +127,7 @@ public enum GdbParsingUtils { /** * Parse a hex string to a big integer * + *

* The string must have the {@code 0x} prefix * * @param hex the string @@ -141,6 +143,7 @@ public enum GdbParsingUtils { /** * Parse an octal string to a long * + *

* The string must have the {@code 0} prefix * * @param oct the string @@ -156,6 +159,7 @@ public enum GdbParsingUtils { /** * Parse an inferior id * + *

* The id must have the {@code i} prefix * * @param id the string diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java index 2541b094ab..dd9e1a0960 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java @@ -211,6 +211,12 @@ public class GdbModelTargetInferiorContainer inferior.modules.libraryUnloaded(name); } + @Override + public void memoryChanged(GdbInferior inf, long addr, int len, GdbCause cause) { + GdbModelTargetInferior inferior = getTargetInferior(inf); + inferior.memory.memoryChanged(addr, len); + } + private void updateUsingInferiors(Map byIID) { List inferiors; synchronized (this) { diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetProcessMemory.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetProcessMemory.java index 604faf721e..24348ec18b 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetProcessMemory.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetProcessMemory.java @@ -81,10 +81,8 @@ public class GdbModelTargetProcessMemory return region; } - @Override - public CompletableFuture readMemory(Address address, int length) { + protected CompletableFuture doReadMemory(Address address, long offset, int length) { ByteBuffer buf = ByteBuffer.allocate(length); - long offset = address.getOffset(); AddressRange range; try { range = new AddressRangeImpl(address, length); @@ -118,6 +116,11 @@ public class GdbModelTargetProcessMemory }); } + @Override + public CompletableFuture readMemory(Address address, int length) { + return doReadMemory(address, address.getOffset(), length); + } + @Override public CompletableFuture writeMemory(Address address, byte[] data) { return inferior.writeMemory(address.getOffset(), ByteBuffer.wrap(data)).thenAccept(__ -> { @@ -138,4 +141,12 @@ public class GdbModelTargetProcessMemory return null; }); } + + public void memoryChanged(long offset, int len) { + Address address = impl.getAddressFactory().getDefaultAddressSpace().getAddress(offset); + doReadMemory(address, offset, len).exceptionally(ex -> { + Msg.error(this, "Failed to update memory contents on memory-changed event", ex); + return null; + }); + } }