Merge remote-tracking branch 'origin/GP-5229_Dan_fixTreeRegValUpdate'

This commit is contained in:
Ryan Kurtz 2025-01-03 19:56:11 -05:00
commit 11ac891e9c
3 changed files with 77 additions and 5 deletions

View file

@ -340,8 +340,16 @@ public class ObjectTreeModel implements DisplaysModified {
while (ic < current.size() && ig < generated.size()) { while (ic < current.size() && ig < generated.size()) {
GTreeNode nc = current.get(ic); GTreeNode nc = current.get(ic);
GTreeNode ng = generated.get(ig); GTreeNode ng = generated.get(ig);
if (nc == ng) {
ic++;
ig++;
continue;
}
int comp = nc.compareTo(ng); int comp = nc.compareTo(ng);
if (comp == 0) { if (comp == 0) {
// Same path, but not identical. Replace.
addNode(ic + diff, ng);
removeNode(nc);
ic++; ic++;
ig++; ig++;
} }

View file

@ -39,6 +39,7 @@ import ghidra.app.plugin.core.debug.gui.model.ObjectTreeModel.AbstractNode;
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow; import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
import ghidra.app.plugin.core.debug.gui.model.columns.*; import ghidra.app.plugin.core.debug.gui.model.columns.*;
import ghidra.debug.api.tracemgr.DebuggerCoordinates; import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.trace.database.ToyDBTraceBuilder.EventSuspension;
import ghidra.trace.model.Lifespan; import ghidra.trace.model.Lifespan;
import ghidra.trace.model.target.*; import ghidra.trace.model.target.*;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
@ -46,8 +47,8 @@ import ghidra.trace.model.target.iface.TraceObjectEventScope;
import ghidra.trace.model.target.iface.TraceObjectInterface; import ghidra.trace.model.target.iface.TraceObjectInterface;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.schema.SchemaContext; import ghidra.trace.model.target.schema.SchemaContext;
import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName; import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
import ghidra.trace.model.target.schema.XmlSchemaContext;
import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceObjectThread;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
@ -694,6 +695,47 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
assertPathIs(path, 11, 0); assertPathIs(path, 11, 0);
} }
/**
* The trace-rmi handler suspends trace events during a remote transaction. Also, if there are
* sufficient events to overload the queue, the event support with clear them and just issue an
* OBJ_RESTORED event instead. This test ensures we update attributes in the tree when that
* happens.
*/
@Test
public void testTreeTracksChangeAttributeWithEventsSuspended() throws Throwable {
createTraceAndPopulateObjects();
KeyPath path = KeyPath.parse("Processes[0].Threads[2].Bytes");
try (Transaction tx = tb.startTransaction()) {
TraceObject thread =
tb.trace.getObjectManager().getObjectByCanonicalPath(path.parent());
thread.setAttribute(Lifespan.nowOn(0), "Bytes", tb.arr(1, 2, 3, 4));
}
traceManager.activateTrace(tb.trace);
waitForSwing();
runSwing(() -> modelProvider.setShowPrimitivesInTree(true));
waitForTasks();
modelProvider.setPath(path);
waitForTasks();
waitForPass(() -> {
AbstractNode node = modelProvider.objectsTreePanel.treeModel.getNode(path);
assertEquals("<html>Bytes:&nbsp;01:02:03:04", node.getDisplayText());
});
try (Transaction tx = tb.startTransaction(); EventSuspension es = tb.suspendEvents()) {
TraceObject thread =
tb.trace.getObjectManager().getObjectByCanonicalPath(path.parent());
thread.setAttribute(Lifespan.nowOn(0), "Bytes", tb.arr(5, 6, 7, 8));
}
waitForTasks();
waitForPass(() -> {
AbstractNode node = modelProvider.objectsTreePanel.treeModel.getNode(path);
assertEquals("<html>Bytes:&nbsp;05:06:07:08", node.getDisplayText());
});
}
@Test @Test
public void testPanesTrackAddAttribute() throws Throwable { public void testPanesTrackAddAttribute() throws Throwable {
createTraceAndPopulateObjects(); createTraceAndPopulateObjects();
@ -1239,11 +1281,9 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
traceManager.activateTrace(tb.trace); traceManager.activateTrace(tb.trace);
waitForSwing(); waitForSwing();
tb.trace.setEventsEnabled(false); try (Transaction tx = tb.startTransaction(); EventSuspension es = tb.suspendEvents()) {
try (Transaction tx = tb.startTransaction()) {
tb.trace.getTimeManager().getSnapshot(30, true); tb.trace.getTimeManager().getSnapshot(30, true);
} }
tb.trace.setEventsEnabled(true);
waitForDomainObject(tb.trace); waitForDomainObject(tb.trace);
// NB. The plot adds a margin of 1 // NB. The plot adds a margin of 1

View file

@ -56,8 +56,9 @@ import ghidra.trace.model.*;
import ghidra.trace.model.guest.TraceGuestPlatform; import ghidra.trace.model.guest.TraceGuestPlatform;
import ghidra.trace.model.guest.TracePlatform; import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.symbol.TraceReferenceManager; import ghidra.trace.model.symbol.TraceReferenceManager;
import ghidra.trace.model.target.*; import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.target.TraceObject.ConflictResolution; import ghidra.trace.model.target.TraceObject.ConflictResolution;
import ghidra.trace.model.target.TraceObjectValue;
import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.target.path.KeyPath;
import ghidra.trace.model.target.path.PathFilter; import ghidra.trace.model.target.path.PathFilter;
import ghidra.trace.model.thread.TraceObjectThread; import ghidra.trace.model.thread.TraceObjectThread;
@ -432,6 +433,17 @@ public class ToyDBTraceBuilder implements AutoCloseable {
return result.flip(); return result.flip();
} }
public class EventSuspension implements AutoCloseable {
public EventSuspension() {
trace.setEventsEnabled(false);
}
@Override
public void close() {
trace.setEventsEnabled(true);
}
}
/** /**
* Start a transaction on the trace * Start a transaction on the trace
* *
@ -444,6 +456,18 @@ public class ToyDBTraceBuilder implements AutoCloseable {
return trace.openTransaction("Testing"); return trace.openTransaction("Testing");
} }
/**
* Suspend events for the trace
*
* <p>
* Use this in a {@code try-with-resources} block
*
* @return the suspension handle
*/
public EventSuspension suspendEvents() {
return new EventSuspension();
}
/** /**
* Ensure the given bookmark type exists and retrieve it * Ensure the given bookmark type exists and retrieve it
* *