mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-2033: Make auto-reads respect 'Force Full View'
This commit is contained in:
parent
7a9544442b
commit
99e00020f3
10 changed files with 105 additions and 11 deletions
|
@ -55,8 +55,9 @@ public class VisibleAutoReadMemorySpec implements AutoReadMemorySpec {
|
|||
return AsyncUtils.NIL;
|
||||
}
|
||||
TraceRecorder recorder = coordinates.getRecorder();
|
||||
AddressSet visibleAccessible =
|
||||
recorder.getAccessibleMemory().intersect(visible);
|
||||
boolean ffv = coordinates.getView().getMemory().isForceFullView();
|
||||
AddressSetView visibleAccessible =
|
||||
ffv ? visible : recorder.getAccessibleMemory().intersect(visible);
|
||||
TraceMemoryManager mm = coordinates.getTrace().getMemoryManager();
|
||||
AddressSetView alreadyKnown =
|
||||
mm.getAddressesWithState(coordinates.getSnap(), visibleAccessible,
|
||||
|
|
|
@ -57,8 +57,9 @@ public class VisibleROOnceAutoReadMemorySpec implements AutoReadMemorySpec {
|
|||
return AsyncUtils.NIL;
|
||||
}
|
||||
TraceRecorder recorder = coordinates.getRecorder();
|
||||
AddressSet visibleAccessible =
|
||||
recorder.getAccessibleMemory().intersect(visible);
|
||||
boolean ffv = coordinates.getView().getMemory().isForceFullView();
|
||||
AddressSetView visibleAccessible =
|
||||
ffv ? visible : recorder.getAccessibleMemory().intersect(visible);
|
||||
TraceMemoryManager mm = coordinates.getTrace().getMemoryManager();
|
||||
AddressSetView alreadyKnown =
|
||||
mm.getAddressesWithState(coordinates.getSnap(), visibleAccessible,
|
||||
|
|
|
@ -52,6 +52,11 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
|
|||
return RecorderUtils.INSTANCE.readMemoryBlocks(recorder, BLOCK_BITS, set, monitor, toMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offerProcessMemory(TargetMemory memory) {
|
||||
recorder.getProcessMemory().addMemory(memory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offerProcessRegion(TargetMemoryRegion region) {
|
||||
TargetMemory mem = region.getMemory();
|
||||
|
@ -81,6 +86,11 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
|
|||
}, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProcessMemory(TargetMemory memory) {
|
||||
recorder.getProcessMemory().removeMemory(memory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProcessRegion(TargetMemoryRegion region) {
|
||||
// Already removed from processMemory. That's how we knew to go here.
|
||||
|
|
|
@ -115,6 +115,12 @@ public class RecorderComposedMemory implements AbstractRecorderMemory {
|
|||
return byRegion.get(floor.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMemory(TargetMemory memory) {
|
||||
// Do nothing
|
||||
// This delegates by region, so need regions even if I have memory
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRegion(TargetMemoryRegion region, TargetMemory memory) {
|
||||
synchronized (accessibilityByMemory) {
|
||||
|
@ -129,6 +135,11 @@ public class RecorderComposedMemory implements AbstractRecorderMemory {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMemory(TargetMemory invalid) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRegion(TargetObject invalid) {
|
||||
if (!(invalid instanceof TargetMemoryRegion)) {
|
||||
|
|
|
@ -37,6 +37,15 @@ public class RecorderSimpleMemory implements AbstractRecorderMemory {
|
|||
public RecorderSimpleMemory() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMemory(TargetMemory memory) {
|
||||
synchronized (this) {
|
||||
if (this.memory == null) {
|
||||
this.memory = memory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRegion(TargetMemoryRegion region, TargetMemory memory) {
|
||||
synchronized (this) {
|
||||
|
@ -47,6 +56,15 @@ public class RecorderSimpleMemory implements AbstractRecorderMemory {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMemory(TargetMemory invalid) {
|
||||
synchronized (this) {
|
||||
if (this.memory == invalid) {
|
||||
this.memory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRegion(TargetObject invalid) {
|
||||
if (!(invalid instanceof TargetMemoryRegion)) {
|
||||
|
|
|
@ -358,6 +358,7 @@ public class TraceObjectManager {
|
|||
if (memMapper != null) {
|
||||
return;
|
||||
}
|
||||
recorder.memoryRecorder.offerProcessMemory((TargetMemory) added);
|
||||
mapper.offerMemory((TargetMemory) added).thenAccept(mm -> {
|
||||
synchronized (this) {
|
||||
memMapper = mm;
|
||||
|
@ -371,7 +372,7 @@ public class TraceObjectManager {
|
|||
}
|
||||
|
||||
public void removeMemory(TargetObject removed) {
|
||||
// Nothing for now
|
||||
recorder.memoryRecorder.removeProcessMemory((TargetMemory) removed);
|
||||
}
|
||||
|
||||
public void addMemoryRegion(TargetObject added) {
|
||||
|
|
|
@ -24,8 +24,12 @@ import ghidra.program.model.address.*;
|
|||
|
||||
public interface AbstractRecorderMemory {
|
||||
|
||||
public void addMemory(TargetMemory memory);
|
||||
|
||||
public void addRegion(TargetMemoryRegion region, TargetMemory memory);
|
||||
|
||||
public void removeMemory(TargetMemory invalid);
|
||||
|
||||
public boolean removeRegion(TargetObject invalid);
|
||||
|
||||
public CompletableFuture<byte[]> readMemory(Address address, int length);
|
||||
|
@ -43,5 +47,4 @@ public interface AbstractRecorderMemory {
|
|||
DebuggerMemoryMapper memMapper);
|
||||
|
||||
public AddressRange alignAndLimitToFloor(Address targetAddress, int length);
|
||||
|
||||
}
|
||||
|
|
|
@ -15,15 +15,18 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.debug.service.model.interfaces;
|
||||
|
||||
import ghidra.dbg.target.TargetMemory;
|
||||
import ghidra.dbg.target.TargetMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
|
||||
public interface ManagedMemoryRecorder {
|
||||
void offerProcessMemory(TargetMemory memory);
|
||||
|
||||
void offerProcessRegion(TargetMemoryRegion region);
|
||||
|
||||
void removeProcessMemory(TargetMemory memory);
|
||||
|
||||
void removeProcessRegion(TargetMemoryRegion region);
|
||||
|
||||
TraceMemoryRegion getTraceMemoryRegion(TargetMemoryRegion region);
|
||||
|
||||
}
|
||||
|
|
|
@ -54,10 +54,7 @@ public enum RecorderUtils {
|
|||
|
||||
int blockSize = 1 << blockBits;
|
||||
int total = 0;
|
||||
AddressSetView expSet = quantize(blockBits, set)
|
||||
.intersect(recorder.getTrace()
|
||||
.getMemoryManager()
|
||||
.getRegionsAddressSet(recorder.getSnap()));
|
||||
AddressSetView expSet = quantize(blockBits, set);
|
||||
for (AddressRange r : expSet) {
|
||||
total += Long.divideUnsigned(r.getLength() + blockSize - 1, blockSize);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates;
|
|||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractFollowsCurrentThreadAction;
|
||||
import ghidra.app.plugin.core.debug.gui.action.AutoReadMemorySpec;
|
||||
import ghidra.app.plugin.core.debug.gui.action.DebuggerGoToDialog;
|
||||
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsolePlugin;
|
||||
import ghidra.app.plugin.core.debug.gui.console.DebuggerConsoleProvider.BoundAction;
|
||||
|
@ -687,6 +688,52 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
});
|
||||
}
|
||||
|
||||
public void runTestAutoReadMemoryReadsWithForceFullView(AutoReadMemorySpec spec)
|
||||
throws Throwable {
|
||||
byte[] data = incBlock();
|
||||
byte[] zero = new byte[data.length];
|
||||
ByteBuffer buf = ByteBuffer.allocate(data.length);
|
||||
listingProvider.setAutoReadMemorySpec(spec);
|
||||
|
||||
createTestModel();
|
||||
mb.createTestProcessesAndThreads();
|
||||
|
||||
// NOTE: Do not add a region. Depend on Force full view!
|
||||
// Populate target memory before recording
|
||||
mb.testProcess1.memory.setMemory(mb.addr(0x55550000), data);
|
||||
|
||||
TraceRecorder recorder = modelService.recordTargetAndActivateTrace(mb.testProcess1,
|
||||
createTargetTraceMapper(mb.testProcess1));
|
||||
Trace trace = recorder.getTrace();
|
||||
waitRecorder(recorder);
|
||||
traceManager.activateTrace(trace);
|
||||
waitForSwing();
|
||||
|
||||
buf.clear();
|
||||
assertEquals(data.length,
|
||||
trace.getMemoryManager().getBytes(recorder.getSnap(), addr(trace, 0x55550000), buf));
|
||||
assertArrayEquals(zero, buf.array());
|
||||
|
||||
runSwing(() -> trace.getProgramView().getMemory().setForceFullView(true));
|
||||
goToDyn(addr(trace, 0x55550000));
|
||||
waitRecorder(recorder);
|
||||
|
||||
buf.clear();
|
||||
assertEquals(data.length,
|
||||
trace.getMemoryManager().getBytes(recorder.getSnap(), addr(trace, 0x55550000), buf));
|
||||
assertArrayEquals(data, buf.array());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoReadMemoryVisROOnceReadsWithForceFullView() throws Throwable {
|
||||
runTestAutoReadMemoryReadsWithForceFullView(readVisROOnce);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoReadMemoryVisibleReadsWithForceFullView() throws Throwable {
|
||||
runTestAutoReadMemoryReadsWithForceFullView(readVisible);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemoryStateBackgroundColors() throws Exception {
|
||||
createAndOpenTrace();
|
||||
|
@ -1067,6 +1114,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
|
||||
traceManager.activateTrace(tb.trace);
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
// In the module, but not in its section
|
||||
listingPlugin.goTo(tb.addr(0x00411234), true);
|
||||
|
@ -1096,6 +1144,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI
|
|||
|
||||
traceManager.activateTrace(tb.trace);
|
||||
}
|
||||
waitForDomainObject(tb.trace);
|
||||
|
||||
// In the module, but not in its section
|
||||
listingPlugin.goTo(tb.addr(0x00411234), true);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue