mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-09-13 21:56:19 +00:00
Merge remote-tracking branch 'origin/GP-2459_Dan_pcSpTrackingNewConventions--SQUASHED'
This commit is contained in:
commit
336b0531bc
|
@ -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.</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,
|
||||
platforms may vary in how they define the stack pointer.</LI>
|
||||
</UL>
|
||||
|
|
|
@ -83,13 +83,26 @@
|
|||
<UL>
|
||||
<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
|
||||
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
|
||||
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>
|
||||
</UL>
|
||||
|
||||
|
|
|
@ -859,11 +859,15 @@ public interface DebuggerResources {
|
|||
String HELP_ANCHOR = "track_location";
|
||||
|
||||
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_NONE = "Do Not Track";
|
||||
|
||||
// TODO: Separate icons for Program Counter and Stack Pointer
|
||||
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;
|
||||
// TODO: Consider sync_disabled icon
|
||||
Icon ICON_NONE = ICON_DELETE;
|
||||
|
|
|
@ -25,6 +25,7 @@ public interface DebuggerTrackLocationAction extends TrackLocationAction {
|
|||
static MultiStateActionBuilder<LocationTrackingSpec> builder(Plugin owner) {
|
||||
MultiStateActionBuilder<LocationTrackingSpec> builder = TrackLocationAction.builder(owner);
|
||||
builder.toolBarGroup(owner.getName());
|
||||
builder.useCheckboxForIcons(true);
|
||||
for (LocationTrackingSpec spec : LocationTrackingSpec.allSpecs().values()) {
|
||||
builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec);
|
||||
}
|
||||
|
|
|
@ -251,8 +251,8 @@ public class DebuggerTrackLocationTrait {
|
|||
return null;
|
||||
}
|
||||
// NB: view's snap may be forked for emulation
|
||||
Address address = spec.computeTraceAddress(tool, cur, current.getView().getSnap());
|
||||
return address == null ? null : new ProgramLocation(current.getView(), address);
|
||||
Address address = spec.computeTraceAddress(tool, cur);
|
||||
return address == null ? null : new ProgramLocation(cur.getView(), address);
|
||||
}
|
||||
|
||||
protected void doTrack() {
|
||||
|
|
|
@ -29,21 +29,26 @@ import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
|||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
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.util.TraceAddressSpace;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
|
||||
/**
|
||||
* A "specification" for automatic navigation of the dynamic listing
|
||||
* A specification for automatic navigation of the dynamic listing
|
||||
*
|
||||
* <p>
|
||||
* 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<String, LocationTrackingSpec> specsByName = new TreeMap<>();
|
||||
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
|
||||
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,
|
||||
DebuggerCoordinates current) {
|
||||
if (space == null || space.getThread() != current.getThread()) {
|
||||
if (space == null) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!range.getLifespan().contains(current.getSnap())) {
|
||||
return false;
|
||||
}
|
||||
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<String, LocationTrackingSpec> allSpecs() {
|
||||
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();
|
||||
|
||||
/**
|
||||
* A human-readable name for this specification
|
||||
*
|
||||
* <p>
|
||||
* 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 {
|
|||
* <p>
|
||||
* 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?
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
return BY_STACK.affectedByStackChange(stack, coordinates);
|
||||
}
|
||||
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;
|
||||
|
||||
@Override
|
||||
public boolean affectedByRegisterChange(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates) {
|
||||
return BY_REG.affectedByRegisterChange(space, range, coordinates);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,11 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
protected void locationTracked() {
|
||||
doGoToTracked();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void specChanged(LocationTrackingSpec spec) {
|
||||
updateTitle();
|
||||
}
|
||||
}
|
||||
|
||||
protected class ForMemoryBytesReadsMemoryTrait extends DebuggerReadsMemoryTrait {
|
||||
|
@ -382,6 +387,7 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||
trackingTrait.goToCoordinates(coordinates);
|
||||
readsMemTrait.goToCoordinates(coordinates);
|
||||
locationLabel.goToCoordinates(coordinates);
|
||||
updateTitle();
|
||||
contextChanged();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue