GP-5266: Only track on user click or address change.

This commit is contained in:
Dan 2025-01-15 13:56:40 -05:00 committed by Ryan Kurtz
parent 2a628178b3
commit 5d71f073f4
10 changed files with 135 additions and 32 deletions

View file

@ -66,7 +66,7 @@ public class DebuggerCoordinates {
private static final String KEY_FRAME = "Frame";
private static final String KEY_OBJ_PATH = "ObjectPath";
public static boolean equalsIgnoreRecorderAndView(DebuggerCoordinates a,
public static boolean equalsIgnoreTargetAndView(DebuggerCoordinates a,
DebuggerCoordinates b) {
if (!Objects.equals(a.trace, b.trace)) {
return false;
@ -417,6 +417,36 @@ public class DebuggerCoordinates {
newFrame, newPath);
}
/**
* Checks if the given coordinates are the same as this but with an extra or differing patch.
*
* @param that the other coordinates
* @return true if the difference is only in the final patch step
*/
public boolean differsOnlyByPatch(DebuggerCoordinates that) {
if (!Objects.equals(this.trace, that.trace)) {
return false;
}
if (!Objects.equals(this.platform, that.platform)) {
return false;
}
if (!Objects.equals(this.thread, that.thread)) {
return false;
}
// Consider defaults
if (!Objects.equals(this.getFrame(), that.getFrame())) {
return false;
}
if (!Objects.equals(this.getObject(), that.getObject())) {
return false;
}
if (!this.getTime().differsOnlyByPatch(that.getTime())) {
return false;
}
return true;
}
public DebuggerCoordinates frame(int newFrame) {
if (trace == null) {
return NOWHERE;
@ -621,7 +651,11 @@ public class DebuggerCoordinates {
if (registerContainer != null) {
return registerContainer;
}
return registerContainer = getObject().findRegisterContainer(getFrame());
TraceObject object = getObject();
if (object == null) {
return null;
}
return registerContainer = object.findRegisterContainer(getFrame());
}
public synchronized long getViewSnap() {

View file

@ -52,6 +52,10 @@ public class DebuggerTrackLocationTrait {
protected static final AutoConfigState.ClassHandler<DebuggerTrackLocationTrait> CONFIG_STATE_HANDLER =
AutoConfigState.wireHandler(DebuggerTrackLocationTrait.class, MethodHandles.lookup());
public enum TrackCause {
USER, DB_CHANGE, NAVIGATION, EMU_PATCH, SPEC_CHANGE_API;
}
protected class ForTrackingListener extends TraceDomainObjectListener {
public ForTrackingListener() {
@ -68,7 +72,7 @@ public class DebuggerTrackLocationTrait {
if (!tracker.affectedByBytesChange(space, range, current)) {
return;
}
doTrack();
doTrack(TrackCause.DB_CHANGE);
}
private void stackChanged(TraceStack stack) {
@ -79,7 +83,7 @@ public class DebuggerTrackLocationTrait {
if (!tracker.affectedByStackChange(stack, current)) {
return;
}
doTrack();
doTrack(TrackCause.DB_CHANGE);
}
}
@ -188,11 +192,11 @@ public class DebuggerTrackLocationTrait {
public void setSpec(LocationTrackingSpec spec) {
if (action == null) {
// It might if the client doesn't need a new button, e.g., TraceDiff
doSetSpec(spec);
doSetSpec(spec, TrackCause.SPEC_CHANGE_API);
}
else if (!hasSpec(spec)) {
Msg.warn(this, "No action state for given tracking spec: " + spec);
doSetSpec(spec);
doSetSpec(spec, TrackCause.SPEC_CHANGE_API);
}
else {
action.setCurrentActionStateByUserData(spec);
@ -234,21 +238,21 @@ public class DebuggerTrackLocationTrait {
}
protected void clickedSpecButton(ActionContext ctx) {
doTrack();
doTrack(TrackCause.USER);
}
protected void clickedSpecMenu(ActionState<LocationTrackingSpec> newState,
EventTrigger trigger) {
doSetSpec(newState.getUserData());
doSetSpec(newState.getUserData(), TrackCause.USER);
}
protected void doSetSpec(LocationTrackingSpec spec) {
protected void doSetSpec(LocationTrackingSpec spec, TrackCause cause) {
if (this.spec != spec) {
this.spec = spec;
this.tracker = spec.getTracker();
specChanged(spec);
}
doTrack();
doTrack(cause);
}
protected ProgramLocation computeTrackedLocation() {
@ -282,9 +286,15 @@ public class DebuggerTrackLocationTrait {
return spec.getLocationLabel() + " = " + trackedLocation.getByteAddress();
}
protected void doTrack() {
protected void doTrack(TrackCause cause) {
try {
trackedLocation = computeTrackedLocation();
ProgramLocation newLocation = computeTrackedLocation();
if (Objects.equals(newLocation, trackedLocation)) {
if (cause == TrackCause.DB_CHANGE || cause == TrackCause.EMU_PATCH) {
return;
}
}
trackedLocation = newLocation;
locationTracked();
}
catch (Throwable ex) {
@ -315,11 +325,12 @@ public class DebuggerTrackLocationTrait {
if (doListeners) {
removeOldListeners();
}
boolean isPatch = current.differsOnlyByPatch(coordinates);
current = coordinates;
if (doListeners) {
addNewListeners();
}
doTrack();
doTrack(isPatch ? TrackCause.EMU_PATCH : TrackCause.NAVIGATION);
}
public void writeConfigState(SaveState saveState) {

View file

@ -235,7 +235,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
super(DebuggerListingProvider.this.tool, DebuggerListingProvider.this.plugin,
DebuggerListingProvider.this);
getListingPanel().addIndexMapChangeListener(e -> this.doTrack());
getListingPanel().addIndexMapChangeListener(e -> this.doTrack(TrackCause.DB_CHANGE));
}
@Override

View file

@ -90,7 +90,7 @@ public abstract class AbstractQueryTablePanel<T, M extends AbstractQueryTableMod
}
public void goToCoordinates(DebuggerCoordinates coords) {
if (DebuggerCoordinates.equalsIgnoreRecorderAndView(current, coords)) {
if (DebuggerCoordinates.equalsIgnoreTargetAndView(current, coords)) {
return;
}
DebuggerCoordinates previous = current;

View file

@ -234,7 +234,7 @@ public class ObjectsTreePanel extends JPanel {
}
public void goToCoordinates(DebuggerCoordinates coords) {
if (DebuggerCoordinates.equalsIgnoreRecorderAndView(current, coords)) {
if (DebuggerCoordinates.equalsIgnoreTargetAndView(current, coords)) {
return;
}
previous = current;

View file

@ -470,4 +470,25 @@ public class Sequence implements Comparable<Sequence> {
}
return result;
}
public boolean differsOnlyByPatch(Sequence that) {
int size = this.steps.size();
if (size == that.steps.size()) {
if (size == 0) {
return true;
}
if (!this.steps.subList(0, size - 1).equals(that.steps.subList(0, size - 1))) {
return false;
}
Step thisLast = this.steps.getLast();
Step thatLast = that.steps.getLast();
return thisLast.equals(thatLast) ||
thisLast instanceof PatchStep && thatLast instanceof PatchStep;
}
if (size == that.steps.size() - 1) {
Step thatLast = that.steps.getLast();
return thatLast instanceof PatchStep;
}
return false;
}
}

View file

@ -673,4 +673,20 @@ public class TraceSchedule implements Comparable<TraceSchedule> {
public TraceSchedule assumeRecorded() {
return new TraceSchedule(snap, steps, pSteps, Source.RECORD);
}
public boolean differsOnlyByPatch(TraceSchedule that) {
if (this.snap != that.snap) {
return false;
}
if (this.pSteps.isNop() != that.pSteps.isNop()) {
return false;
}
if (this.pSteps.isNop()) {
return this.steps.differsOnlyByPatch(that.steps);
}
if (!this.steps.equals(that.steps)) {
return false;
}
return this.pSteps.differsOnlyByPatch(that.pSteps);
}
}

View file

@ -470,4 +470,37 @@ public class TraceScheduleTest extends AbstractGhidraHeadlessIntegrationTest {
"t0-{r0=0x200000001};t0-{r1l=0x3}", time.toString());
}
}
@Test
public void testDiffersOnlyByPatch() throws Exception {
assertTrue(TraceSchedule.parse("1").differsOnlyByPatch(TraceSchedule.parse("1")));
assertTrue(TraceSchedule.parse("1:1").differsOnlyByPatch(TraceSchedule.parse("1:1")));
assertTrue(TraceSchedule.parse("1:1.1").differsOnlyByPatch(TraceSchedule.parse("1:1.1")));
assertTrue(TraceSchedule.parse("1:1;{r0=1}")
.differsOnlyByPatch(TraceSchedule.parse("1:1;{r0=1}")));
assertTrue(TraceSchedule.parse("1:1.1;{r0=1}")
.differsOnlyByPatch(TraceSchedule.parse("1:1.1;{r0=1}")));
assertFalse(TraceSchedule.parse("1").differsOnlyByPatch(TraceSchedule.parse("1:1")));
assertFalse(TraceSchedule.parse("1:1").differsOnlyByPatch(TraceSchedule.parse("1")));
assertFalse(TraceSchedule.parse("1:1").differsOnlyByPatch(TraceSchedule.parse("1:2")));
assertFalse(TraceSchedule.parse("1:2").differsOnlyByPatch(TraceSchedule.parse("1:1")));
assertFalse(TraceSchedule.parse("1:1").differsOnlyByPatch(TraceSchedule.parse("1:1.1")));
assertFalse(TraceSchedule.parse("1:1.1").differsOnlyByPatch(TraceSchedule.parse("1:1")));
assertTrue(TraceSchedule.parse("1").differsOnlyByPatch(TraceSchedule.parse("1:{r0=1}")));
assertFalse(TraceSchedule.parse("1:{r0=1}").differsOnlyByPatch(TraceSchedule.parse("1")));
assertTrue(
TraceSchedule.parse("1:1").differsOnlyByPatch(TraceSchedule.parse("1:1;{r0=1}")));
assertFalse(
TraceSchedule.parse("1:1;{r0=1}").differsOnlyByPatch(TraceSchedule.parse("1:1")));
assertTrue(
TraceSchedule.parse("1:1.1").differsOnlyByPatch(TraceSchedule.parse("1:1.1;{r0=1}")));
assertFalse(
TraceSchedule.parse("1:1.1;{r0=1}").differsOnlyByPatch(TraceSchedule.parse("1:1.1")));
}
}

View file

@ -295,13 +295,6 @@ section of <code>termmines</code> in the Static Listing, the Dynamic
Listing will follow along showing you the live values in memory. You can
also experiment by placing code units in the Dynamic Listing before
committing to them in the Static Listing.</p>
<p><strong>NOTE</strong>: Theres a known issue with auto-seek obtruding
user navigation in the listings. In most cases, just navigating again
will make it stick. If it becomes a real annoyance, set the
<strong>Auto-Track</strong> drop-down in the top right of the Dynamic
Listing to <strong>Do Not Track</strong> while youre doing static RE.
Be sure to put it back to <strong>Track Program Counter</strong> when
you are done.</p>
<section id="questions" class="level4">
<h4>Questions:</h4>
<ol type="1">

View file

@ -137,11 +137,6 @@ Because you are in a dynamic session, you have an example board to work with.
As you navigate the `.data` section of `termmines` in the Static Listing, the Dynamic Listing will follow along showing you the live values in memory.
You can also experiment by placing code units in the Dynamic Listing before committing to them in the Static Listing.
**NOTE**: There's a known issue with auto-seek obtruding user navigation in the listings.
In most cases, just navigating again will make it stick.
If it becomes a real annoyance, set the **Auto-Track** drop-down in the top right of the Dynamic Listing to **Do Not Track** while you're doing static RE.
Be sure to put it back to **Track Program Counter** when you are done.
#### Questions:
1. How are the cells allocated?