From 237e8a80453bd22c73653c5da686d6a51d82410f Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 27 Aug 2021 16:23:25 -0400 Subject: [PATCH 1/4] GP-1059: Fix NPE in DBTraceStack --- .../main/java/ghidra/trace/database/stack/DBTraceStack.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java index 900f30cdca..d92df16baa 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/stack/DBTraceStack.java @@ -126,6 +126,9 @@ public class DBTraceStack extends DBAnnotatedObject implements TraceStack { else { thread = manager.threadManager.getThread(threadSnap.threadKey); frames.clear(); + if (frameKeys == null) { + return; + } for (long k : frameKeys) { frames.add(manager.getFrameByKey(k)); } From 7ac2d89e537e38182faa83b86cd46716da2eabe2 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 27 Aug 2021 17:00:55 -0400 Subject: [PATCH 2/4] GP-1047: Fixed NPE in Objects Provider: Import/Export As actions. --- .../debug/gui/objects/actions/ImportExportAsAction.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/actions/ImportExportAsAction.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/actions/ImportExportAsAction.java index b91105a470..f1e34aec38 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/actions/ImportExportAsAction.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/actions/ImportExportAsAction.java @@ -76,11 +76,11 @@ public abstract class ImportExportAsAction extends DockingAction { chooser.setFileSelectionMode(fileMode); chooser.setCurrentDirectory(Application.getUserSettingsDirectory()); - if (chooser.wasCancelled()) { - return; - } File f = chooser.getSelectedFile(); + if (chooser.wasCancelled() || f == null) { // Redundant? Meh, it's cheap. + return; + } doAction(container, f); } From 259c346c40a5bc8afee05260ddebadd90d7d62ea Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Mon, 30 Aug 2021 09:29:13 -0400 Subject: [PATCH 3/4] GP-1227: Making "captureMemory" a bit less timid. --- .../gui/action/VisibleAutoReadMemorySpec.java | 2 +- .../VisibleROOnceAutoReadMemorySpec.java | 2 +- .../gui/listing/DebuggerListingProvider.java | 4 +-- .../platform/DbgengX64DisassemblyInject.java | 2 +- .../ReadsTargetMemoryPcodeExecutorState.java | 2 +- .../service/model/DefaultMemoryRecorder.java | 30 ++++++++++++------- .../service/model/DefaultTraceRecorder.java | 4 +-- .../ghidra/app/services/TraceRecorder.java | 11 +++++-- .../TraceRecorderAsyncPcodeExecutorState.java | 2 +- 9 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java index 48bededf40..0211928e05 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java @@ -67,6 +67,6 @@ public class VisibleAutoReadMemorySpec implements AutoReadMemorySpec { return AsyncUtils.NIL; } - return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY); + return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY, false); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java index 3db7d1a2e3..fe5c37c547 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java @@ -92,6 +92,6 @@ public class VisibleROOnceAutoReadMemorySpec implements AutoReadMemorySpec { return AsyncUtils.NIL; } - return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY); + return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY, false); } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java index 2aa6e6b4dc..fe301ba939 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java @@ -134,8 +134,8 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi Trace trace = current.getTrace(); TraceRecorder recorder = current.getRecorder(); BackgroundUtils.async(plugin.getTool(), trace, NAME, true, true, false, - (__, monitor) -> recorder - .captureProcessMemory(getListingPanel().getProgramSelection(), monitor)); + (__, monitor) -> recorder.captureProcessMemory( + getListingPanel().getProgramSelection(), monitor, false)); } @Override diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/platform/DbgengX64DisassemblyInject.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/platform/DbgengX64DisassemblyInject.java index 5d732aafe0..30d846fa47 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/platform/DbgengX64DisassemblyInject.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/platform/DbgengX64DisassemblyInject.java @@ -97,7 +97,7 @@ public class DbgengX64DisassemblyInject implements DisassemblyInject { try { // This is on its own task thread, so whatever. // Just don't hang it indefinitely. - recorder.captureProcessMemory(set, TaskMonitor.DUMMY) + recorder.captureProcessMemory(set, TaskMonitor.DUMMY, false) .get(1000, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ReadsTargetMemoryPcodeExecutorState.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ReadsTargetMemoryPcodeExecutorState.java index 808afb8bb8..82a726b3d0 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ReadsTargetMemoryPcodeExecutorState.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ReadsTargetMemoryPcodeExecutorState.java @@ -61,7 +61,7 @@ public class ReadsTargetMemoryPcodeExecutorState } protected void fillUnknownWithRecorder(AddressSet unknown) { - waitTimeout(recorder.captureProcessMemory(unknown, TaskMonitor.DUMMY)); + waitTimeout(recorder.captureProcessMemory(unknown, TaskMonitor.DUMMY, false)); } private void fillUnknownWithStaticImages(AddressSet unknown) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java index 0eaa1a2d2d..217057e916 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java @@ -61,11 +61,14 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { } public CompletableFuture> captureProcessMemory(AddressSetView set, - TaskMonitor monitor) { + TaskMonitor monitor, boolean toMap) { // TODO: Figure out how to display/select per-thread memory. // Probably need a thread parameter passed in then? // NOTE: That thread memory will already be chained to process memory. Good. + // NOTE: I don't intend to warn about the number of requests. + // They're delivered in serial, and there's a cancel button that works + int total = 0; AddressSetView expSet = expandToBlocks(set) .intersect(trace.getMemoryManager().getRegionsAddressSet(recorder.getSnap())); @@ -75,22 +78,27 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { monitor.initialize(total); monitor.setMessage("Capturing memory"); // TODO: Read blocks in parallel? Probably NO. Tends to overload the agent. - NavigableMap result = new TreeMap<>(); + NavigableMap result = toMap ? new TreeMap<>() : null; return AsyncUtils.each(TypeSpec.VOID, expSet.iterator(), (r, loop) -> { - AddressRangeChunker it = new AddressRangeChunker(r, BLOCK_SIZE); - AsyncUtils.each(TypeSpec.VOID, it.iterator(), (vRng, inner) -> { + AddressRangeChunker blocks = new AddressRangeChunker(r, BLOCK_SIZE); + AsyncUtils.each(TypeSpec.VOID, blocks.iterator(), (vBlk, inner) -> { // The listener in the recorder will copy to the Trace. monitor.incrementProgress(1); - AddressRange tRng = recorder.getMemoryMapper().traceToTarget(vRng); + AddressRange tBlk = recorder.getMemoryMapper().traceToTarget(vBlk); recorder.getProcessMemory() - .readMemory(tRng.getMinAddress(), (int) tRng.getLength()) - .thenAccept(data -> result.put(tRng.getMinAddress(), data)) + .readMemory(tBlk.getMinAddress(), (int) tBlk.getLength()) + .thenAccept(data -> { + if (toMap) { + result.put(tBlk.getMinAddress(), data); + } + }) + .exceptionally(e -> { + Msg.error(this, "Error reading block " + tBlk + ": " + e); + // NOTE: Above may double log, since recorder listens for errors, too + return null; // Continue looping on errors + }) .thenApply(__ -> !monitor.isCancelled()) .handle(inner::repeatWhile); - }).exceptionally(e -> { - Msg.error(this, "Error reading range " + r + ": " + e); - // NOTE: Above may double log, since recorder listens for errors, too - return null; // Continue looping on errors }).thenApply(v -> !monitor.isCancelled()).handle(loop::repeatWhile); }).thenApply(__ -> result); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java index 5b286c9989..c009f1dbc7 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorder.java @@ -269,11 +269,11 @@ public class DefaultTraceRecorder implements TraceRecorder { @Override public CompletableFuture> captureProcessMemory(AddressSetView set, - TaskMonitor monitor) { + TaskMonitor monitor, boolean toMap) { if (set.isEmpty()) { return CompletableFuture.completedFuture(new TreeMap<>()); } - return memoryRecorder.captureProcessMemory(set, monitor); + return memoryRecorder.captureProcessMemory(set, monitor, toMap); } @Override diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/TraceRecorder.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/TraceRecorder.java index d560555f43..b03b4d2222 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/TraceRecorder.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/TraceRecorder.java @@ -321,15 +321,20 @@ public interface TraceRecorder { * returned future completes. * *

- * This task is relatively error tolerant. If a region cannot be captured -- a common occurrence - * -- the error is logged, but the future may still complete successfully. + * This task is relatively error tolerant. If a block or region cannot be captured -- a common + * occurrence -- the error is logged, but the future may still complete successfully. For large + * captures, it is recommended to set {@code toMap} to false. The recorder will place the bytes + * into the trace where they can be retrieved later. For small captures, and where bypassing the + * database may offer some advantage, set {@code toMap} to true, and the captured bytes will be + * returned in an interval map. Connected intervals may or may not be joined. * * @param selection the addresses to capture, as viewed in the trace * @param monitor a monitor for displaying task steps + * @param toMap true to return results in a map, false to complete with null * @return a future which completes with the capture results */ CompletableFuture> captureProcessMemory(AddressSetView selection, - TaskMonitor monitor); + TaskMonitor monitor, boolean toMap); /** * Capture the data types of a target's module. diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecutorState.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecutorState.java index e513b0040f..bf62ecb961 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecutorState.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecutorState.java @@ -99,7 +99,7 @@ public class TraceRecorderAsyncPcodeExecutorState Address addr = space.getAddress(truncateOffset(space, offset)); AddressSet set = new AddressSet(addr, space.getAddress(offset + size - 1)); CompletableFuture> future = - recorder.captureProcessMemory(set, TaskMonitor.DUMMY); + recorder.captureProcessMemory(set, TaskMonitor.DUMMY, true); return future.thenApply(map -> { return knitFromResults(map, addr, size); }); From 1d64c7ff2947727bedcd22306b2eb90c9de4667c Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 31 Aug 2021 11:47:24 -0400 Subject: [PATCH 4/4] GP-1193: Including --add-opens java.base/java.util=ALL-UNNAMED for Gson library (fixes #3355) --- Ghidra/Features/Base/.launch/Ghidra.launch | 2 +- Ghidra/RuntimeScripts/Common/support/launch.properties | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Ghidra/Features/Base/.launch/Ghidra.launch b/Ghidra/Features/Base/.launch/Ghidra.launch index baae6f1125..4b904e6635 100644 --- a/Ghidra/Features/Base/.launch/Ghidra.launch +++ b/Ghidra/Features/Base/.launch/Ghidra.launch @@ -30,5 +30,5 @@ - + diff --git a/Ghidra/RuntimeScripts/Common/support/launch.properties b/Ghidra/RuntimeScripts/Common/support/launch.properties index 025e5285f3..914085dbe6 100644 --- a/Ghidra/RuntimeScripts/Common/support/launch.properties +++ b/Ghidra/RuntimeScripts/Common/support/launch.properties @@ -83,6 +83,7 @@ VMARGS=-Xshare:off # Permit "illegal reflective accesses" to enable JDK compatibility with Ghidra and 3rd party jars. VMARGS=--add-opens java.base/java.lang=ALL-UNNAMED +VMARGS=--add-opens java.base/java.util=ALL-UNNAMED VMARGS=--add-opens java.base/java.net=ALL-UNNAMED VMARGS=--add-opens java.desktop/sun.awt.image=ALL-UNNAMED VMARGS=--add-opens java.base/sun.security.x509=ALL-UNNAMED