Merge remote-tracking branch 'origin/GP-1890_Dan_memoryBytesDiffColoring--SQUASHED'

This commit is contained in:
Ryan Kurtz 2022-09-24 01:46:22 -04:00
commit 5ee752891b
6 changed files with 135 additions and 22 deletions

View file

@ -0,0 +1,64 @@
/* ###
* 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.nio.ByteBuffer;
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.program.model.address.Address;
public class CachedBytePage {
private boolean valid = true;
private DebuggerCoordinates coordinates;
private Address start;
private byte[] page = new byte[4096];
private ByteBuffer buf = ByteBuffer.wrap(page);
public byte getByte(DebuggerCoordinates coordinates, Address address) {
long offset;
if (!valid || this.coordinates == null || !this.coordinates.equals(coordinates) ||
start == null || !start.hasSameAddressSpace(address)) {
offset = refresh(coordinates, address);
}
else {
offset = address.subtract(start);
if (offset < 0 || 4096 <= offset) {
offset = refresh(coordinates, address);
}
}
return page[(int) offset];
}
public void invalidate() {
valid = false;
}
private long refresh(DebuggerCoordinates coordinates, Address address) {
valid = false;
buf.clear();
Address min = address.getAddressSpace().getMinAddress();
start = address.subtractWrap(page.length / 2);
if (start.compareTo(min) < 0 || start.compareTo(address) > 0) {
start = min;
}
coordinates.getTrace()
.getMemoryManager()
.getViewBytes(coordinates.getViewSnap(), start, buf);
valid = true;
return address.subtract(start);
}
}

View file

@ -47,7 +47,10 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.Trace;
import ghidra.trace.model.Trace.TraceMemoryBytesChangeType;
import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.Swing;
public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvider {
@ -75,6 +78,19 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
return true;
}
protected class ListenerForChanges extends TraceDomainObjectListener {
public ListenerForChanges() {
listenFor(TraceMemoryBytesChangeType.CHANGED, this::bytesChanged);
}
private void bytesChanged(TraceAddressSpace space) {
if (space.getAddressSpace().isMemorySpace()) {
currCache.invalidate();
prevCache.invalidate();
}
}
}
protected class ForMemoryBytesGoToTrait extends DebuggerGoToTrait {
public ForMemoryBytesGoToTrait() {
super(DebuggerMemoryBytesProvider.this.tool, DebuggerMemoryBytesProvider.this.plugin,
@ -151,7 +167,13 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
protected AutoReadMemorySpec autoReadMemorySpec = defaultReadMemorySpec;
// TODO: followsCurrentSnap?
private final ListenerForChanges listenerForChanges = new ListenerForChanges();
DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
private DebuggerCoordinates previous = DebuggerCoordinates.NOWHERE;
private final CachedBytePage currCache = new CachedBytePage();
private final CachedBytePage prevCache = new CachedBytePage();
protected final boolean isMainViewer;
@ -174,6 +196,27 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
setHelpLocation(DebuggerResources.HELP_PROVIDER_MEMORY_BYTES);
}
@Override
protected ByteBlockChangeManager newByteBlockChangeManager(ProgramByteBlockSet blockSet,
ByteBlockChangeManager bbcm) {
return new ByteBlockChangeManager(blockSet, bbcm) {
@Override
protected boolean isChanged(ByteBlock block, BigInteger offset, int unitByteSize) {
if (super.isChanged(block, offset, unitByteSize)) {
return true;
}
if (previous.getTrace() != current.getTrace()) {
return false;
}
Address address = blockSet.getAddress(block, offset);
if (address == null) {
return false;
}
return currCache.getByte(current, address) != prevCache.getByte(previous, address);
}
};
}
@Override
protected ProgramByteBlockSet newByteBlockSet(ByteBlockChangeManager changeManager) {
if (program == null) {
@ -304,6 +347,18 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
return result;
}
protected void removeOldListeners() {
if (current.getTrace() != null) {
current.getTrace().removeListener(listenerForChanges);
}
}
protected void addNewListeners() {
if (current.getTrace() != null) {
current.getTrace().addListener(listenerForChanges);
}
}
protected DebuggerCoordinates adjustCoordinates(DebuggerCoordinates coordinates) {
if (followsCurrentThread) {
return coordinates;
@ -318,7 +373,10 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
current = coordinates;
return;
}
previous = current;
removeOldListeners();
current = coordinates;
addNewListeners();
doSetProgram(current.getView());
goToTrait.goToCoordinates(coordinates);
trackingTrait.goToCoordinates(coordinates);