From e6a41bb5d1bf71b4b82122f1ec2088cfcff6e7df Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Wed, 27 Oct 2021 12:32:35 -0400 Subject: [PATCH] GP-1431: Adding Help for DebuggerMemoryBytesPlugin --- Ghidra/Debug/Debugger/certification.manifest | 2 + .../src/main/help/help/TOC_Source.xml | 4 + .../DebuggerMemoryBytesPlugin.html | 149 ++++++++++++++++++ .../images/DebuggerMemoryBytesPlugin.png | Bin 0 -> 46088 bytes .../DebuggerMemoryBytesPluginScreenShots.java | 128 +++++++++++++++ 5 files changed, 283 insertions(+) create mode 100644 Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/DebuggerMemoryBytesPlugin.html create mode 100644 Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerMemoryBytesPlugin/images/DebuggerMemoryBytesPlugin.png create mode 100644 Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPluginScreenShots.java 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 0000000000000000000000000000000000000000..fcfa2b60a2ffbc32ed87b5be0c57c0237f4e1f51 GIT binary patch literal 46088 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 Job^8*`v2E?O$Pt~ literal 0 HcmV?d00001 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); + } +}