mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/patch'
Conflicts: Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ReadsTargetMemoryPcodeExecutorState.java
This commit is contained in:
commit
50b48ae63b
13 changed files with 44 additions and 27 deletions
|
@ -67,6 +67,6 @@ public class VisibleAutoReadMemorySpec implements AutoReadMemorySpec {
|
||||||
return AsyncUtils.NIL;
|
return AsyncUtils.NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY);
|
return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,6 @@ public class VisibleROOnceAutoReadMemorySpec implements AutoReadMemorySpec {
|
||||||
return AsyncUtils.NIL;
|
return AsyncUtils.NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY);
|
return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,8 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
|
||||||
Trace trace = current.getTrace();
|
Trace trace = current.getTrace();
|
||||||
TraceRecorder recorder = current.getRecorder();
|
TraceRecorder recorder = current.getRecorder();
|
||||||
BackgroundUtils.async(plugin.getTool(), trace, NAME, true, true, false,
|
BackgroundUtils.async(plugin.getTool(), trace, NAME, true, true, false,
|
||||||
(__, monitor) -> recorder
|
(__, monitor) -> recorder.captureProcessMemory(
|
||||||
.captureProcessMemory(getListingPanel().getProgramSelection(), monitor));
|
getListingPanel().getProgramSelection(), monitor, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -76,11 +76,11 @@ public abstract class ImportExportAsAction extends DockingAction {
|
||||||
chooser.setFileSelectionMode(fileMode);
|
chooser.setFileSelectionMode(fileMode);
|
||||||
|
|
||||||
chooser.setCurrentDirectory(Application.getUserSettingsDirectory());
|
chooser.setCurrentDirectory(Application.getUserSettingsDirectory());
|
||||||
if (chooser.wasCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File f = chooser.getSelectedFile();
|
File f = chooser.getSelectedFile();
|
||||||
|
if (chooser.wasCancelled() || f == null) { // Redundant? Meh, it's cheap.
|
||||||
|
return;
|
||||||
|
}
|
||||||
doAction(container, f);
|
doAction(container, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class DbgengX64DisassemblyInject implements DisassemblyInject {
|
||||||
try {
|
try {
|
||||||
// This is on its own task thread, so whatever.
|
// This is on its own task thread, so whatever.
|
||||||
// Just don't hang it indefinitely.
|
// Just don't hang it indefinitely.
|
||||||
recorder.captureProcessMemory(set, TaskMonitor.DUMMY)
|
recorder.captureProcessMemory(set, TaskMonitor.DUMMY, false)
|
||||||
.get(1000, TimeUnit.MILLISECONDS);
|
.get(1000, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class ReadsTargetMemoryPcodeExecutorState
|
||||||
if (!isLive()) {
|
if (!isLive()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
waitTimeout(recorder.captureProcessMemory(unknown, TaskMonitor.DUMMY));
|
waitTimeout(recorder.captureProcessMemory(unknown, TaskMonitor.DUMMY, false));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,14 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<NavigableMap<Address, byte[]>> captureProcessMemory(AddressSetView set,
|
public CompletableFuture<NavigableMap<Address, byte[]>> captureProcessMemory(AddressSetView set,
|
||||||
TaskMonitor monitor) {
|
TaskMonitor monitor, boolean toMap) {
|
||||||
// TODO: Figure out how to display/select per-thread memory.
|
// TODO: Figure out how to display/select per-thread memory.
|
||||||
// Probably need a thread parameter passed in then?
|
// Probably need a thread parameter passed in then?
|
||||||
// NOTE: That thread memory will already be chained to process memory. Good.
|
// 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;
|
int total = 0;
|
||||||
AddressSetView expSet = expandToBlocks(set)
|
AddressSetView expSet = expandToBlocks(set)
|
||||||
.intersect(trace.getMemoryManager().getRegionsAddressSet(recorder.getSnap()));
|
.intersect(trace.getMemoryManager().getRegionsAddressSet(recorder.getSnap()));
|
||||||
|
@ -75,22 +78,27 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
|
||||||
monitor.initialize(total);
|
monitor.initialize(total);
|
||||||
monitor.setMessage("Capturing memory");
|
monitor.setMessage("Capturing memory");
|
||||||
// TODO: Read blocks in parallel? Probably NO. Tends to overload the agent.
|
// TODO: Read blocks in parallel? Probably NO. Tends to overload the agent.
|
||||||
NavigableMap<Address, byte[]> result = new TreeMap<>();
|
NavigableMap<Address, byte[]> result = toMap ? new TreeMap<>() : null;
|
||||||
return AsyncUtils.each(TypeSpec.VOID, expSet.iterator(), (r, loop) -> {
|
return AsyncUtils.each(TypeSpec.VOID, expSet.iterator(), (r, loop) -> {
|
||||||
AddressRangeChunker it = new AddressRangeChunker(r, BLOCK_SIZE);
|
AddressRangeChunker blocks = new AddressRangeChunker(r, BLOCK_SIZE);
|
||||||
AsyncUtils.each(TypeSpec.VOID, it.iterator(), (vRng, inner) -> {
|
AsyncUtils.each(TypeSpec.VOID, blocks.iterator(), (vBlk, inner) -> {
|
||||||
// The listener in the recorder will copy to the Trace.
|
// The listener in the recorder will copy to the Trace.
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
AddressRange tRng = recorder.getMemoryMapper().traceToTarget(vRng);
|
AddressRange tBlk = recorder.getMemoryMapper().traceToTarget(vBlk);
|
||||||
recorder.getProcessMemory()
|
recorder.getProcessMemory()
|
||||||
.readMemory(tRng.getMinAddress(), (int) tRng.getLength())
|
.readMemory(tBlk.getMinAddress(), (int) tBlk.getLength())
|
||||||
.thenAccept(data -> result.put(tRng.getMinAddress(), data))
|
.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())
|
.thenApply(__ -> !monitor.isCancelled())
|
||||||
.handle(inner::repeatWhile);
|
.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(v -> !monitor.isCancelled()).handle(loop::repeatWhile);
|
||||||
}).thenApply(__ -> result);
|
}).thenApply(__ -> result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,11 +269,11 @@ public class DefaultTraceRecorder implements TraceRecorder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<NavigableMap<Address, byte[]>> captureProcessMemory(AddressSetView set,
|
public CompletableFuture<NavigableMap<Address, byte[]>> captureProcessMemory(AddressSetView set,
|
||||||
TaskMonitor monitor) {
|
TaskMonitor monitor, boolean toMap) {
|
||||||
if (set.isEmpty()) {
|
if (set.isEmpty()) {
|
||||||
return CompletableFuture.completedFuture(new TreeMap<>());
|
return CompletableFuture.completedFuture(new TreeMap<>());
|
||||||
}
|
}
|
||||||
return memoryRecorder.captureProcessMemory(set, monitor);
|
return memoryRecorder.captureProcessMemory(set, monitor, toMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -321,15 +321,20 @@ public interface TraceRecorder {
|
||||||
* returned future completes.
|
* returned future completes.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This task is relatively error tolerant. If a region cannot be captured -- a common occurrence
|
* This task is relatively error tolerant. If a block or region cannot be captured -- a common
|
||||||
* -- the error is logged, but the future may still complete successfully.
|
* 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 selection the addresses to capture, as viewed in the trace
|
||||||
* @param monitor a monitor for displaying task steps
|
* @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
|
* @return a future which completes with the capture results
|
||||||
*/
|
*/
|
||||||
CompletableFuture<NavigableMap<Address, byte[]>> captureProcessMemory(AddressSetView selection,
|
CompletableFuture<NavigableMap<Address, byte[]>> captureProcessMemory(AddressSetView selection,
|
||||||
TaskMonitor monitor);
|
TaskMonitor monitor, boolean toMap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capture the data types of a target's module.
|
* Capture the data types of a target's module.
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class TraceRecorderAsyncPcodeExecutorState
|
||||||
Address addr = space.getAddress(truncateOffset(space, offset));
|
Address addr = space.getAddress(truncateOffset(space, offset));
|
||||||
AddressSet set = new AddressSet(addr, space.getAddress(offset + size - 1));
|
AddressSet set = new AddressSet(addr, space.getAddress(offset + size - 1));
|
||||||
CompletableFuture<NavigableMap<Address, byte[]>> future =
|
CompletableFuture<NavigableMap<Address, byte[]>> future =
|
||||||
recorder.captureProcessMemory(set, TaskMonitor.DUMMY);
|
recorder.captureProcessMemory(set, TaskMonitor.DUMMY, true);
|
||||||
return future.thenApply(map -> {
|
return future.thenApply(map -> {
|
||||||
return knitFromResults(map, addr, size);
|
return knitFromResults(map, addr, size);
|
||||||
});
|
});
|
||||||
|
|
|
@ -126,6 +126,9 @@ public class DBTraceStack extends DBAnnotatedObject implements TraceStack {
|
||||||
else {
|
else {
|
||||||
thread = manager.threadManager.getThread(threadSnap.threadKey);
|
thread = manager.threadManager.getThread(threadSnap.threadKey);
|
||||||
frames.clear();
|
frames.clear();
|
||||||
|
if (frameKeys == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (long k : frameKeys) {
|
for (long k : frameKeys) {
|
||||||
frames.add(manager.getFrameByKey(k));
|
frames.add(manager.getFrameByKey(k));
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,5 +30,5 @@
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="Framework Utility"/>
|
<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="Framework Utility"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="ghidra.GhidraRun"/>
|
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="ghidra.GhidraRun"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Framework Utility"/>
|
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Framework Utility"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+IgnoreUnrecognizedVMOptions -Djava.system.class.loader=ghidra.GhidraClassLoader -Xshare:off -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Dsun.java2d.pmoffscreen=false -Dsun.java2d.xrender=true -Dsun.java2d.d3d=false -Xdock:name="Ghidra" -Dvisualvm.display.name=Ghidra -Dpython.console.encoding=UTF-8 --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.base/sun.security.x509=ALL-UNNAMED --add-opens java.base/sun.security.util=ALL-UNNAMED --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED"/>
|
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+IgnoreUnrecognizedVMOptions -Djava.system.class.loader=ghidra.GhidraClassLoader -Xshare:off -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Dsun.java2d.pmoffscreen=false -Dsun.java2d.xrender=true -Dsun.java2d.d3d=false -Xdock:name="Ghidra" -Dvisualvm.display.name=Ghidra -Dpython.console.encoding=UTF-8 --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.base/sun.security.x509=ALL-UNNAMED --add-opens java.base/sun.security.util=ALL-UNNAMED --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
|
|
@ -83,6 +83,7 @@ VMARGS=-Xshare:off
|
||||||
|
|
||||||
# Permit "illegal reflective accesses" to enable JDK compatibility with Ghidra and 3rd party jars.
|
# 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.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.base/java.net=ALL-UNNAMED
|
||||||
VMARGS=--add-opens java.desktop/sun.awt.image=ALL-UNNAMED
|
VMARGS=--add-opens java.desktop/sun.awt.image=ALL-UNNAMED
|
||||||
VMARGS=--add-opens java.base/sun.security.x509=ALL-UNNAMED
|
VMARGS=--add-opens java.base/sun.security.x509=ALL-UNNAMED
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue