GP-0: Fix tests. Add "requireCanonical" parameter

This commit is contained in:
Dan 2023-02-16 09:21:28 -05:00
parent c198419b7e
commit ab97c34205
13 changed files with 43 additions and 33 deletions

View file

@ -470,7 +470,7 @@ public class ObjectBasedTraceRecorder implements TraceRecorder {
public Set<TargetThread> getLiveTargetThreads() {
return trace.getObjectManager()
.getRootObject()
.querySuccessorsInterface(Lifespan.at(getSnap()), TraceObjectThread.class)
.querySuccessorsInterface(Lifespan.at(getSnap()), TraceObjectThread.class, true)
.map(t -> objectRecorder.getTargetInterface(t.getObject(), TargetThread.class))
.collect(Collectors.toSet());
}
@ -673,9 +673,10 @@ public class ObjectBasedTraceRecorder implements TraceRecorder {
public List<TargetBreakpointSpecContainer> collectBreakpointContainers(TargetThread thread) {
if (thread == null) {
return objectRecorder.collectTargetSuccessors(target,
TargetBreakpointSpecContainer.class);
TargetBreakpointSpecContainer.class, false);
}
return objectRecorder.collectTargetSuccessors(thread, TargetBreakpointSpecContainer.class);
return objectRecorder.collectTargetSuccessors(thread, TargetBreakpointSpecContainer.class,
false);
}
private class BreakpointConvention {
@ -711,7 +712,8 @@ public class ObjectBasedTraceRecorder implements TraceRecorder {
@Override
public List<TargetBreakpointLocation> collectBreakpoints(TargetThread thread) {
if (thread == null) {
return objectRecorder.collectTargetSuccessors(target, TargetBreakpointLocation.class);
return objectRecorder.collectTargetSuccessors(target, TargetBreakpointLocation.class,
true);
}
BreakpointConvention convention = new BreakpointConvention(
objectRecorder.getTraceInterface(thread, TraceObjectThread.class));
@ -725,7 +727,8 @@ public class ObjectBasedTraceRecorder implements TraceRecorder {
@Override
public Set<TraceBreakpointKind> getSupportedBreakpointKinds() {
return objectRecorder.collectTargetSuccessors(target, TargetBreakpointSpecContainer.class)
return objectRecorder
.collectTargetSuccessors(target, TargetBreakpointSpecContainer.class, false)
.stream()
.flatMap(c -> c.getSupportedBreakpointKinds().stream())
.map(k -> TraceRecorder.targetToTraceBreakpointKind(k))
@ -750,7 +753,7 @@ public class ObjectBasedTraceRecorder implements TraceRecorder {
@Override
public CompletableFuture<Boolean> requestFocus(TargetObject focus) {
for (TargetFocusScope scope : objectRecorder.collectTargetSuccessors(target,
TargetFocusScope.class)) {
TargetFocusScope.class, false)) {
if (PathUtils.isAncestor(scope.getPath(), focus.getPath())) {
return scope.requestFocus(focus).thenApply(__ -> true).exceptionally(ex -> {
ex = AsyncUtils.unwrapThrowable(ex);
@ -772,7 +775,7 @@ public class ObjectBasedTraceRecorder implements TraceRecorder {
@Override
public CompletableFuture<Boolean> requestActivation(TargetObject active) {
for (TargetActiveScope scope : objectRecorder.collectTargetSuccessors(target,
TargetActiveScope.class)) {
TargetActiveScope.class, false)) {
if (PathUtils.isAncestor(scope.getPath(), active.getPath())) {
return scope.requestActivation(active).thenApply(__ -> true).exceptionally(ex -> {
ex = AsyncUtils.unwrapThrowable(ex);

View file

@ -314,13 +314,14 @@ class ObjectRecorder {
}
protected <T extends TargetObject> List<T> collectTargetSuccessors(TargetObject targetSeed,
Class<T> targetIf) {
Class<T> targetIf, boolean requireCanonical) {
// TODO: Should this really go through the database?
TraceObject seed = toTrace(targetSeed);
if (seed == null) {
return List.of();
}
return seed.querySuccessorsTargetInterface(Lifespan.at(recorder.getSnap()), targetIf)
return seed.querySuccessorsTargetInterface(Lifespan.at(recorder.getSnap()), targetIf,
requireCanonical)
.map(p -> toTarget(p.getDestination(seed)).as(targetIf))
.collect(Collectors.toList());
}

View file

@ -47,10 +47,9 @@ import ghidra.framework.plugintool.annotation.AutoConfigStateField;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.lifecycle.Internal;
import ghidra.trace.model.Trace;
import ghidra.trace.model.*;
import ghidra.trace.model.Trace.TraceObjectChangeType;
import ghidra.trace.model.Trace.TraceThreadChangeType;
import ghidra.trace.model.TraceDomainObjectListener;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.program.TraceProgramView;
import ghidra.trace.model.program.TraceVariableSnapProgramView;
@ -641,7 +640,13 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
inactive = curForTrace.snapNoResolve(snap);
lastCoordsByTrace.put(trace, inactive);
}
trace.getProgramView().setSnap(snap);
try {
trace.getProgramView().setSnap(snap);
}
catch (TraceClosedException e) {
// Whatever. Presumably, a closed event is already queued....
Msg.warn(this, "Ignoring snapshot advance for closed trace: " + e);
}
firePluginEvent(new TraceInactiveCoordinatesPluginEvent(getName(), inactive));
return;
}

View file

@ -186,13 +186,13 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI
try (UndoableTransaction tid = tb.startTransaction()) {
TraceObject root = om.getRootObject();
for (TraceObject module : (Iterable<TraceObject>) () -> root
.querySuccessorsTargetInterface(Lifespan.at(0), TargetModule.class)
.querySuccessorsTargetInterface(Lifespan.at(0), TargetModule.class, true)
.map(p -> p.getDestination(root))
.iterator()) {
String moduleName = module.getCanonicalPath().index();
Lifespan span = module.getLife().bound();
for (TraceObject section : (Iterable<TraceObject>) () -> module
.querySuccessorsTargetInterface(Lifespan.at(0), TargetSection.class)
.querySuccessorsTargetInterface(Lifespan.at(0), TargetSection.class, true)
.map(p -> p.getDestination(root))
.iterator()) {
String sectionName = section.getCanonicalPath().index();

View file

@ -517,7 +517,7 @@ public class ObjectBasedTraceRecorderTest extends AbstractGhidraHeadedDebuggerGU
TraceObject traceBank = thread.getObject()
.querySuccessorsTargetInterface(Lifespan.at(recorder.getSnap()),
TargetRegisterBank.class)
TargetRegisterBank.class, false)
.map(p -> p.getDestination(thread.getObject()))
.findAny()
.orElseThrow();

View file

@ -618,6 +618,7 @@ public interface TargetObjectSchema {
}
if (sch.getInterfaces().contains(type) && (parentIsCanonical || !requireCanonical)) {
result.addPattern(prefix);
return;
}
if (!visited.add(sch)) {
return;

View file

@ -283,7 +283,7 @@ public class DBTraceObjectBreakpointLocation
return object.getAncestorsRoot(getLifespan(), procMatcher)
.flatMap(proc -> proc.getSource(object)
.querySuccessorsInterface(getLifespan(),
TraceObjectThread.class))
TraceObjectThread.class, true))
.collect(Collectors.toSet());
}
}

View file

@ -226,9 +226,8 @@ public class DBTraceObjectBreakpointSpec
@Override
public Collection<? extends TraceObjectBreakpointLocation> getLocations() {
try (LockHold hold = object.getTrace().lockRead()) {
return object
.querySuccessorsInterface(getLifespan(), TraceObjectBreakpointLocation.class)
.collect(Collectors.toSet());
return object.querySuccessorsInterface(getLifespan(),
TraceObjectBreakpointLocation.class, true).collect(Collectors.toSet());
}
}

View file

@ -242,7 +242,8 @@ public enum DBTraceObjectRegisterSupport {
protected void onSpaceAddedCheckTransferToPlatformRegisters(TracePlatform platform,
TraceObject regContainer, TraceMemorySpace mem) {
for (TraceObjectValPath path : it(
regContainer.querySuccessorsTargetInterface(Lifespan.ALL, TargetRegister.class))) {
regContainer.querySuccessorsTargetInterface(Lifespan.ALL, TargetRegister.class,
true))) {
TraceObject registerObject =
path.getDestination(platform.getTrace().getObjectManager().getRootObject());
onSpaceAddedCheckTransferObjectToPlatformRegister(registerObject, platform, mem);
@ -437,7 +438,7 @@ public enum DBTraceObjectRegisterSupport {
public void onMappingAddedCheckTransferMemoryMapped(TraceObject root,
TraceGuestPlatformMappedRange mapped) {
for (TraceObjectValPath path : it(
root.querySuccessorsTargetInterface(Lifespan.ALL, TargetRegister.class))) {
root.querySuccessorsTargetInterface(Lifespan.ALL, TargetRegister.class, true))) {
TraceObject registerObject = path.getDestination(root);
onMappingAddedCheckTransferRegisterObjectMemoryMapped(registerObject, mapped);
}

View file

@ -240,7 +240,7 @@ public class DBTraceObjectModule implements TraceObjectModule, DBTraceObjectInte
@Override
public Collection<? extends TraceObjectSection> getSections() {
try (LockHold hold = object.getTrace().lockRead()) {
return object.querySuccessorsInterface(getLifespan(), TraceObjectSection.class)
return object.querySuccessorsInterface(getLifespan(), TraceObjectSection.class, true)
.collect(Collectors.toSet());
}
}

View file

@ -93,8 +93,7 @@ public class DBTraceObjectStack implements TraceObjectStack, DBTraceObjectInterf
@Override
public int getDepth() {
try (LockHold hold = object.getTrace().lockRead()) {
return object
.querySuccessorsInterface(computeSpan(), TraceObjectStackFrame.class)
return object.querySuccessorsInterface(computeSpan(), TraceObjectStackFrame.class, true)
.map(f -> f.getLevel())
.reduce(Integer::max)
.map(m -> m + 1)
@ -210,8 +209,7 @@ public class DBTraceObjectStack implements TraceObjectStack, DBTraceObjectInterf
}
protected Stream<TraceObjectStackFrame> doGetFrames(long snap) {
return object
.querySuccessorsInterface(Lifespan.at(snap), TraceObjectStackFrame.class)
return object.querySuccessorsInterface(Lifespan.at(snap), TraceObjectStackFrame.class, true)
.sorted(Comparator.comparing(f -> f.getLevel()));
}

View file

@ -876,16 +876,16 @@ public class DBTraceObject extends DBAnnotatedObject implements TraceObject {
@Override
public Stream<? extends TraceObjectValPath> querySuccessorsTargetInterface(Lifespan span,
Class<? extends TargetObject> targetIf) {
PathMatcher matcher = getTargetSchema().searchFor(targetIf, true);
Class<? extends TargetObject> targetIf, boolean requireCanonical) {
PathMatcher matcher = getTargetSchema().searchFor(targetIf, requireCanonical);
return getSuccessors(span, matcher).filter(p -> isActuallyInterface(p, targetIf));
}
@Override
public <I extends TraceObjectInterface> Stream<I> querySuccessorsInterface(Lifespan span,
Class<I> ifClass) {
return querySuccessorsTargetInterface(span, TraceObjectInterfaceUtils.toTargetIf(ifClass))
.map(p -> p.getDestination(this).queryInterface(ifClass));
Class<I> ifClass, boolean requireCanonical) {
return querySuccessorsTargetInterface(span, TraceObjectInterfaceUtils.toTargetIf(ifClass),
requireCanonical).map(p -> p.getDestination(this).queryInterface(ifClass));
}
protected void doDelete() {

View file

@ -466,10 +466,11 @@ public interface TraceObject extends TraceUniqueObject {
*
* @param span the span which the found paths must intersect
* @param targetIf the target interface class
* @param requireCanonical if the objects must be found within their canonical container
* @return the stream of found paths to values
*/
Stream<? extends TraceObjectValPath> querySuccessorsTargetInterface(Lifespan span,
Class<? extends TargetObject> targetIf);
Class<? extends TargetObject> targetIf, boolean requireCanonical);
/**
* Search for successors providing the given interface and retrieve those interfaces
@ -477,10 +478,11 @@ public interface TraceObject extends TraceUniqueObject {
* @param <I> the interface type
* @param span the span which the found objects must intersect
* @param ifClass the interface class
* @param requireCanonical if the objects must be found within their canonical container
* @return the stream of interfaces
*/
<I extends TraceObjectInterface> Stream<I> querySuccessorsInterface(Lifespan span,
Class<I> ifClass);
Class<I> ifClass, boolean requireCanonical);
/**
* Delete this object along with parent and child value entries referring to it