GP-2033: Make auto-reads respect 'Force Full View'

This commit is contained in:
Dan 2022-05-17 10:02:57 -04:00
parent 7a9544442b
commit 99e00020f3
10 changed files with 105 additions and 11 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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.

View file

@ -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)) {

View file

@ -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)) {

View file

@ -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) {

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);