diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html index ff1c20b779..3b590a8135 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerListingPlugin/DebuggerListingPlugin.html @@ -108,6 +108,19 @@ meaning may vary among platforms. While there may be some nuances to the register value, the value recorded in the stack should indicate the next instruction to be executed. +
- * TODO: Some of these should be configurable, and permit multiple instances, so that common
- * configurations can be saved. The most obvious use case would be a SLEIGH expression. A user may
- * want 3 different common expressions readily available in the drop-down list.
+ * TODO: Some of these should be configurable and permit multiple instances so that common
+ * configurations can be saved. The most obvious use case would be a Sleigh expression. A user may
+ * want 3 different common expressions readily available in the drop-down list. It might make sense
+ * to generate a tracking specification from each Watch.
*/
public interface LocationTrackingSpec extends ExtensionPoint {
- class Private {
+ enum Private {
+ INSTANCE;
+
private final Map
+ * If the space models memory, the thread and frame are not considered, in case, e.g., the
+ * tracked register is memory-mapped. If the space models registers, the thread and frame are
+ * considered and must match those given in the coordinates. Whatever the case, the span must
+ * include the snap of the coordinates. Otherwise, the change is not considered current.
+ *
+ * @param space the trace-space, giving thread, frame, and address space
+ * @param range the address range and time span of the change
+ * @param current the current coordinates
+ * @return true if the change affects the tracked address for the given coordinates
+ */
static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range,
DebuggerCoordinates current) {
- if (space == null || space.getThread() != current.getThread()) {
+ if (space == null) {
return false;
}
- if (space.getFrameLevel() != current.getFrame()) {
- return false;
+ if (!space.getAddressSpace().isMemorySpace()) {
+ TraceMemorySpace memSpace = current.getTrace()
+ .getMemoryManager()
+ .getMemoryRegisterSpace(current.getThread(), current.getFrame(), false);
+ if (memSpace == null || memSpace.getAddressSpace() != space.getAddressSpace()) {
+ return false;
+ }
}
if (!range.getLifespan().contains(current.getSnap())) {
return false;
@@ -88,22 +112,54 @@ public interface LocationTrackingSpec extends ExtensionPoint {
return true;
}
+ /**
+ * Get the specification for the given configuration name
+ *
+ * @param name the name
+ * @return the spec, or null
+ */
static LocationTrackingSpec fromConfigName(String name) {
synchronized (PRIVATE) {
return PRIVATE.specsByName.get(name);
}
}
+ /**
+ * Get a copy of all the known specifications
+ *
+ * @return the specifications by configuration name
+ */
static Map
+ * This is the value stored in configuration files to identify this specification
+ *
+ * @return the configuration name
+ */
String getConfigName();
+ /**
+ * A human-readable name for this specification
+ *
+ *
+ * This is the text displayed in menus
+ *
+ * @return the menu name
+ */
String getMenuName();
+ /**
+ * Get the icon for this specification
+ *
+ * @return the icon
+ */
Icon getMenuIcon();
/**
@@ -120,15 +176,16 @@ public interface LocationTrackingSpec extends ExtensionPoint {
*
* If the coordinates indicate emulation, i.e., the schedule is non-empty, the trace manager
* will already have performed the emulation and stored the results in a "scratch" snap. In
- * general, the location should be computed using that snap (@code emuSnap) rather than the one
- * indicated in {@code coordinates}.
+ * general, the location should be computed using that snap, i.e.,
+ * {@link DebuggerCoordinates#getViewSnap()} rather than {@link DebuggerCoordinates#getSnap()}.
+ * The address returned must be in the host platform's language, i.e., please use
+ * {@link TracePlatform#mapGuestToHost(Address)}.
*
* @param tool the tool containing the provider
* @param coordinates the trace, thread, snap, etc., of the tool
- * @param emuSnap the "scratch" snap storing emulated state
* @return the address to navigate to
*/
- Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, long emuSnap);
+ Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates);
// TODO: Is there a way to generalize these so that other dependencies need not
// have their own bespoke methods?
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java
index f0df0c5f50..e013e2a62c 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java
@@ -49,8 +49,7 @@ public class NoneLocationTrackingSpec implements LocationTrackingSpec {
}
@Override
- public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates,
- long emuSnap) {
+ public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
return null;
}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByRegisterLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByRegisterLocationTrackingSpec.java
new file mode 100644
index 0000000000..400e0b7f01
--- /dev/null
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByRegisterLocationTrackingSpec.java
@@ -0,0 +1,57 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.plugin.core.debug.gui.action;
+
+import javax.swing.Icon;
+
+import ghidra.app.plugin.core.debug.DebuggerCoordinates;
+import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
+import ghidra.program.model.address.AddressSpace;
+import ghidra.program.model.lang.Register;
+import ghidra.trace.model.guest.TracePlatform;
+
+public class PCByRegisterLocationTrackingSpec implements RegisterLocationTrackingSpec {
+ public static final String CONFIG_NAME = "TRACK_PC_BY_REGISTER";
+
+ @Override
+ public String getConfigName() {
+ return CONFIG_NAME;
+ }
+
+ @Override
+ public String getMenuName() {
+ return TrackLocationAction.NAME_PC_BY_REGISTER;
+ }
+
+ @Override
+ public Icon getMenuIcon() {
+ return TrackLocationAction.ICON_PC_BY_REGISTER;
+ }
+
+ @Override
+ public Register computeRegister(DebuggerCoordinates coordinates) {
+ TracePlatform platform = coordinates.getPlatform();
+ if (platform == null) {
+ return null;
+ }
+ return platform.getLanguage().getProgramCounter();
+ }
+
+ @Override
+ public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) {
+ return coordinates.getPlatform().getLanguage().getDefaultSpace();
+ }
+}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java
new file mode 100644
index 0000000000..ad69988204
--- /dev/null
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCByStackLocationTrackingSpec.java
@@ -0,0 +1,96 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.app.plugin.core.debug.gui.action;
+
+import javax.swing.Icon;
+
+import ghidra.app.plugin.core.debug.DebuggerCoordinates;
+import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
+import ghidra.framework.plugintool.PluginTool;
+import ghidra.program.model.address.Address;
+import ghidra.trace.model.Trace;
+import ghidra.trace.model.TraceAddressSnapRange;
+import ghidra.trace.model.stack.TraceStack;
+import ghidra.trace.model.stack.TraceStackFrame;
+import ghidra.trace.model.thread.TraceThread;
+import ghidra.trace.util.TraceAddressSpace;
+
+public class PCByStackLocationTrackingSpec implements LocationTrackingSpec {
+ public static final String CONFIG_NAME = "TRACK_PC_BY_STACK";
+
+ @Override
+ public String getConfigName() {
+ return CONFIG_NAME;
+ }
+
+ @Override
+ public String getMenuName() {
+ return TrackLocationAction.NAME_PC_BY_STACK;
+ }
+
+ @Override
+ public Icon getMenuIcon() {
+ return TrackLocationAction.ICON_PC_BY_STACK;
+ }
+
+ @Override
+ public String computeTitle(DebuggerCoordinates coordinates) {
+ return "Stack's PC";
+ }
+
+ @Override
+ public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
+ Trace trace = coordinates.getTrace();
+ TraceThread thread = coordinates.getThread();
+ long snap = coordinates.getSnap();
+ TraceStack stack = trace.getStackManager().getLatestStack(thread, snap);
+ if (stack == null) {
+ return null;
+ }
+ int level = coordinates.getFrame();
+ TraceStackFrame frame = stack.getFrame(level, false);
+ if (frame == null) {
+ return null;
+ }
+ return frame.getProgramCounter(snap);
+ }
+
+ // Note it does no good to override affectByRegChange. It must do what we'd avoid anyway.
+ @Override
+ public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) {
+ if (stack.getThread() != coordinates.getThread()) {
+ return false;
+ }
+ if (!coordinates.getTime().isSnapOnly()) {
+ return false;
+ }
+ // TODO: Would be nice to have stack lifespan...
+ // TODO: It does in objects mode. Leave until old code is removed.
+ TraceStack curStack = coordinates.getTrace()
+ .getStackManager()
+ .getLatestStack(stack.getThread(), coordinates.getSnap());
+ if (stack != curStack) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean affectedByRegisterChange(TraceAddressSpace space, TraceAddressSnapRange range,
+ DebuggerCoordinates coordinates) {
+ return false;
+ }
+}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java
index 0da99ed8b0..783ac0bd2b 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java
@@ -21,16 +21,18 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
-import ghidra.program.model.address.AddressSpace;
-import ghidra.program.model.lang.Register;
-import ghidra.trace.model.Trace;
+import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.stack.TraceStack;
-import ghidra.trace.model.stack.TraceStackFrame;
-import ghidra.trace.model.thread.TraceThread;
+import ghidra.trace.util.TraceAddressSpace;
-public class PCLocationTrackingSpec implements RegisterLocationTrackingSpec {
+public class PCLocationTrackingSpec implements LocationTrackingSpec {
public static final String CONFIG_NAME = "TRACK_PC";
+ private static final PCByRegisterLocationTrackingSpec BY_REG =
+ new PCByRegisterLocationTrackingSpec();
+ private static final PCByStackLocationTrackingSpec BY_STACK =
+ new PCByStackLocationTrackingSpec();
+
@Override
public String getConfigName() {
return CONFIG_NAME;
@@ -47,63 +49,30 @@ public class PCLocationTrackingSpec implements RegisterLocationTrackingSpec {
}
@Override
- public Register computeRegister(DebuggerCoordinates coordinates) {
- Trace trace = coordinates.getTrace();
- if (trace == null) {
- return null;
- }
- return trace.getBaseLanguage().getProgramCounter();
+ public String computeTitle(DebuggerCoordinates coordinates) {
+ return "Auto PC";
}
@Override
- public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) {
- return coordinates.getTrace().getBaseLanguage().getDefaultSpace();
- }
-
- public Address computePCViaStack(DebuggerCoordinates coordinates) {
- Trace trace = coordinates.getTrace();
- TraceThread thread = coordinates.getThread();
- long snap = coordinates.getSnap();
- TraceStack stack = trace.getStackManager().getLatestStack(thread, snap);
- if (stack == null) {
- return null;
- }
- int level = coordinates.getFrame();
- TraceStackFrame frame = stack.getFrame(level, false);
- if (frame == null) {
- return null;
- }
- return frame.getProgramCounter(snap);
- }
-
- @Override
- public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates,
- long emuSnap) {
+ public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
if (coordinates.getTime().isSnapOnly()) {
- Address pc = computePCViaStack(coordinates);
+ Address pc = BY_STACK.computeTraceAddress(tool, coordinates);
if (pc != null) {
return pc;
}
}
- return RegisterLocationTrackingSpec.super.computeTraceAddress(tool, coordinates, emuSnap);
+ return BY_REG.computeTraceAddress(tool, coordinates);
}
// Note it does no good to override affectByRegChange. It must do what we'd avoid anyway.
@Override
public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) {
- if (stack.getThread() != coordinates.getThread()) {
- return false;
- }
- if (!coordinates.getTime().isSnapOnly()) {
- return false;
- }
- // TODO: Would be nice to have stack lifespan...
- TraceStack curStack = coordinates.getTrace()
- .getStackManager()
- .getLatestStack(stack.getThread(), coordinates.getSnap());
- if (stack != curStack) {
- return false;
- }
- return true;
+ return BY_STACK.affectedByStackChange(stack, coordinates);
+ }
+
+ @Override
+ public boolean affectedByRegisterChange(TraceAddressSpace space, TraceAddressSnapRange range,
+ DebuggerCoordinates coordinates) {
+ return BY_REG.affectedByRegisterChange(space, range, coordinates);
}
}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java
index cbb00c1a1e..6583f9f2cd 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java
@@ -22,12 +22,12 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange;
+import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace;
-import ghidra.trace.util.TraceRegisterUtils;
// TODO: Use this, or allow arbitrary expressions
public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
@@ -45,10 +45,11 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
}
@Override
- default Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates,
- long emuSnap) {
+ default Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
Trace trace = coordinates.getTrace();
+ TracePlatform platform = coordinates.getPlatform();
TraceThread thread = coordinates.getThread();
+ long viewSnap = coordinates.getViewSnap();
long snap = coordinates.getSnap();
int frame = coordinates.getFrame();
Register reg = computeRegister(coordinates);
@@ -64,19 +65,19 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
return null;
}
RegisterValue value;
- if (regs.getState(emuSnap, reg) == TraceMemoryState.KNOWN) {
- value = regs.getValue(emuSnap, reg);
+ if (regs.getState(platform, viewSnap, reg) == TraceMemoryState.KNOWN) {
+ value = regs.getValue(platform, viewSnap, reg);
}
else {
- value = regs.getValue(snap, reg);
+ value = regs.getValue(platform, snap, reg);
}
if (value == null) {
return null;
}
// TODO: Action to select the address space
// Could use code unit, but that can't specify space, yet, either....
- return computeDefaultAddressSpace(coordinates)
- .getAddress(value.getUnsignedValue().longValue(), true);
+ return platform.mapGuestToHost(computeDefaultAddressSpace(coordinates)
+ .getAddress(value.getUnsignedValue().longValue(), true));
}
@Override
@@ -89,7 +90,9 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
if (register == null) {
return false;
}
- AddressRange regRng = TraceRegisterUtils.rangeForRegister(register);
+ AddressSpace as = space.getAddressSpace();
+ AddressRange regRng = coordinates.getPlatform()
+ .getConventionalRegisterRange(as.isRegisterSpace() ? as : null, register);
return range.getRange().intersects(regRng);
}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java
index 922db2fbf3..b38dd679cd 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java
@@ -21,7 +21,7 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register;
-import ghidra.trace.model.Trace;
+import ghidra.trace.model.guest.TracePlatform;
public class SPLocationTrackingSpec implements RegisterLocationTrackingSpec {
public static final String CONFIG_NAME = "TRACK_SP";
@@ -43,11 +43,11 @@ public class SPLocationTrackingSpec implements RegisterLocationTrackingSpec {
@Override
public Register computeRegister(DebuggerCoordinates coordinates) {
- Trace trace = coordinates.getTrace();
- if (trace == null) {
+ TracePlatform platform = coordinates.getPlatform();
+ if (platform == null) {
return null;
}
- return trace.getBaseCompilerSpec().getStackPointer();
+ return platform.getCompilerSpec().getStackPointer();
}
@Override
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java
index 319a161c3e..2d3a956328 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java
@@ -201,6 +201,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
@Override
protected void specChanged(LocationTrackingSpec spec) {
+ updateTitle();
trackingSpecChangeListeners.fire.locationTrackingSpecChanged(spec);
}
@@ -1057,6 +1058,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
trackingTrait.goToCoordinates(coordinates);
readsMemTrait.goToCoordinates(coordinates);
locationLabel.goToCoordinates(coordinates);
+ updateTitle();
contextChanged();
}
diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java
index 67d6db2267..0abc918c85 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java
@@ -101,6 +101,11 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
protected void locationTracked() {
doGoToTracked();
}
+
+ @Override
+ protected void specChanged(LocationTrackingSpec spec) {
+ updateTitle();
+ }
}
protected class ForMemoryBytesReadsMemoryTrait extends DebuggerReadsMemoryTrait {
@@ -324,6 +329,7 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
trackingTrait.goToCoordinates(coordinates);
readsMemTrait.goToCoordinates(coordinates);
locationLabel.goToCoordinates(coordinates);
+ updateTitle();
contextChanged();
}