diff --git a/Ghidra/Debug/Debugger/certification.manifest b/Ghidra/Debug/Debugger/certification.manifest index 93b98c22e3..2b87be0f13 100644 --- a/Ghidra/Debug/Debugger/certification.manifest +++ b/Ghidra/Debug/Debugger/certification.manifest @@ -46,6 +46,8 @@ src/main/help/help/topics/DebuggerInterpreterPlugin/DebuggerInterpreterPlugin.ht src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html||GHIDRA||||END| src/main/help/help/topics/DebuggerListingPlugin/images/DebuggerGoToDialog.png||GHIDRA||||END| src/main/help/help/topics/DebuggerListingPlugin/images/DebuggerListingPlugin.png||GHIDRA||||END| +src/main/help/help/topics/DebuggerMemoryBytesPlugin/DebuggerMemoryBytesPlugin.html||GHIDRA||||END| +src/main/help/help/topics/DebuggerMemoryBytesPlugin/images/DebuggerMemoryBytesPlugin.png||GHIDRA||||END| src/main/help/help/topics/DebuggerMemviewPlugin/DebuggerMemviewPlugin.html||GHIDRA||||END| src/main/help/help/topics/DebuggerMemviewPlugin/images/DebuggerMemviewPlugin.png||GHIDRA||||END| src/main/help/help/topics/DebuggerMemviewPlugin/images/DebuggerMemviewPlugin_old.png||GHIDRA||||END| diff --git a/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml b/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml index 9019d4a84a..df323e28ae 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml +++ b/Ghidra/Debug/Debugger/src/main/help/help/TOC_Source.xml @@ -102,6 +102,10 @@ sortgroup="h" target="help/topics/DebuggerRegistersPlugin/DebuggerRegistersPlugin.html" /> + + diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/DebuggerMemoryBytesPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/DebuggerMemoryBytesPlugin.html new file mode 100644 index 0000000000..79d4a7fc04 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/DebuggerMemoryBytesPlugin.html @@ -0,0 +1,149 @@ + + + + + + + Debugger: Memory (Dynamic Bytes) + + + + + +

Debugger: Memory (Dynamic Bytes)

+ + + + + + + +
+ +

The memory, or dynamic bytes, window is analogous to Ghidra's + bytes window for static analysis, but in the dynamic context. That is, it displays memory + contents from a target. More precisely, it displays recorded memory contents in a trace. In + most use cases, that trace is "at the present," meaning it is the most recent memory from a + live target. Multiple memory windows can be displayed simultaneously, using the same pattern as + many other Ghidra windows. The "primary" window is always displayed and generally tracks with + the rest of the tool. Any window can be "snapshotted," i.e., duplicated. This is where memory + windows differ from static bytes windows. Static snapshots remain in place; they do not + automatically navigate. Dynamic snapshots can still be configured to navigate, following the + rest of the tool. A common use is to configure a "snapshot" to follow the stack pointer. Still, + you can disable a window's automatic navigation, so it behaves like a true snapshot. A current + limitation is that you cannot use snapshots to display different points in time for the same + trace.

+ +

Because not all memory is captured, some background coloring is used to indicate the state + of attempted memory reads. Regardless of state, the most-recent contents, as recorded in the + trace, are displayed in the window, defaulting to 00. "Stale" memory, that is ranges of memory + which have not been read at the current time, are displayed with a darker background. Where + that memory is marked "read-only" and has been successfully read previously, that coloring is + subdued, since the contents are not likely to have changed. Where a read was attempted but + failed, the first address in the failed range is displayed with a pink background. Otherwise, + up-to-date contents are displayed with the default background color.

+ +

NOTE: Modification of trace byte contents is a work in progress. At the moment, the feature + is simply disabled. In general, modifications to bytes when the window is "at the present" are + directed to the target. Otherwise, they simply modify the historical or emulated values stored + in the trace. A modification at a given time remains in effect, but stale, for all future times + up to but excluding the time of the next recorded value.

+ +

Actions

+ +

The memory window provides a variety of actions, some for managing and configuring windows, + and others for capturing memory from a target.

+ +

Follows Selected Thread

+ +

This action is only available on snapshot memory windows. The primary window always follows + the tool's current thread. Disabling this toggle causes the snapshot to remain on its own + current thread rather than following the tool's. The current thread is used when computing a + location to navigate to automatically. It is only applicable when "Track Location" is set to + something other than "Do Not Track."

+ +

Track Location

+ +

This action is always available on all memory windows. It configures automatic navigation + for the window. When location tracking is enabled, the window is automatically navigated to an + address computed from the trace's or target's machine state. The address is also highlighted in + green. The computed address is affected by the tool's current "coordinates," that is the + selected thread, frame, and point in time. The options are pluggable, but currently consist + of:

+ + + +

Go To (G)

+ +

This action is available whenever a trace is active in the window. It prompts the user for + an address, which can be expressed in Sleigh, then attempts to navigate to it. The expression + is evaluated in the context of the current thread, frame, and point in time. If the current + trace is live and at the present, the target may be queried to retrieve any machine state + required to evaluate the expression.

+ + + + + + + +
+ +

Capture Memory

+ +

This action is available when the current trace is "at the present" with a live target, and + there is a selection of addresses in the memory window. It will instruct the recorder to + capture the contents of memory for the selected range(s). Typically, the viewable addresses are + automatically captured — see the Auto-Read action.

+ +

Auto-Read Memory

+ +

