mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-5266: Only track on user click or address change.
This commit is contained in:
parent
2a628178b3
commit
5d71f073f4
10 changed files with 135 additions and 32 deletions
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>: 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
|
||||
<strong>Auto-Track</strong> drop-down in the top right of the Dynamic
|
||||
Listing to <strong>Do Not Track</strong> while you’re 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">
|
||||
|
|
|
@ -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?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue