Merge remote-tracking branch 'origin/GP-2834_Dan_hoverVarVals--SQUASHED'

(#4732)
This commit is contained in:
Ryan Kurtz 2023-01-12 18:53:35 -05:00
commit bf5dfa6170
105 changed files with 12279 additions and 478 deletions

View file

@ -15,7 +15,10 @@
*/
package ghidra.pcode.exec.trace;
import java.util.Map;
import generic.ULongSpan.ULongSpanSet;
import ghidra.generic.util.datastruct.SemisparseByteArray;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language;
@ -38,6 +41,17 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiec
super(language, space, backing);
}
protected CheckedCachedSpace(Language language, AddressSpace space,
PcodeTraceDataAccess backing, SemisparseByteArray bytes, AddressSet written) {
super(language, space, backing, bytes, written);
}
@Override
public CachedSpace fork() {
return new CheckedCachedSpace(language, space, backing, bytes.fork(),
new AddressSet(written));
}
@Override
public byte[] read(long offset, int size, Reason reason) {
ULongSpanSet uninitialized =
@ -59,14 +73,34 @@ public abstract class AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiec
super(data);
}
protected AbstractCheckedTraceCachedWriteBytesPcodeExecutorStatePiece(PcodeTraceDataAccess data,
AbstractSpaceMap<CachedSpace> spaceMap) {
super(data, spaceMap);
}
protected class CheckedCachedSpaceMap extends TraceBackedSpaceMap {
public CheckedCachedSpaceMap() {
super();
}
protected CheckedCachedSpaceMap(Map<AddressSpace, CachedSpace> spaces) {
super(spaces);
}
@Override
protected CachedSpace newSpace(AddressSpace space, PcodeTraceDataAccess backing) {
return new CheckedCachedSpace(language, space, backing);
}
@Override
public CheckedCachedSpaceMap fork() {
return new CheckedCachedSpaceMap(fork(spaces));
}
}
@Override
protected AbstractSpaceMap<CachedSpace> newSpaceMap() {
return new TraceBackedSpaceMap() {
@Override
protected CachedSpace newSpace(AddressSpace space, PcodeTraceDataAccess backing) {
return new CheckedCachedSpace(language, space, backing);
}
};
return new CheckedCachedSpaceMap();
}
/**

View file

@ -15,8 +15,7 @@
*/
package ghidra.pcode.exec.trace;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import javax.help.UnsupportedOperationException;
@ -24,6 +23,7 @@ import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.mem.MemBuffer;
/**
@ -43,7 +43,7 @@ public class AddressesReadTracePcodeExecutorStatePiece
implements TracePcodeExecutorStatePiece<byte[], AddressSetView> {
protected final PcodeTraceDataAccess data;
private final Map<Long, AddressSetView> unique = new HashMap<>();
private final Map<Long, AddressSetView> unique;
/**
* Construct the state piece
@ -54,6 +54,15 @@ public class AddressesReadTracePcodeExecutorStatePiece
super(data.getLanguage(), BytesPcodeArithmetic.forLanguage(data.getLanguage()),
AddressesReadPcodeArithmetic.INSTANCE);
this.data = data;
this.unique = new HashMap<>();
}
protected AddressesReadTracePcodeExecutorStatePiece(PcodeTraceDataAccess data,
Map<Long, AddressSetView> unique) {
super(data.getLanguage(), BytesPcodeArithmetic.forLanguage(data.getLanguage()),
AddressesReadPcodeArithmetic.INSTANCE);
this.data = data;
this.unique = unique;
}
@Override
@ -66,11 +75,27 @@ public class AddressesReadTracePcodeExecutorStatePiece
return data;
}
@Override
public AddressesReadTracePcodeExecutorStatePiece fork() {
return new AddressesReadTracePcodeExecutorStatePiece(data, new HashMap<>(unique));
}
@Override
public void writeDown(PcodeTraceDataAccess into) {
throw new UnsupportedOperationException();
}
@Override
protected Map<Register, AddressSetView> getRegisterValuesFromSpace(AddressSpace s,
List<Register> registers) {
return Map.of();
}
@Override
public Map<Register, AddressSetView> getRegisterValues() {
return Map.of();
}
@Override
protected AddressSpace getForSpace(AddressSpace space, boolean toWrite) {
return space;

View file

@ -29,4 +29,13 @@ public class BytesTracePcodeExecutorState extends DefaultTracePcodeExecutorState
public BytesTracePcodeExecutorState(PcodeTraceDataAccess data) {
super(new BytesTracePcodeExecutorStatePiece(data));
}
protected BytesTracePcodeExecutorState(TracePcodeExecutorStatePiece<byte[], byte[]> piece) {
super(piece);
}
@Override
public BytesTracePcodeExecutorState fork() {
return new BytesTracePcodeExecutorState(piece.fork());
}
}

View file

@ -16,11 +16,12 @@
package ghidra.pcode.exec.trace;
import java.nio.ByteBuffer;
import java.util.Map;
import generic.ULongSpan;
import generic.ULongSpan.ULongSpanSet;
import ghidra.pcode.exec.AbstractBytesPcodeExecutorStatePiece;
import ghidra.pcode.exec.BytesPcodeExecutorStateSpace;
import ghidra.generic.util.datastruct.SemisparseByteArray;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.trace.BytesTracePcodeExecutorStatePiece.CachedSpace;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.*;
@ -41,11 +42,23 @@ public class BytesTracePcodeExecutorStatePiece
protected static class CachedSpace
extends BytesPcodeExecutorStateSpace<PcodeTraceDataAccess> {
protected final AddressSet written = new AddressSet();
protected final AddressSet written;
public CachedSpace(Language language, AddressSpace space, PcodeTraceDataAccess backing) {
// Backing could be null, so we need language parameter
super(language, space, backing);
this.written = new AddressSet();
}
protected CachedSpace(Language language, AddressSpace space, PcodeTraceDataAccess backing,
SemisparseByteArray bytes, AddressSet written) {
super(language, space, backing, bytes);
this.written = written;
}
@Override
public CachedSpace fork() {
return new CachedSpace(language, space, backing, bytes.fork(), new AddressSet(written));
}
@Override
@ -118,11 +131,22 @@ public class BytesTracePcodeExecutorStatePiece
this.data = data;
}
protected BytesTracePcodeExecutorStatePiece(PcodeTraceDataAccess data,
AbstractSpaceMap<CachedSpace> spaceMap) {
super(data.getLanguage(), spaceMap);
this.data = data;
}
@Override
public PcodeTraceDataAccess getData() {
return data;
}
@Override
public BytesTracePcodeExecutorStatePiece fork() {
return new BytesTracePcodeExecutorStatePiece(data, spaceMap.fork());
}
@Override
public void writeDown(PcodeTraceDataAccess into) {
if (into.getLanguage() != language) {
@ -139,6 +163,14 @@ public class BytesTracePcodeExecutorStatePiece
*/
protected class TraceBackedSpaceMap
extends CacheingSpaceMap<PcodeTraceDataAccess, CachedSpace> {
public TraceBackedSpaceMap() {
super();
}
protected TraceBackedSpaceMap(Map<AddressSpace, CachedSpace> spaces) {
super(spaces);
}
@Override
protected PcodeTraceDataAccess getBacking(AddressSpace space) {
return data;
@ -148,6 +180,16 @@ public class BytesTracePcodeExecutorStatePiece
protected CachedSpace newSpace(AddressSpace space, PcodeTraceDataAccess backing) {
return new CachedSpace(language, space, backing);
}
@Override
public TraceBackedSpaceMap fork() {
return new TraceBackedSpaceMap(fork(spaces));
}
@Override
public CachedSpace fork(CachedSpace s) {
return s.fork();
}
}
@Override

View file

@ -44,6 +44,11 @@ public class DefaultTracePcodeExecutorState<T> extends DefaultPcodeExecutorState
return piece.getData();
}
@Override
public DefaultTracePcodeExecutorState<T> fork() {
return new DefaultTracePcodeExecutorState<>(piece.fork());
}
@Override
public void writeDown(PcodeTraceDataAccess into) {
piece.writeDown(into);

View file

@ -60,6 +60,11 @@ public class DirectBytesTracePcodeExecutorState extends DefaultTracePcodeExecuto
super(new DirectBytesTracePcodeExecutorStatePiece(data));
}
protected DirectBytesTracePcodeExecutorState(
TracePcodeExecutorStatePiece<byte[], byte[]> piece) {
super(piece);
}
/**
* Create the state
*
@ -83,4 +88,9 @@ public class DirectBytesTracePcodeExecutorState extends DefaultTracePcodeExecuto
return new PairedPcodeExecutorState<>(this,
new TraceMemoryStatePcodeExecutorStatePiece(getData()));
}
@Override
public DirectBytesTracePcodeExecutorState fork() {
return new DirectBytesTracePcodeExecutorState(piece.fork());
}
}

View file

@ -16,6 +16,8 @@
package ghidra.pcode.exec.trace;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import javax.help.UnsupportedOperationException;
@ -27,6 +29,7 @@ import ghidra.pcode.exec.PcodeArithmetic.Purpose;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register;
import ghidra.program.model.mem.MemBuffer;
import ghidra.trace.model.memory.TraceMemoryState;
@ -48,7 +51,7 @@ public class DirectBytesTracePcodeExecutorStatePiece
protected final PcodeTraceDataAccess data;
protected final SemisparseByteArray unique = new SemisparseByteArray();
protected final SemisparseByteArray unique;
/**
* Construct a piece
@ -57,9 +60,10 @@ public class DirectBytesTracePcodeExecutorStatePiece
* @param data the trace-data access shim
*/
protected DirectBytesTracePcodeExecutorStatePiece(PcodeArithmetic<byte[]> arithmetic,
PcodeTraceDataAccess data) {
PcodeTraceDataAccess data, SemisparseByteArray unique) {
super(data.getLanguage(), arithmetic, arithmetic);
this.data = data;
this.unique = unique;
}
/**
@ -68,7 +72,7 @@ public class DirectBytesTracePcodeExecutorStatePiece
* @param data the trace-data access shim
*/
public DirectBytesTracePcodeExecutorStatePiece(PcodeTraceDataAccess data) {
this(BytesPcodeArithmetic.forLanguage(data.getLanguage()), data);
this(BytesPcodeArithmetic.forLanguage(data.getLanguage()), data, new SemisparseByteArray());
}
@Override
@ -76,6 +80,11 @@ public class DirectBytesTracePcodeExecutorStatePiece
return data;
}
@Override
public DirectBytesTracePcodeExecutorStatePiece fork() {
return new DirectBytesTracePcodeExecutorStatePiece(arithmetic, data, unique.fork());
}
/**
* Create a state which computes an expression's {@link TraceMemoryState} as an auxiliary
* attribute
@ -129,6 +138,17 @@ public class DirectBytesTracePcodeExecutorStatePiece
return buf.array();
}
@Override
protected Map<Register, byte[]> getRegisterValuesFromSpace(AddressSpace s,
List<Register> registers) {
return Map.of();
}
@Override
public Map<Register, byte[]> getRegisterValues() {
return Map.of();
}
@Override
public MemBuffer getConcreteBuffer(Address address, Purpose purpose) {
throw new UnsupportedOperationException();

View file

@ -30,30 +30,30 @@ import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
public class PairedTracePcodeExecutorState<L, R> extends PairedPcodeExecutorState<L, R>
implements TracePcodeExecutorState<Pair<L, R>> {
private final TracePcodeExecutorStatePiece<L, L> left;
private final TracePcodeExecutorStatePiece<L, R> right;
private final PairedTracePcodeExecutorStatePiece<L, L, R> piece;
public PairedTracePcodeExecutorState(PairedTracePcodeExecutorStatePiece<L, L, R> piece) {
super(piece);
this.left = piece.getLeft();
this.right = piece.getRight();
this.piece = piece;
}
public PairedTracePcodeExecutorState(TracePcodeExecutorState<L> left,
TracePcodeExecutorStatePiece<L, R> right) {
super(left, right);
this.left = left;
this.right = right;
this(new PairedTracePcodeExecutorStatePiece<>(left, right));
}
@Override
public PcodeTraceDataAccess getData() {
return left.getData();
return piece.getData();
}
@Override
public PairedTracePcodeExecutorState<L, R> fork() {
return new PairedTracePcodeExecutorState<>(piece.fork());
}
@Override
public void writeDown(PcodeTraceDataAccess into) {
left.writeDown(into);
right.writeDown(into);
piece.writeDown(into);
}
}

View file

@ -56,6 +56,12 @@ public class PairedTracePcodeExecutorStatePiece<A, L, R>
return left.getData();
}
@Override
public PairedTracePcodeExecutorStatePiece<A, L, R> fork() {
return new PairedTracePcodeExecutorStatePiece<>(left.fork(), right.fork(),
getAddressArithmetic(), getArithmetic());
}
@Override
public void writeDown(PcodeTraceDataAccess into) {
left.writeDown(into);

View file

@ -31,4 +31,14 @@ public class RequireHasKnownTraceCachedWriteBytesPcodeExecutorState
public RequireHasKnownTraceCachedWriteBytesPcodeExecutorState(PcodeTraceDataAccess data) {
super(new RequireHasKnownTraceCachedWriteBytesPcodeExecutorStatePiece(data));
}
protected RequireHasKnownTraceCachedWriteBytesPcodeExecutorState(
TracePcodeExecutorStatePiece<byte[], byte[]> piece) {
super(piece);
}
@Override
public RequireHasKnownTraceCachedWriteBytesPcodeExecutorState fork() {
return new RequireHasKnownTraceCachedWriteBytesPcodeExecutorState(piece.fork());
}
}

View file

@ -40,6 +40,17 @@ public class RequireHasKnownTraceCachedWriteBytesPcodeExecutorStatePiece
super(data);
}
protected RequireHasKnownTraceCachedWriteBytesPcodeExecutorStatePiece(PcodeTraceDataAccess data,
AbstractSpaceMap<CachedSpace> spaceMap) {
super(data, spaceMap);
}
@Override
public RequireHasKnownTraceCachedWriteBytesPcodeExecutorStatePiece fork() {
return new RequireHasKnownTraceCachedWriteBytesPcodeExecutorStatePiece(data,
spaceMap.fork());
}
@Override
protected AddressSetView getKnown(PcodeTraceDataAccess backing) {
return backing.getKnownBefore();

View file

@ -31,4 +31,14 @@ public class RequireIsKnownTraceCachedWriteBytesPcodeExecutorState
public RequireIsKnownTraceCachedWriteBytesPcodeExecutorState(PcodeTraceDataAccess data) {
super(new RequireIsKnownTraceCachedWriteBytesPcodeExecutorStatePiece(data));
}
protected RequireIsKnownTraceCachedWriteBytesPcodeExecutorState(
TracePcodeExecutorStatePiece<byte[], byte[]> piece) {
super(piece);
}
@Override
public RequireIsKnownTraceCachedWriteBytesPcodeExecutorState fork() {
return new RequireIsKnownTraceCachedWriteBytesPcodeExecutorState(piece.fork());
}
}

View file

@ -16,6 +16,7 @@
package ghidra.pcode.exec.trace;
import ghidra.pcode.exec.AccessPcodeExecutionException;
import ghidra.pcode.exec.PcodeExecutorStatePiece;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.*;
import ghidra.trace.model.memory.TraceMemorySpace;
@ -34,6 +35,17 @@ public class RequireIsKnownTraceCachedWriteBytesPcodeExecutorStatePiece
super(data);
}
protected RequireIsKnownTraceCachedWriteBytesPcodeExecutorStatePiece(PcodeTraceDataAccess data,
AbstractSpaceMap<CachedSpace> spaceMap) {
super(data, spaceMap);
}
@Override
public RequireIsKnownTraceCachedWriteBytesPcodeExecutorStatePiece fork() {
return new RequireIsKnownTraceCachedWriteBytesPcodeExecutorStatePiece(data,
spaceMap.fork());
}
/**
* Construct a piece
*

View file

@ -15,6 +15,8 @@
*/
package ghidra.pcode.exec.trace;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import generic.ULongSpan;
@ -23,6 +25,7 @@ import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.mem.MemBuffer;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
@ -42,7 +45,7 @@ import ghidra.trace.model.memory.TraceMemoryState;
public class TraceMemoryStatePcodeExecutorStatePiece extends
AbstractLongOffsetPcodeExecutorStatePiece<byte[], TraceMemoryState, AddressSpace> {
protected final MutableULongSpanMap<TraceMemoryState> unique = new DefaultULongSpanMap<>();
protected final MutableULongSpanMap<TraceMemoryState> unique;
protected final PcodeTraceDataAccess data;
/**
@ -55,6 +58,22 @@ public class TraceMemoryStatePcodeExecutorStatePiece extends
BytesPcodeArithmetic.forLanguage(data.getLanguage()),
TraceMemoryStatePcodeArithmetic.INSTANCE);
this.data = data;
this.unique = new DefaultULongSpanMap<>();
}
protected TraceMemoryStatePcodeExecutorStatePiece(PcodeTraceDataAccess data,
MutableULongSpanMap<TraceMemoryState> unique) {
super(data.getLanguage(), BytesPcodeArithmetic.forLanguage(data.getLanguage()),
TraceMemoryStatePcodeArithmetic.INSTANCE);
this.data = data;
this.unique = unique;
}
@Override
public TraceMemoryStatePcodeExecutorStatePiece fork() {
MutableULongSpanMap<TraceMemoryState> copyUnique = new DefaultULongSpanMap<>();
copyUnique.putAll(unique);
return new TraceMemoryStatePcodeExecutorStatePiece(data, copyUnique);
}
protected AddressRange range(AddressSpace space, long offset, int size) {
@ -107,6 +126,17 @@ public class TraceMemoryStatePcodeExecutorStatePiece extends
return TraceMemoryState.UNKNOWN;
}
@Override
protected Map<Register, TraceMemoryState> getRegisterValuesFromSpace(AddressSpace s,
List<Register> registers) {
return Map.of();
}
@Override
public Map<Register, TraceMemoryState> getRegisterValues() {
return Map.of();
}
@Override
public MemBuffer getConcreteBuffer(Address address, Purpose purpose) {
throw new ConcretionError("Cannot make TraceMemoryState into a concrete buffer", purpose);

View file

@ -23,13 +23,14 @@ import ghidra.pcode.exec.trace.data.PcodeTraceDataAccess;
*
* <p>
* In particular, because this derives from {@link TracePcodeExecutorStatePiece}, such states are
* required to implement {@link #writeDown(PcodeTraceDataAccess)}. This interface also
* derives from {@link PcodeExecutorState} so that, as the name implies, they can be used where a
* state is required.
* required to implement {@link #writeDown(PcodeTraceDataAccess)}. This interface also derives from
* {@link PcodeExecutorState} so that, as the name implies, they can be used where a state is
* required.
*
* @param <T> the type of values
*/
public interface TracePcodeExecutorState<T>
extends PcodeExecutorState<T>, TracePcodeExecutorStatePiece<T, T> {
// Nothing to add. Simply a composition of interfaces.
@Override
TracePcodeExecutorState<T> fork();
}

View file

@ -38,6 +38,9 @@ public interface TracePcodeExecutorStatePiece<A, T> extends PcodeExecutorStatePi
*/
PcodeTraceDataAccess getData();
@Override
TracePcodeExecutorStatePiece<A, T> fork();
/**
* Write the accumulated values (cache) into the given trace
*

View file

@ -256,7 +256,7 @@ public class UndefinedDBTraceData implements DBTraceDataAdapter, DBTraceSpaceKey
}
@Override
public Data getComponentContaining(int offset) {
public TraceData getComponentContaining(int offset) {
return null;
}

View file

@ -42,7 +42,8 @@ public interface DBTraceDelegatingManager<M> {
default void checkIsInMemory(AddressSpace space) {
if (!space.isMemorySpace() && space != Address.NO_ADDRESS.getAddressSpace()) {
throw new IllegalArgumentException("Address must be in memory or NO_ADDRESS");
throw new IllegalArgumentException(
"Address must be in memory or NO_ADDRESS. Got " + space);
}
}

View file

@ -29,6 +29,9 @@ public interface TraceData extends TraceCodeUnit, Data {
@Override
TraceData getComponentAt(int offset);
@Override
TraceData getComponentContaining(int offset);
@Override
TraceData getComponent(int[] componentPath);

View file

@ -333,6 +333,29 @@ public interface TraceMemoryOperations {
Collection<Entry<TraceAddressSnapRange, TraceMemoryState>> getStates(long snap,
AddressRange range);
/**
* Check if a range addresses are all known
*
* @param snap the time
* @param range the range to examine
* @return true if the entire range is {@link TraceMemoryState#KNOWN}
*/
default boolean isKnown(long snap, AddressRange range) {
Collection<Entry<TraceAddressSnapRange, TraceMemoryState>> states = getStates(snap, range);
if (states.isEmpty()) {
return false;
}
if (states.size() != 1) {
return false;
}
AddressRange entryRange = states.iterator().next().getKey().getRange();
if (!entryRange.contains(range.getMinAddress()) ||
!entryRange.contains(range.getMaxAddress())) {
return false;
}
return true;
}
/**
* Break a range of addresses into smaller ranges each mapped to its most recent state at the
* given time

View file

@ -118,6 +118,9 @@ public interface Scheduler {
TickStep slice = nextSlice(trace);
eventThread = slice.getThread(tm, eventThread);
emuThread = machine.getThread(eventThread.getPath(), true);
if (emuThread.getFrame() != null) {
emuThread.finishInstruction();
}
for (int i = 0; i < slice.tickCount; i++) {
monitor.checkCanceled();
emuThread.stepInstruction();

View file

@ -200,7 +200,7 @@ public enum TraceRegisterUtils {
public static void requireByteBound(Register register) {
if (!isByteBound(register)) {
throw new IllegalArgumentException(
"Cannot work with sub-byte registers. Consider a parent, instead.");
"Cannot work with sub-byte registers. Consider a parent instead.");
}
}
}