This action is always available on all memory windows. It configures whether or not the + memory range(s) displayed in the window are automatically captured. Like the Capture Memory + action, capture can only occur when the current trace is "at the present" with a live target. + It occurs when the user scrolls the window, or when the window is otherwise navigated to a new + location. Note that other components may capture memory, regardless of this windows's + configuration. For example, the recorder typically captures the page of memory pointed to by + the program counter. In other words, this action cannot "disable all memory captures." + The options are pluggable, but currently consist of:

+ + + +

Byte Viewer Options

+ +

This action does the same as it does for the static context.

+ +

Toggle Editing

+ +

This action does the same as it does for the static context. NOTE: This feature is currently + disabled, as it is a work in progress.

+ +

Tool Options: Colors

+ +

The memory-state and tracked-location background colors are replicated from the Dynamic Listing.

+ + diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/images/DebuggerMemoryBytesPlugin.png b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/images/DebuggerMemoryBytesPlugin.png new file mode 100644 index 0000000000..fcfa2b60a2 Binary files /dev/null and b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/images/DebuggerMemoryBytesPlugin.png differ diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java new file mode 100644 index 0000000000..4c5959c19f --- /dev/null +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java @@ -0,0 +1,128 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.memory; + +import java.util.Set; + +import org.junit.*; + +import com.google.common.collect.Range; + +import ghidra.app.plugin.assembler.Assembler; +import ghidra.app.plugin.assembler.Assemblers; +import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; +import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin; +import ghidra.app.services.DebuggerTraceManagerService; +import ghidra.program.model.lang.RegisterValue; +import ghidra.program.model.symbol.SourceType; +import ghidra.test.ToyProgramBuilder; +import ghidra.trace.database.ToyDBTraceBuilder; +import ghidra.trace.model.memory.TraceMemoryFlag; +import ghidra.trace.model.memory.TraceMemoryRegisterSpace; +import ghidra.trace.model.symbol.*; +import ghidra.trace.model.thread.TraceThread; +import ghidra.util.database.UndoableTransaction; +import help.screenshot.GhidraScreenShotGenerator; + +public class DebuggerMemoryBytesPluginScreenShots extends GhidraScreenShotGenerator { + + DebuggerTraceManagerService traceManager; + DebuggerMemoryBytesPlugin memoryPlugin; + DebuggerMemoryBytesProvider memoryProvider; + DebuggerListingPlugin listingPlugin; // For colors + ToyDBTraceBuilder tb; + + @Before + public void setUpMine() throws Throwable { + traceManager = addPlugin(tool, DebuggerTraceManagerServicePlugin.class); + memoryPlugin = addPlugin(tool, DebuggerMemoryBytesPlugin.class); + listingPlugin = addPlugin(tool, DebuggerListingPlugin.class); + + memoryProvider = waitForComponentProvider(DebuggerMemoryBytesProvider.class); + tool.showComponentProvider(memoryProvider, true); + + tb = new ToyDBTraceBuilder("echo", ToyProgramBuilder._X64); + } + + @After + public void tearDownMine() { + tb.close(); + } + + @Test + public void testCaptureDebuggerMemoryBytesPlugin() throws Throwable { + try (UndoableTransaction tid = tb.startTransaction()) { + long snap = tb.trace.getTimeManager().createSnapshot("First").getKey(); + tb.trace.getMemoryManager() + .addRegion(".text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), + Set.of(TraceMemoryFlag.READ, TraceMemoryFlag.EXECUTE)); + + TraceSymbolManager symbolManager = tb.trace.getSymbolManager(); + TraceNamespaceSymbol global = symbolManager.getGlobalNamespace(); + + TraceSymbol mainLabel = symbolManager + .labels() + .create(snap, null, tb.addr(0x00400000), + "main", global, SourceType.USER_DEFINED); + @SuppressWarnings("unused") + TraceSymbol cloneLabel = symbolManager + .labels() + .create(snap, null, tb.addr(0x00400060), + "clone", global, SourceType.USER_DEFINED); + TraceSymbol childLabel = symbolManager + .labels() + .create(snap, null, tb.addr(0x00400034), + "child", global, SourceType.USER_DEFINED); + @SuppressWarnings("unused") + TraceSymbol exitLabel = symbolManager + .labels() + .create(snap, null, tb.addr(0x00400061), + "exit", global, SourceType.USER_DEFINED); + + Assembler assembler = Assemblers.getAssembler(tb.trace.getProgramView()); + + assembler.assemble(mainLabel.getAddress(), + "PUSH RBP", + "MOV RBP,RSP", + "CALL clone", + "TEST EAX,EAX", + "JNZ child", + "SUB RSP,0x10", + "MOV dword ptr [RSP],0x6c6c6548", + "MOV dword ptr [RSP+4],0x57202c6f", + "MOV dword ptr [RSP+8],0x646c726f", + "MOV word ptr [RSP+0xc],0x21", + "CALL exit", + "SUB RSP,0x10", + "MOV dword ptr [RSP],0x2c657942", + "MOV dword ptr [RSP+4],0x726f5720", + "MOV dword ptr [RSP+8],0x21646c", + "CALL exit"); + + TraceThread thread = tb.getOrAddThread("[1]", snap); + + TraceMemoryRegisterSpace regs = + tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); + regs.setValue(snap, new RegisterValue(tb.language.getProgramCounter(), + childLabel.getAddress().getOffsetAsBigInteger())); + } + + traceManager.openTrace(tb.trace); + traceManager.activateTrace(tb.trace); + + captureIsolatedProvider(DebuggerMemoryBytesProvider.class, 600, 600); + } +}