GP-2459: Refactor platform into LocationTracking. Add PC-by-reg, PC-by-stack

This commit is contained in:
Dan 2022-09-23 15:31:33 -04:00
parent 45165ea167
commit 8247ff6d43
14 changed files with 304 additions and 84 deletions

View file

@ -108,6 +108,19 @@
meaning may vary among platforms. While there may be some nuances to the register value, the 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.</LI> value recorded in the stack should indicate the next instruction to be executed.</LI>
<LI>Track Program Counter (by stack) - navigates this listing to the current program counter
as recorded from the debugger's stack trace. This option is not recommended for regular use,
especially for emulation, since the emulator does not provide stack trace records. It is
recommended for debugger connection developers to verify the stack records are being property
interpreted by the GUI.</LI>
<LI>Track Program Counter (by register) - navigates this listing to the current program
counter as recorded from the registers. While suitable for regular use, the default "Track
Program Counter" option is recommended, since the stack may record the program counter in
some cases where the registers do not. For example, when unwinding a stack frame, the
debugger may report the frame's program counter without reporting the frame's registers. This
option may be desired if/when stack frames are recorded incorrectly.</LI>
<LI>Track Stack Pointer - navigates this listing to the current stack pointer. Again, <LI>Track Stack Pointer - navigates this listing to the current stack pointer. Again,
platforms may vary in how they define the stack pointer.</LI> platforms may vary in how they define the stack pointer.</LI>
</UL> </UL>

View file

@ -83,13 +83,26 @@
<UL> <UL>
<LI>Do Not Track - disables automatic navigation.</LI> <LI>Do Not Track - disables automatic navigation.</LI>
<LI>Track Program Counter - (default) navigates this window to the current program counter. <LI>Track Program Counter - (default) navigates this listing to the current program counter.
If the stack contains a record of the program counter, it is preferred to the recorded If the stack contains a record of the program counter, it is preferred to the recorded
register value. Note that debuggers may vary in how they report the program counter, and its register value. Note that debuggers may vary in how they report the program counter, and its
meaning may vary among platforms. While there may be some nuances to the register value, the 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.</LI> value recorded in the stack should indicate the next instruction to be executed.</LI>
<LI>Track Stack Pointer - navigates this window to the current stack pointer. Again, <LI>Track Program Counter (by stack) - navigates this listing to the current program counter
as recorded from the debugger's stack trace. This option is not recommended for regular use,
especially for emulation, since the emulator does not provide stack trace records. It is
recommended for debugger connection developers to verify the stack records are being property
interpreted by the GUI.</LI>
<LI>Track Program Counter (by register) - navigates this listing to the current program
counter as recorded from the registers. While suitable for regular use, the default "Track
Program Counter" option is recommended, since the stack may record the program counter in
some cases where the registers do not. For example, when unwinding a stack frame, the
debugger may report the frame's program counter without reporting the frame's registers. This
option may be desired if/when stack frames are recorded incorrectly.</LI>
<LI>Track Stack Pointer - navigates this listing to the current stack pointer. Again,
platforms may vary in how they define the stack pointer.</LI> platforms may vary in how they define the stack pointer.</LI>
</UL> </UL>

View file

@ -859,11 +859,15 @@ public interface DebuggerResources {
String HELP_ANCHOR = "track_location"; String HELP_ANCHOR = "track_location";
String NAME_PC = "Track Program Counter"; String NAME_PC = "Track Program Counter";
String NAME_PC_BY_REGISTER = "Track Program Counter (by Register)";
String NAME_PC_BY_STACK = "Track Program Counter (by Stack)";
String NAME_SP = "Track Stack Pointer"; String NAME_SP = "Track Stack Pointer";
String NAME_NONE = "Do Not Track"; String NAME_NONE = "Do Not Track";
// TODO: Separate icons for Program Counter and Stack Pointer // TODO: Separate icons for Program Counter and Stack Pointer
Icon ICON_PC = ICON_REGISTER_MARKER; Icon ICON_PC = ICON_REGISTER_MARKER;
Icon ICON_PC_BY_REGISTER = ICON_REGISTER_MARKER;
Icon ICON_PC_BY_STACK = ICON_REGISTER_MARKER;
Icon ICON_SP = ICON_REGISTER_MARKER; Icon ICON_SP = ICON_REGISTER_MARKER;
// TODO: Consider sync_disabled icon // TODO: Consider sync_disabled icon
Icon ICON_NONE = ICON_DELETE; Icon ICON_NONE = ICON_DELETE;

View file

@ -25,6 +25,7 @@ public interface DebuggerTrackLocationAction extends TrackLocationAction {
static MultiStateActionBuilder<LocationTrackingSpec> builder(Plugin owner) { static MultiStateActionBuilder<LocationTrackingSpec> builder(Plugin owner) {
MultiStateActionBuilder<LocationTrackingSpec> builder = TrackLocationAction.builder(owner); MultiStateActionBuilder<LocationTrackingSpec> builder = TrackLocationAction.builder(owner);
builder.toolBarGroup(owner.getName()); builder.toolBarGroup(owner.getName());
builder.useCheckboxForIcons(true);
for (LocationTrackingSpec spec : LocationTrackingSpec.allSpecs().values()) { for (LocationTrackingSpec spec : LocationTrackingSpec.allSpecs().values()) {
builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec); builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec);
} }

View file

@ -251,8 +251,8 @@ public class DebuggerTrackLocationTrait {
return null; return null;
} }
// NB: view's snap may be forked for emulation // NB: view's snap may be forked for emulation
Address address = spec.computeTraceAddress(tool, cur, current.getView().getSnap()); Address address = spec.computeTraceAddress(tool, cur);
return address == null ? null : new ProgramLocation(current.getView(), address); return address == null ? null : new ProgramLocation(cur.getView(), address);
} }
protected void doTrack() { protected void doTrack() {

View file

@ -29,21 +29,26 @@ import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceAddressSpace;
import ghidra.util.classfinder.ClassSearcher; import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.classfinder.ExtensionPoint; import ghidra.util.classfinder.ExtensionPoint;
/** /**
* A "specification" for automatic navigation of the dynamic listing * A specification for automatic navigation of the dynamic listing
* *
* <p> * <p>
* TODO: Some of these should be configurable, and permit multiple instances, so that common * 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 * 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. * 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 { public interface LocationTrackingSpec extends ExtensionPoint {
class Private { enum Private {
INSTANCE;
private final Map<String, LocationTrackingSpec> specsByName = new TreeMap<>(); private final Map<String, LocationTrackingSpec> specsByName = new TreeMap<>();
private final ChangeListener classListener = this::classesChanged; private final ChangeListener classListener = this::classesChanged;
@ -57,7 +62,7 @@ public interface LocationTrackingSpec extends ExtensionPoint {
} }
} }
Private PRIVATE = new Private(); Private PRIVATE = Private.INSTANCE;
public static class TrackingSpecConfigFieldCodec public static class TrackingSpecConfigFieldCodec
implements ConfigFieldCodec<LocationTrackingSpec> { implements ConfigFieldCodec<LocationTrackingSpec> {
@ -74,36 +79,87 @@ public interface LocationTrackingSpec extends ExtensionPoint {
} }
} }
/**
* Check if the given trace-space and range refer to memory or the current frame
*
* <p>
* 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, static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range,
DebuggerCoordinates current) { DebuggerCoordinates current) {
if (space == null || space.getThread() != current.getThread()) { if (space == null) {
return false; return false;
} }
if (space.getFrameLevel() != current.getFrame()) { if (!space.getAddressSpace().isMemorySpace()) {
TraceMemorySpace memSpace = current.getTrace()
.getMemoryManager()
.getMemoryRegisterSpace(current.getThread(), current.getFrame(), false);
if (memSpace == null || memSpace.getAddressSpace() != space.getAddressSpace()) {
return false; return false;
} }
}
if (!range.getLifespan().contains(current.getSnap())) { if (!range.getLifespan().contains(current.getSnap())) {
return false; return false;
} }
return true; return true;
} }
/**
* Get the specification for the given configuration name
*
* @param name the name
* @return the spec, or null
*/
static LocationTrackingSpec fromConfigName(String name) { static LocationTrackingSpec fromConfigName(String name) {
synchronized (PRIVATE) { synchronized (PRIVATE) {
return PRIVATE.specsByName.get(name); return PRIVATE.specsByName.get(name);
} }
} }
/**
* Get a copy of all the known specifications
*
* @return the specifications by configuration name
*/
static Map<String, LocationTrackingSpec> allSpecs() { static Map<String, LocationTrackingSpec> allSpecs() {
synchronized (PRIVATE) { synchronized (PRIVATE) {
return Map.copyOf(PRIVATE.specsByName); return new TreeMap<>(PRIVATE.specsByName);
} }
} }
/**
* Get the configuration name
*
* <p>
* This is the value stored in configuration files to identify this specification
*
* @return the configuration name
*/
String getConfigName(); String getConfigName();
/**
* A human-readable name for this specification
*
* <p>
* This is the text displayed in menus
*
* @return the menu name
*/
String getMenuName(); String getMenuName();
/**
* Get the icon for this specification
*
* @return the icon
*/
Icon getMenuIcon(); Icon getMenuIcon();
/** /**
@ -120,15 +176,16 @@ public interface LocationTrackingSpec extends ExtensionPoint {
* <p> * <p>
* If the coordinates indicate emulation, i.e., the schedule is non-empty, the trace manager * 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 * 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 * general, the location should be computed using that snap, i.e.,
* indicated in {@code coordinates}. * {@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 tool the tool containing the provider
* @param coordinates the trace, thread, snap, etc., of the tool * @param coordinates the trace, thread, snap, etc., of the tool
* @param emuSnap the "scratch" snap storing emulated state
* @return the address to navigate to * @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 // TODO: Is there a way to generalize these so that other dependencies need not
// have their own bespoke methods? // have their own bespoke methods?

View file

@ -49,8 +49,7 @@ public class NoneLocationTrackingSpec implements LocationTrackingSpec {
} }
@Override @Override
public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
long emuSnap) {
return null; return null;
} }

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -21,16 +21,18 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.stack.TraceStackFrame; import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.model.thread.TraceThread;
public class PCLocationTrackingSpec implements RegisterLocationTrackingSpec { public class PCLocationTrackingSpec implements LocationTrackingSpec {
public static final String CONFIG_NAME = "TRACK_PC"; 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 @Override
public String getConfigName() { public String getConfigName() {
return CONFIG_NAME; return CONFIG_NAME;
@ -47,63 +49,30 @@ public class PCLocationTrackingSpec implements RegisterLocationTrackingSpec {
} }
@Override @Override
public Register computeRegister(DebuggerCoordinates coordinates) { public String computeTitle(DebuggerCoordinates coordinates) {
Trace trace = coordinates.getTrace(); return "Auto PC";
if (trace == null) {
return null;
}
return trace.getBaseLanguage().getProgramCounter();
} }
@Override @Override
public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) { public Address computeTraceAddress(PluginTool tool, 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) {
if (coordinates.getTime().isSnapOnly()) { if (coordinates.getTime().isSnapOnly()) {
Address pc = computePCViaStack(coordinates); Address pc = BY_STACK.computeTraceAddress(tool, coordinates);
if (pc != null) { if (pc != null) {
return pc; 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. // Note it does no good to override affectByRegChange. It must do what we'd avoid anyway.
@Override @Override
public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) {
if (stack.getThread() != coordinates.getThread()) { return BY_STACK.affectedByStackChange(stack, coordinates);
return false;
} }
if (!coordinates.getTime().isSnapOnly()) {
return false; @Override
} public boolean affectedByRegisterChange(TraceAddressSpace space, TraceAddressSnapRange range,
// TODO: Would be nice to have stack lifespan... DebuggerCoordinates coordinates) {
TraceStack curStack = coordinates.getTrace() return BY_REG.affectedByRegisterChange(space, range, coordinates);
.getStackManager()
.getLatestStack(stack.getThread(), coordinates.getSnap());
if (stack != curStack) {
return false;
}
return true;
} }
} }

View file

@ -22,12 +22,12 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue; import ghidra.program.model.lang.RegisterValue;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.TraceAddressSnapRange;
import ghidra.trace.model.guest.TracePlatform;
import ghidra.trace.model.memory.TraceMemorySpace; import ghidra.trace.model.memory.TraceMemorySpace;
import ghidra.trace.model.memory.TraceMemoryState; import ghidra.trace.model.memory.TraceMemoryState;
import ghidra.trace.model.stack.TraceStack; import ghidra.trace.model.stack.TraceStack;
import ghidra.trace.model.thread.TraceThread; import ghidra.trace.model.thread.TraceThread;
import ghidra.trace.util.TraceAddressSpace; import ghidra.trace.util.TraceAddressSpace;
import ghidra.trace.util.TraceRegisterUtils;
// TODO: Use this, or allow arbitrary expressions // TODO: Use this, or allow arbitrary expressions
public interface RegisterLocationTrackingSpec extends LocationTrackingSpec { public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
@ -45,10 +45,11 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
} }
@Override @Override
default Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, default Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
long emuSnap) {
Trace trace = coordinates.getTrace(); Trace trace = coordinates.getTrace();
TracePlatform platform = coordinates.getPlatform();
TraceThread thread = coordinates.getThread(); TraceThread thread = coordinates.getThread();
long viewSnap = coordinates.getViewSnap();
long snap = coordinates.getSnap(); long snap = coordinates.getSnap();
int frame = coordinates.getFrame(); int frame = coordinates.getFrame();
Register reg = computeRegister(coordinates); Register reg = computeRegister(coordinates);
@ -64,19 +65,19 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
return null; return null;
} }
RegisterValue value; RegisterValue value;
if (regs.getState(emuSnap, reg) == TraceMemoryState.KNOWN) { if (regs.getState(platform, viewSnap, reg) == TraceMemoryState.KNOWN) {
value = regs.getValue(emuSnap, reg); value = regs.getValue(platform, viewSnap, reg);
} }
else { else {
value = regs.getValue(snap, reg); value = regs.getValue(platform, snap, reg);
} }
if (value == null) { if (value == null) {
return null; return null;
} }
// TODO: Action to select the address space // TODO: Action to select the address space
// Could use code unit, but that can't specify space, yet, either.... // Could use code unit, but that can't specify space, yet, either....
return computeDefaultAddressSpace(coordinates) return platform.mapGuestToHost(computeDefaultAddressSpace(coordinates)
.getAddress(value.getUnsignedValue().longValue(), true); .getAddress(value.getUnsignedValue().longValue(), true));
} }
@Override @Override
@ -89,7 +90,9 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec {
if (register == null) { if (register == null) {
return false; 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); return range.getRange().intersects(regRng);
} }

View file

@ -21,7 +21,7 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace; import ghidra.trace.model.guest.TracePlatform;
public class SPLocationTrackingSpec implements RegisterLocationTrackingSpec { public class SPLocationTrackingSpec implements RegisterLocationTrackingSpec {
public static final String CONFIG_NAME = "TRACK_SP"; public static final String CONFIG_NAME = "TRACK_SP";
@ -43,11 +43,11 @@ public class SPLocationTrackingSpec implements RegisterLocationTrackingSpec {
@Override @Override
public Register computeRegister(DebuggerCoordinates coordinates) { public Register computeRegister(DebuggerCoordinates coordinates) {
Trace trace = coordinates.getTrace(); TracePlatform platform = coordinates.getPlatform();
if (trace == null) { if (platform == null) {
return null; return null;
} }
return trace.getBaseCompilerSpec().getStackPointer(); return platform.getCompilerSpec().getStackPointer();
} }
@Override @Override

View file

@ -201,6 +201,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
@Override @Override
protected void specChanged(LocationTrackingSpec spec) { protected void specChanged(LocationTrackingSpec spec) {
updateTitle();
trackingSpecChangeListeners.fire.locationTrackingSpecChanged(spec); trackingSpecChangeListeners.fire.locationTrackingSpecChanged(spec);
} }
@ -1057,6 +1058,7 @@ public class DebuggerListingProvider extends CodeViewerProvider {
trackingTrait.goToCoordinates(coordinates); trackingTrait.goToCoordinates(coordinates);
readsMemTrait.goToCoordinates(coordinates); readsMemTrait.goToCoordinates(coordinates);
locationLabel.goToCoordinates(coordinates); locationLabel.goToCoordinates(coordinates);
updateTitle();
contextChanged(); contextChanged();
} }

View file

@ -101,6 +101,11 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
protected void locationTracked() { protected void locationTracked() {
doGoToTracked(); doGoToTracked();
} }
@Override
protected void specChanged(LocationTrackingSpec spec) {
updateTitle();
}
} }
protected class ForMemoryBytesReadsMemoryTrait extends DebuggerReadsMemoryTrait { protected class ForMemoryBytesReadsMemoryTrait extends DebuggerReadsMemoryTrait {
@ -324,6 +329,7 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
trackingTrait.goToCoordinates(coordinates); trackingTrait.goToCoordinates(coordinates);
readsMemTrait.goToCoordinates(coordinates); readsMemTrait.goToCoordinates(coordinates);
locationLabel.goToCoordinates(coordinates); locationLabel.goToCoordinates(coordinates);
updateTitle();
contextChanged(); contextChanged();
} }