mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 05:32:14 +00:00
GP-4236: Implement new columns: PC, Func, Mod, SP. Remove: Created, Destroyed
This commit is contained in:
parent
f5008f9f99
commit
270fb01400
@ -15,10 +15,8 @@
|
||||
*/
|
||||
package ghidra.debug.api.action;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
@ -47,21 +45,21 @@ public interface LocationTracker {
|
||||
* 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 provider the service provider (usually the tool)
|
||||
* @param coordinates the trace, thread, snap, etc., of the tool
|
||||
* @return the address to navigate to
|
||||
*/
|
||||
Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates);
|
||||
Address computeTraceAddress(ServiceProvider provider, DebuggerCoordinates coordinates);
|
||||
|
||||
/**
|
||||
* Get the suggested input if the user activates "Go To" while this tracker is active
|
||||
*
|
||||
* @param tool the tool containing the provider
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param coordinates the user's current coordinates
|
||||
* @param location the user's current location
|
||||
* @return the suggested address or Sleigh expression
|
||||
*/
|
||||
GoToInput getDefaultGoToInput(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
GoToInput getDefaultGoToInput(ServiceProvider provider, DebuggerCoordinates coordinates,
|
||||
ProgramLocation location);
|
||||
|
||||
// TODO: Is there a way to generalize these so that other dependencies need not
|
||||
|
@ -119,7 +119,7 @@ public interface LocationTrackingSpec {
|
||||
/**
|
||||
* Compute a title prefix to indicate this tracking specification
|
||||
*
|
||||
* @param thread the provider's current thread
|
||||
* @param coordinates the current coordinates
|
||||
* @return a prefix, or {@code null} to use a default
|
||||
*/
|
||||
String computeTitle(DebuggerCoordinates coordinates);
|
||||
|
@ -20,7 +20,7 @@ import javax.swing.Icon;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
|
||||
import ghidra.debug.api.action.*;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
@ -63,12 +63,12 @@ public enum NoneLocationTrackingSpec implements LocationTrackingSpec, LocationTr
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
|
||||
public Address computeTraceAddress(ServiceProvider provider, DebuggerCoordinates coordinates) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoToInput getDefaultGoToInput(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
public GoToInput getDefaultGoToInput(ServiceProvider provider, DebuggerCoordinates coordinates,
|
||||
ProgramLocation location) {
|
||||
if (location == null) {
|
||||
return GoToInput.fromString("00000000");
|
||||
|
@ -20,7 +20,7 @@ import javax.swing.Icon;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
|
||||
import ghidra.debug.api.action.*;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
@ -66,9 +66,12 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
|
||||
public Address computeTraceAddress(ServiceProvider provider, DebuggerCoordinates coordinates) {
|
||||
Trace trace = coordinates.getTrace();
|
||||
TraceThread thread = coordinates.getThread();
|
||||
if (thread == null) {
|
||||
return null;
|
||||
}
|
||||
long snap = coordinates.getSnap();
|
||||
TraceStack stack = trace.getStackManager().getLatestStack(thread, snap);
|
||||
if (stack == null) {
|
||||
@ -83,11 +86,11 @@ public enum PCByStackLocationTrackingSpec implements LocationTrackingSpec, Locat
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoToInput getDefaultGoToInput(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
public GoToInput getDefaultGoToInput(ServiceProvider provider, DebuggerCoordinates coordinates,
|
||||
ProgramLocation location) {
|
||||
Address address = computeTraceAddress(tool, coordinates);
|
||||
Address address = computeTraceAddress(provider, coordinates);
|
||||
if (address == null) {
|
||||
return NoneLocationTrackingSpec.INSTANCE.getDefaultGoToInput(tool, coordinates,
|
||||
return NoneLocationTrackingSpec.INSTANCE.getDefaultGoToInput(provider, coordinates,
|
||||
location);
|
||||
}
|
||||
return GoToInput.fromAddress(address);
|
||||
|
@ -20,7 +20,7 @@ import javax.swing.Icon;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
|
||||
import ghidra.debug.api.action.*;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
@ -68,20 +68,20 @@ public enum PCLocationTrackingSpec implements LocationTrackingSpec, LocationTrac
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
|
||||
public Address computeTraceAddress(ServiceProvider provider, DebuggerCoordinates coordinates) {
|
||||
if (coordinates.getTime().isSnapOnly()) {
|
||||
Address pc = BY_STACK.computeTraceAddress(tool, coordinates);
|
||||
Address pc = BY_STACK.computeTraceAddress(provider, coordinates);
|
||||
if (pc != null) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return BY_REG.computeTraceAddress(tool, coordinates);
|
||||
return BY_REG.computeTraceAddress(provider, coordinates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoToInput getDefaultGoToInput(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
public GoToInput getDefaultGoToInput(ServiceProvider provider, DebuggerCoordinates coordinates,
|
||||
ProgramLocation location) {
|
||||
return BY_REG.getDefaultGoToInput(tool, coordinates, location);
|
||||
return BY_REG.getDefaultGoToInput(provider, coordinates, location);
|
||||
}
|
||||
|
||||
// Note it does no good to override affectByRegChange. It must do what we'd avoid anyway.
|
||||
|
@ -17,7 +17,7 @@ package ghidra.app.plugin.core.debug.gui.action;
|
||||
|
||||
import ghidra.debug.api.action.*;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
@ -51,10 +51,13 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, Loca
|
||||
}
|
||||
|
||||
@Override
|
||||
default Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
|
||||
default Address computeTraceAddress(ServiceProvider provider, DebuggerCoordinates coordinates) {
|
||||
Trace trace = coordinates.getTrace();
|
||||
TracePlatform platform = coordinates.getPlatform();
|
||||
TraceThread thread = coordinates.getThread();
|
||||
if (thread == null) {
|
||||
return null;
|
||||
}
|
||||
long viewSnap = coordinates.getViewSnap();
|
||||
long snap = coordinates.getSnap();
|
||||
int frame = coordinates.getFrame();
|
||||
@ -88,7 +91,7 @@ public interface RegisterLocationTrackingSpec extends LocationTrackingSpec, Loca
|
||||
}
|
||||
|
||||
@Override
|
||||
default GoToInput getDefaultGoToInput(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
default GoToInput getDefaultGoToInput(ServiceProvider provider, DebuggerCoordinates coordinates,
|
||||
ProgramLocation location) {
|
||||
Register register = computeRegister(coordinates);
|
||||
return GoToInput.offsetOnly(register.getName());
|
||||
|
@ -24,7 +24,7 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction;
|
||||
import ghidra.debug.api.action.*;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.debug.api.watch.WatchRow;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.pcode.exec.*;
|
||||
import ghidra.pcode.exec.DebuggerPcodeUtils.WatchValue;
|
||||
import ghidra.pcode.exec.SleighUtils.AddressOf;
|
||||
@ -117,11 +117,12 @@ public class WatchLocationTrackingSpec implements LocationTrackingSpec {
|
||||
private PcodeExpression compiled;
|
||||
|
||||
@Override
|
||||
public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates) {
|
||||
public Address computeTraceAddress(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates) {
|
||||
if (!Objects.equals(current, coordinates) || exec == null) {
|
||||
current = coordinates;
|
||||
exec = current.getPlatform() == null ? null
|
||||
: DebuggerPcodeUtils.buildWatchExecutor(tool, coordinates);
|
||||
: DebuggerPcodeUtils.buildWatchExecutor(provider, coordinates);
|
||||
}
|
||||
else {
|
||||
exec.getState().clear();
|
||||
@ -129,20 +130,20 @@ public class WatchLocationTrackingSpec implements LocationTrackingSpec {
|
||||
if (current.getTrace() == null) {
|
||||
return null;
|
||||
}
|
||||
compiled = DebuggerPcodeUtils.compileExpression(tool, current, expression);
|
||||
compiled = DebuggerPcodeUtils.compileExpression(provider, current, expression);
|
||||
WatchValue value = compiled.evaluate(exec);
|
||||
return value == null ? null : value.address();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GoToInput getDefaultGoToInput(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
ProgramLocation location) {
|
||||
public GoToInput getDefaultGoToInput(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates, ProgramLocation location) {
|
||||
TracePlatform platform = current.getPlatform();
|
||||
String defaultSpace =
|
||||
platform == null ? "ram" : platform.getLanguage().getDefaultSpace().getName();
|
||||
AddressOf addrOf = SleighUtils.recoverAddressOf(defaultSpace, expression);
|
||||
if (addrOf == null) {
|
||||
return NoneLocationTrackingSpec.INSTANCE.getDefaultGoToInput(tool, coordinates,
|
||||
return NoneLocationTrackingSpec.INSTANCE.getDefaultGoToInput(provider, coordinates,
|
||||
location);
|
||||
}
|
||||
return new GoToInput(addrOf.space(),
|
||||
|
@ -54,6 +54,11 @@ public abstract class TraceValueObjectPropertyColumn<T>
|
||||
super.getTableCellRendererComponent(data);
|
||||
@SuppressWarnings("unchecked")
|
||||
ValueProperty<T> p = (ValueProperty<T>) data.getValue();
|
||||
if (p == null) {
|
||||
setText("");
|
||||
setToolTipText("");
|
||||
return this;
|
||||
}
|
||||
setText(p.getHtmlDisplay());
|
||||
setToolTipText(p.getToolTip());
|
||||
setForeground(getForegroundFor(data.getTable(), p.isModified(), data.isSelected()));
|
||||
|
@ -40,20 +40,8 @@ public class ModuleRow {
|
||||
}
|
||||
}
|
||||
|
||||
public static String computeShortName(String path) {
|
||||
int sep = path.lastIndexOf('\\');
|
||||
if (sep > 0 && sep < path.length()) {
|
||||
path = path.substring(sep + 1);
|
||||
}
|
||||
sep = path.lastIndexOf('/');
|
||||
if (sep > 0 && sep < path.length()) {
|
||||
path = path.substring(sep + 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return computeShortName(module.getName());
|
||||
return DebuggerStaticMappingUtils.computeModuleShortName(module.getName());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -27,6 +27,7 @@ import ghidra.app.plugin.core.debug.gui.model.AbstractQueryTablePanel.CellActiva
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||
import ghidra.app.plugin.core.debug.gui.model.columns.TraceValueKeyColumn;
|
||||
import ghidra.app.plugin.core.debug.gui.model.columns.TraceValueObjectAttributeColumn;
|
||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.dbg.target.TargetStack;
|
||||
import ghidra.dbg.target.TargetStackFrame;
|
||||
@ -40,7 +41,6 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
@ -84,7 +84,8 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
TraceObjectValue value =
|
||||
rowObject.getAttributeEntry(TargetStackFrame.PC_ATTRIBUTE_NAME);
|
||||
return value == null ? null : provider.getFunction(value.castValue());
|
||||
return DebuggerStaticMappingUtils.getFunction(value.castValue(), provider.current,
|
||||
serviceProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,7 +100,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
TraceObjectValue value =
|
||||
rowObject.getAttributeEntry(TargetStackFrame.PC_ATTRIBUTE_NAME);
|
||||
return value == null ? null : provider.getModule(value.castValue());
|
||||
return DebuggerStaticMappingUtils.getModuleName(value.castValue(), provider.current);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,17 +30,12 @@ import docking.action.DockingAction;
|
||||
import docking.action.builder.ActionBuilder;
|
||||
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
|
||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||
import ghidra.app.plugin.core.debug.gui.modules.ModuleRow;
|
||||
import ghidra.app.plugin.core.debug.stack.UnwindStackCommand;
|
||||
import ghidra.app.services.DebuggerStaticMappingService;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.modules.TraceModule;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
@ -192,39 +187,4 @@ public class DebuggerStackProvider extends ComponentProviderAdapter {
|
||||
legacyPanel.coordinatesActivated(DebuggerCoordinates.NOWHERE);
|
||||
}
|
||||
}
|
||||
|
||||
public Function getFunction(Address pc) {
|
||||
if (pc == null) {
|
||||
return null;
|
||||
}
|
||||
if (mappingService == null) {
|
||||
return null;
|
||||
}
|
||||
TraceThread curThread = current.getThread();
|
||||
if (curThread == null) {
|
||||
return null;
|
||||
}
|
||||
TraceLocation dloc = new DefaultTraceLocation(curThread.getTrace(),
|
||||
curThread, Lifespan.at(current.getSnap()), pc);
|
||||
ProgramLocation sloc = mappingService.getOpenMappedLocation(dloc);
|
||||
if (sloc == null) {
|
||||
return null;
|
||||
}
|
||||
return sloc.getProgram().getFunctionManager().getFunctionContaining(sloc.getAddress());
|
||||
}
|
||||
|
||||
public String getModule(Address pc) {
|
||||
if (pc == null) {
|
||||
return null;
|
||||
}
|
||||
Trace trace = current.getTrace();
|
||||
if (trace == null) {
|
||||
return null;
|
||||
}
|
||||
for (TraceModule module : trace.getModuleManager().getModulesAt(current.getSnap(), pc)) {
|
||||
// Just take the first
|
||||
return ModuleRow.computeShortName(module.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package ghidra.app.plugin.core.debug.gui.stack;
|
||||
|
||||
import db.Transaction;
|
||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
@ -84,11 +85,12 @@ public class StackFrameRow {
|
||||
}
|
||||
|
||||
public Function getFunction() {
|
||||
return panel.provider.getFunction(getProgramCounter());
|
||||
return DebuggerStaticMappingUtils.getFunction(getProgramCounter(), panel.current,
|
||||
panel.provider.getTool());
|
||||
}
|
||||
|
||||
public String getModule() {
|
||||
return panel.provider.getModule(getProgramCounter());
|
||||
return DebuggerStaticMappingUtils.getModuleName(getProgramCounter(), panel.current);
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
|
@ -37,6 +37,7 @@ import ghidra.framework.model.DomainObjectChangeRecord;
|
||||
import ghidra.framework.model.DomainObjectEvent;
|
||||
import ghidra.framework.plugintool.AutoService;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.thread.TraceThreadManager;
|
||||
@ -55,32 +56,40 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
|
||||
|
||||
protected enum ThreadTableColumns
|
||||
implements EnumeratedTableColumn<ThreadTableColumns, ThreadRow> {
|
||||
NAME("Name", String.class, ThreadRow::getName, ThreadRow::setName, true),
|
||||
CREATED("Created", Long.class, ThreadRow::getCreationSnap, true),
|
||||
DESTROYED("Destroyed", String.class, ThreadRow::getDestructionSnap, true),
|
||||
STATE("State", ThreadState.class, ThreadRow::getState, true),
|
||||
COMMENT("Comment", String.class, ThreadRow::getComment, ThreadRow::setComment, true),
|
||||
PLOT("Plot", Lifespan.class, ThreadRow::getLifespan, false);
|
||||
NAME("Name", String.class, ThreadRow::getName, ThreadRow::setName, true, true),
|
||||
PC("PC", Address.class, ThreadRow::getProgramCounter, true, true),
|
||||
FUNCTION("Function", ghidra.program.model.listing.Function.class, ThreadRow::getFunction, //
|
||||
true, true),
|
||||
MODULE("Module", String.class, ThreadRow::getModule, true, false),
|
||||
SP("SP", Address.class, ThreadRow::getStackPointer, true, false),
|
||||
CREATED("Created", Long.class, ThreadRow::getCreationSnap, true, false),
|
||||
DESTROYED("Destroyed", String.class, ThreadRow::getDestructionSnap, true, false),
|
||||
|
||||
STATE("State", ThreadState.class, ThreadRow::getState, true, true),
|
||||
COMMENT("Comment", String.class, ThreadRow::getComment, ThreadRow::setComment, true, false),
|
||||
PLOT("Plot", Lifespan.class, ThreadRow::getLifespan, false, true);
|
||||
|
||||
private final String header;
|
||||
private final Function<ThreadRow, ?> getter;
|
||||
private final BiConsumer<ThreadRow, Object> setter;
|
||||
private final boolean sortable;
|
||||
private final boolean visible;
|
||||
private final Class<?> cls;
|
||||
|
||||
<T> ThreadTableColumns(String header, Class<T> cls, Function<ThreadRow, T> getter,
|
||||
boolean sortable) {
|
||||
this(header, cls, getter, null, sortable);
|
||||
boolean sortable, boolean visible) {
|
||||
this(header, cls, getter, null, sortable, visible);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> ThreadTableColumns(String header, Class<T> cls, Function<ThreadRow, T> getter,
|
||||
BiConsumer<ThreadRow, T> setter, boolean sortable) {
|
||||
BiConsumer<ThreadRow, T> setter, boolean sortable, boolean visible) {
|
||||
this.header = header;
|
||||
this.cls = cls;
|
||||
this.getter = getter;
|
||||
this.setter = (BiConsumer<ThreadRow, Object>) setter;
|
||||
this.sortable = sortable;
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -108,6 +117,11 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
|
||||
return sortable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueOf(ThreadRow row, Object value) {
|
||||
setter.accept(row, value);
|
||||
@ -253,22 +267,16 @@ public class DebuggerLegacyThreadsPanel extends JPanel {
|
||||
|
||||
TableColumnModel columnModel = threadTable.getColumnModel();
|
||||
TableColumn colName = columnModel.getColumn(ThreadTableColumns.NAME.ordinal());
|
||||
colName.setPreferredWidth(100);
|
||||
colName.setCellRenderer(boldCurrentRenderer);
|
||||
TableColumn colCreated = columnModel.getColumn(ThreadTableColumns.CREATED.ordinal());
|
||||
colCreated.setPreferredWidth(10);
|
||||
colCreated.setCellRenderer(boldCurrentRenderer);
|
||||
TableColumn colDestroyed = columnModel.getColumn(ThreadTableColumns.DESTROYED.ordinal());
|
||||
colDestroyed.setPreferredWidth(10);
|
||||
colDestroyed.setCellRenderer(boldCurrentRenderer);
|
||||
TableColumn colState = columnModel.getColumn(ThreadTableColumns.STATE.ordinal());
|
||||
colState.setPreferredWidth(20);
|
||||
colState.setCellRenderer(boldCurrentRenderer);
|
||||
TableColumn colComment = columnModel.getColumn(ThreadTableColumns.COMMENT.ordinal());
|
||||
colComment.setPreferredWidth(100);
|
||||
colComment.setCellRenderer(boldCurrentRenderer);
|
||||
TableColumn colPlot = columnModel.getColumn(ThreadTableColumns.PLOT.ordinal());
|
||||
colPlot.setPreferredWidth(200);
|
||||
colPlot.setCellRenderer(spanRenderer);
|
||||
colPlot.setHeaderRenderer(headerRenderer);
|
||||
|
||||
|
@ -20,12 +20,16 @@ import java.util.List;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
|
||||
import docking.widgets.table.AbstractDynamicTableColumn;
|
||||
import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener;
|
||||
import docking.widgets.table.TableColumnDescriptor;
|
||||
import docking.widgets.table.threaded.ThreadedTableModelListener;
|
||||
import ghidra.app.plugin.core.debug.gui.action.PCLocationTrackingSpec;
|
||||
import ghidra.app.plugin.core.debug.gui.action.SPLocationTrackingSpec;
|
||||
import ghidra.app.plugin.core.debug.gui.model.*;
|
||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
@ -34,10 +38,10 @@ import ghidra.docking.settings.Settings;
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
|
||||
public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceObjectThread> {
|
||||
@ -67,53 +71,92 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class AbstractThreadLifeBoundColumn
|
||||
extends TraceValueObjectPropertyColumn<Long> {
|
||||
public AbstractThreadLifeBoundColumn() {
|
||||
super(Long.class);
|
||||
private Address computeProgramCounter(DebuggerCoordinates coords) {
|
||||
// TODO: Cheating a bit. Also, can user configure whether by stack or regs?
|
||||
return PCLocationTrackingSpec.INSTANCE.computeTraceAddress(provider.getTool(),
|
||||
coords);
|
||||
}
|
||||
|
||||
private class ThreadPcColumn extends TraceValueObjectPropertyColumn<Address> {
|
||||
public ThreadPcColumn() {
|
||||
super(Address.class);
|
||||
}
|
||||
|
||||
abstract Long fromLifespan(Lifespan lifespan);
|
||||
|
||||
@Override
|
||||
public ValueProperty<Long> getProperty(ValueRow row) {
|
||||
return new ValueDerivedProperty<>(row, Long.class) {
|
||||
public ValueProperty<Address> getProperty(ValueRow row) {
|
||||
TraceObject obj = row.getValue().getChild();
|
||||
DebuggerCoordinates coords = provider.current.object(obj);
|
||||
return new ValueAddressProperty(row) {
|
||||
@Override
|
||||
public Long getValue() {
|
||||
// De-duplication may not select parent value at current snap
|
||||
TraceObjectValue curVal =
|
||||
row.getValue().getChild().getCanonicalParent(row.currentSnap());
|
||||
if (curVal == null) {
|
||||
// Thread is not actually alive a current snap
|
||||
return null;
|
||||
}
|
||||
return fromLifespan(curVal.getLifespan());
|
||||
public Address getValue() {
|
||||
return computeProgramCounter(coords);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThreadCreatedColumn extends AbstractThreadLifeBoundColumn {
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "Created";
|
||||
}
|
||||
|
||||
@Override
|
||||
Long fromLifespan(Lifespan lifespan) {
|
||||
return lifespan.minIsFinite() ? lifespan.lmin() : null;
|
||||
return "PC";
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThreadDestroyedColumn extends AbstractThreadLifeBoundColumn {
|
||||
private class ThreadFunctionColumn
|
||||
extends AbstractDynamicTableColumn<ValueRow, Function, Trace> {
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "Destroyed";
|
||||
return "Function";
|
||||
}
|
||||
|
||||
@Override
|
||||
Long fromLifespan(Lifespan lifespan) {
|
||||
return lifespan.maxIsFinite() ? lifespan.lmax() : null;
|
||||
public Function getValue(ValueRow rowObject, Settings settings, Trace data,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
DebuggerCoordinates coords = provider.current.object(rowObject.currentObject());
|
||||
Address pc = computeProgramCounter(coords);
|
||||
if (pc == null) {
|
||||
return null;
|
||||
}
|
||||
return DebuggerStaticMappingUtils.getFunction(pc, coords, serviceProvider);
|
||||
}
|
||||
}
|
||||
|
||||
private class ThreadModuleColumn extends AbstractDynamicTableColumn<ValueRow, String, Trace> {
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "Module";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(ValueRow rowObject, Settings settings, Trace data,
|
||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||
DebuggerCoordinates coords = provider.current.object(rowObject.currentObject());
|
||||
Address pc = computeProgramCounter(coords);
|
||||
if (pc == null) {
|
||||
return null;
|
||||
}
|
||||
return DebuggerStaticMappingUtils.getModuleName(pc, coords);
|
||||
}
|
||||
}
|
||||
|
||||
private class ThreadSpColumn extends TraceValueObjectPropertyColumn<Address> {
|
||||
public ThreadSpColumn() {
|
||||
super(Address.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueProperty<Address> getProperty(ValueRow row) {
|
||||
DebuggerCoordinates coords = provider.current.object(row.currentObject());
|
||||
return new ValueAddressProperty(row) {
|
||||
@Override
|
||||
public Address getValue() {
|
||||
return SPLocationTrackingSpec.INSTANCE.computeTraceAddress(provider.getTool(),
|
||||
coords);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return "SP";
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +187,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
||||
private static class ThreadPlotColumn extends TraceValueLifePlotColumn {
|
||||
}
|
||||
|
||||
private static class ThreadTableModel extends ObjectTableModel {
|
||||
private class ThreadTableModel extends ObjectTableModel {
|
||||
protected ThreadTableModel(Plugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
@ -154,10 +197,12 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
||||
TableColumnDescriptor<ValueRow> descriptor = new TableColumnDescriptor<>();
|
||||
descriptor.addHiddenColumn(new ThreadPathColumn());
|
||||
descriptor.addVisibleColumn(new ThreadNameColumn(), 1, true);
|
||||
descriptor.addVisibleColumn(new ThreadCreatedColumn());
|
||||
descriptor.addVisibleColumn(new ThreadDestroyedColumn());
|
||||
descriptor.addVisibleColumn(new ThreadPcColumn());
|
||||
descriptor.addVisibleColumn(new ThreadFunctionColumn());
|
||||
descriptor.addHiddenColumn(new ThreadModuleColumn());
|
||||
descriptor.addHiddenColumn(new ThreadSpColumn());
|
||||
descriptor.addVisibleColumn(new ThreadStateColumn());
|
||||
descriptor.addVisibleColumn(new ThreadCommentColumn());
|
||||
descriptor.addHiddenColumn(new ThreadCommentColumn());
|
||||
descriptor.addVisibleColumn(new ThreadPlotColumn());
|
||||
return descriptor;
|
||||
}
|
||||
|
@ -16,8 +16,14 @@
|
||||
package ghidra.app.plugin.core.debug.gui.thread;
|
||||
|
||||
import db.Transaction;
|
||||
import ghidra.app.plugin.core.debug.gui.action.PCLocationTrackingSpec;
|
||||
import ghidra.app.plugin.core.debug.gui.action.SPLocationTrackingSpec;
|
||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
@ -50,6 +56,34 @@ public class ThreadRow {
|
||||
return thread.getName();
|
||||
}
|
||||
|
||||
private Address computeProgramCounter(DebuggerCoordinates coords) {
|
||||
// TODO: Cheating a bit. Also, can user configure whether by stack or regs?
|
||||
return PCLocationTrackingSpec.INSTANCE.computeTraceAddress(provider.getTool(),
|
||||
coords);
|
||||
}
|
||||
|
||||
public Address getProgramCounter() {
|
||||
DebuggerCoordinates coords = provider.current.thread(thread);
|
||||
return computeProgramCounter(coords);
|
||||
}
|
||||
|
||||
public Function getFunction() {
|
||||
DebuggerCoordinates coords = provider.current.thread(thread);
|
||||
Address pc = computeProgramCounter(coords);
|
||||
return DebuggerStaticMappingUtils.getFunction(pc, coords, provider.getTool());
|
||||
}
|
||||
|
||||
public String getModule() {
|
||||
DebuggerCoordinates coords = provider.current.thread(thread);
|
||||
Address pc = computeProgramCounter(coords);
|
||||
return DebuggerStaticMappingUtils.getModuleName(pc, coords);
|
||||
}
|
||||
|
||||
public Address getStackPointer() {
|
||||
DebuggerCoordinates coords = provider.current.thread(thread);
|
||||
return SPLocationTrackingSpec.INSTANCE.computeTraceAddress(provider.getTool(), coords);
|
||||
}
|
||||
|
||||
public long getCreationSnap() {
|
||||
return thread.getCreationSnap();
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package ghidra.app.plugin.core.debug.service.emulation.data;
|
||||
|
||||
import ghidra.debug.api.emulation.*;
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.pcode.exec.trace.data.AbstractPcodeTraceAccess;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
|
||||
@ -31,21 +31,22 @@ public abstract class AbstractPcodeDebuggerAccess<S extends PcodeDebuggerMemoryA
|
||||
extends AbstractPcodeTraceAccess<S, L>
|
||||
implements PcodeDebuggerAccess {
|
||||
|
||||
protected final PluginTool tool;
|
||||
protected final ServiceProvider provider;
|
||||
protected final Target target;
|
||||
|
||||
/**
|
||||
* Construct a shim
|
||||
*
|
||||
* @param tool the tool controlling the session
|
||||
* @param recorder the target's recorder
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param target the target
|
||||
* @param platform the associated platform, having the same trace as the recorder
|
||||
* @param snap the associated snap
|
||||
*/
|
||||
public AbstractPcodeDebuggerAccess(PluginTool tool, Target target, TracePlatform platform,
|
||||
public AbstractPcodeDebuggerAccess(ServiceProvider provider, Target target,
|
||||
TracePlatform platform,
|
||||
long snap) {
|
||||
super(platform, snap);
|
||||
this.tool = tool;
|
||||
this.provider = provider;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package ghidra.app.plugin.core.debug.service.emulation.data;
|
||||
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
|
||||
@ -30,25 +30,25 @@ public class DefaultPcodeDebuggerAccess extends
|
||||
/**
|
||||
* Construct a shim
|
||||
*
|
||||
* @param tool the tool controlling the session
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param target the target
|
||||
* @param platform the associated platform, having the same trace as the recorder
|
||||
* @param snap the associated snap
|
||||
*/
|
||||
public DefaultPcodeDebuggerAccess(PluginTool tool, Target target, TracePlatform platform,
|
||||
long snap) {
|
||||
super(tool, target, platform, snap);
|
||||
public DefaultPcodeDebuggerAccess(ServiceProvider provider, Target target,
|
||||
TracePlatform platform, long snap) {
|
||||
super(provider, target, platform, snap);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultPcodeDebuggerMemoryAccess newDataForSharedState() {
|
||||
return new DefaultPcodeDebuggerMemoryAccess(tool, target, platform, snap, viewport);
|
||||
return new DefaultPcodeDebuggerMemoryAccess(provider, target, platform, snap, viewport);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultPcodeDebuggerRegistersAccess newDataForLocalState(TraceThread thread,
|
||||
int frame) {
|
||||
return new DefaultPcodeDebuggerRegistersAccess(tool, target, platform, snap, thread, frame,
|
||||
viewport);
|
||||
return new DefaultPcodeDebuggerRegistersAccess(provider, target, platform, snap, thread,
|
||||
frame, viewport);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import ghidra.app.services.DebuggerStaticMappingService;
|
||||
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
|
||||
import ghidra.debug.api.emulation.PcodeDebuggerMemoryAccess;
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.generic.util.datastruct.SemisparseByteArray;
|
||||
import ghidra.pcode.exec.trace.data.DefaultPcodeTraceMemoryAccess;
|
||||
import ghidra.pcode.exec.trace.data.PcodeTracePropertyAccess;
|
||||
@ -42,22 +42,22 @@ import ghidra.util.task.TaskMonitor;
|
||||
public class DefaultPcodeDebuggerMemoryAccess extends DefaultPcodeTraceMemoryAccess
|
||||
implements PcodeDebuggerMemoryAccess, InternalPcodeDebuggerDataAccess {
|
||||
|
||||
protected final PluginTool tool;
|
||||
protected final ServiceProvider provider;
|
||||
protected final Target target;
|
||||
|
||||
/**
|
||||
* Construct a shim
|
||||
*
|
||||
* @param tool the tool controlling the session
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param target the target
|
||||
* @param platform the associated platform, having the same trace as the recorder
|
||||
* @param snap the associated snap
|
||||
* @param viewport the viewport, set to the same snapshot
|
||||
*/
|
||||
protected DefaultPcodeDebuggerMemoryAccess(PluginTool tool, Target target,
|
||||
protected DefaultPcodeDebuggerMemoryAccess(ServiceProvider provider, Target target,
|
||||
TracePlatform platform, long snap, TraceTimeViewport viewport) {
|
||||
super(platform, snap, viewport);
|
||||
this.tool = Objects.requireNonNull(tool);
|
||||
this.provider = Objects.requireNonNull(provider);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@ -67,8 +67,8 @@ public class DefaultPcodeDebuggerMemoryAccess extends DefaultPcodeTraceMemoryAcc
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTool getTool() {
|
||||
return tool;
|
||||
public ServiceProvider getServiceProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,7 +97,7 @@ public class DefaultPcodeDebuggerMemoryAccess extends DefaultPcodeTraceMemoryAcc
|
||||
public boolean readFromStaticImages(SemisparseByteArray bytes, AddressSetView guestView) {
|
||||
// TODO: Expand to block? DON'T OVERWRITE KNOWN!
|
||||
DebuggerStaticMappingService mappingService =
|
||||
tool.getService(DebuggerStaticMappingService.class);
|
||||
provider.getService(DebuggerStaticMappingService.class);
|
||||
if (mappingService == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public class DefaultPcodeDebuggerPropertyAccess<T>
|
||||
@Override
|
||||
protected T whenNull(Address hostAddress) {
|
||||
DebuggerStaticMappingService mappingService =
|
||||
data.getTool().getService(DebuggerStaticMappingService.class);
|
||||
data.getServiceProvider().getService(DebuggerStaticMappingService.class);
|
||||
if (mappingService == null) {
|
||||
return super.whenNull(hostAddress);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.debug.api.emulation.PcodeDebuggerRegistersAccess;
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.pcode.exec.trace.data.DefaultPcodeTraceRegistersAccess;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
@ -33,13 +33,13 @@ import ghidra.trace.model.thread.TraceThread;
|
||||
public class DefaultPcodeDebuggerRegistersAccess extends DefaultPcodeTraceRegistersAccess
|
||||
implements PcodeDebuggerRegistersAccess, InternalPcodeDebuggerDataAccess {
|
||||
|
||||
protected final PluginTool tool;
|
||||
protected final ServiceProvider provider;
|
||||
protected final Target target;
|
||||
|
||||
/**
|
||||
* Construct a shim
|
||||
*
|
||||
* @param tool the tool controlling the session
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param target the target
|
||||
* @param platform the associated platform, having the same trace as the recorder
|
||||
* @param snap the associated snap
|
||||
@ -47,11 +47,11 @@ public class DefaultPcodeDebuggerRegistersAccess extends DefaultPcodeTraceRegist
|
||||
* @param frame the associated frame, or 0 if not applicable
|
||||
* @param viewport the viewport, set to the same snapshot
|
||||
*/
|
||||
protected DefaultPcodeDebuggerRegistersAccess(PluginTool tool, Target target,
|
||||
protected DefaultPcodeDebuggerRegistersAccess(ServiceProvider provider, Target target,
|
||||
TracePlatform platform, long snap, TraceThread thread, int frame,
|
||||
TraceTimeViewport viewport) {
|
||||
super(platform, snap, thread, frame, viewport);
|
||||
this.tool = tool;
|
||||
this.provider = provider;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@ -61,8 +61,8 @@ public class DefaultPcodeDebuggerRegistersAccess extends DefaultPcodeTraceRegist
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginTool getTool() {
|
||||
return tool;
|
||||
public ServiceProvider getServiceProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,14 +16,14 @@
|
||||
package ghidra.app.plugin.core.debug.service.emulation.data;
|
||||
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.lifecycle.Internal;
|
||||
import ghidra.pcode.exec.trace.data.InternalPcodeTraceDataAccess;
|
||||
import ghidra.trace.model.TraceTimeViewport;
|
||||
|
||||
@Internal
|
||||
public interface InternalPcodeDebuggerDataAccess extends InternalPcodeTraceDataAccess {
|
||||
PluginTool getTool();
|
||||
ServiceProvider getServiceProvider();
|
||||
|
||||
Target getTarget();
|
||||
|
||||
|
@ -20,18 +20,21 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ghidra.app.plugin.core.debug.utils.ProgramURLUtils;
|
||||
import ghidra.app.services.DebuggerStaticMappingService;
|
||||
import ghidra.debug.api.modules.MapEntry;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.framework.model.ProjectData;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Library;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.ExternalManager;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.*;
|
||||
import ghidra.trace.model.modules.*;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.ComparatorMath;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@ -301,4 +304,55 @@ public enum DebuggerStaticMappingUtils {
|
||||
}
|
||||
return names.stream().collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
public static Function getFunction(Address pc, DebuggerCoordinates coordinates,
|
||||
ServiceProvider serviceProvider) {
|
||||
if (pc == null) {
|
||||
return null;
|
||||
}
|
||||
DebuggerStaticMappingService mappingService =
|
||||
serviceProvider.getService(DebuggerStaticMappingService.class);
|
||||
if (mappingService == null) {
|
||||
return null;
|
||||
}
|
||||
TraceThread curThread = coordinates.getThread();
|
||||
if (curThread == null) {
|
||||
return null;
|
||||
}
|
||||
TraceLocation dloc = new DefaultTraceLocation(curThread.getTrace(),
|
||||
curThread, Lifespan.at(coordinates.getSnap()), pc);
|
||||
ProgramLocation sloc = mappingService.getOpenMappedLocation(dloc);
|
||||
if (sloc == null) {
|
||||
return null;
|
||||
}
|
||||
return sloc.getProgram().getFunctionManager().getFunctionContaining(sloc.getAddress());
|
||||
}
|
||||
|
||||
public static String computeModuleShortName(String path) {
|
||||
int sep = path.lastIndexOf('\\');
|
||||
if (sep > 0 && sep < path.length()) {
|
||||
path = path.substring(sep + 1);
|
||||
}
|
||||
sep = path.lastIndexOf('/');
|
||||
if (sep > 0 && sep < path.length()) {
|
||||
path = path.substring(sep + 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public static String getModuleName(Address pc, DebuggerCoordinates coordinates) {
|
||||
if (pc == null) {
|
||||
return null;
|
||||
}
|
||||
Trace trace = coordinates.getTrace();
|
||||
if (trace == null) {
|
||||
return null;
|
||||
}
|
||||
for (TraceModule module : trace.getModuleManager()
|
||||
.getModulesAt(coordinates.getSnap(), pc)) {
|
||||
// Just take the first
|
||||
return computeModuleShortName(module.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import ghidra.app.plugin.processors.sleigh.SleighException;
|
||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||
import ghidra.app.services.DebuggerStaticMappingService;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.pcode.emu.ThreadPcodeExecutorState;
|
||||
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
||||
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
|
||||
@ -73,12 +73,12 @@ public enum DebuggerPcodeUtils {
|
||||
/**
|
||||
* Construct a parser bound to the given coordinates
|
||||
*
|
||||
* @param tool the tool for the mapping service
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param coordinates the current coordinates for context
|
||||
*/
|
||||
public LabelBoundPcodeParser(PluginTool tool, DebuggerCoordinates coordinates) {
|
||||
public LabelBoundPcodeParser(ServiceProvider provider, DebuggerCoordinates coordinates) {
|
||||
super((SleighLanguage) coordinates.getPlatform().getLanguage());
|
||||
this.mappings = tool.getService(DebuggerStaticMappingService.class);
|
||||
this.mappings = provider.getService(DebuggerStaticMappingService.class);
|
||||
this.coordinates = coordinates;
|
||||
}
|
||||
|
||||
@ -194,15 +194,17 @@ public enum DebuggerPcodeUtils {
|
||||
* substituted for their offsets. If a label moves, the program should be recompiled in order to
|
||||
* update those substitutions.
|
||||
*
|
||||
* @param tool the tool for context
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param coordinates the coordinates for the trace (and programs) from which labels can be
|
||||
* resolved
|
||||
* @see SleighProgramCompiler#compileProgram(PcodeParser, SleighLanguage, String, String,
|
||||
* PcodeUseropLibrary)
|
||||
*/
|
||||
public static PcodeProgram compileProgram(PluginTool tool, DebuggerCoordinates coordinates,
|
||||
public static PcodeProgram compileProgram(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates,
|
||||
String sourceName, String source, PcodeUseropLibrary<?> library) {
|
||||
return SleighProgramCompiler.compileProgram(new LabelBoundPcodeParser(tool, coordinates),
|
||||
return SleighProgramCompiler.compileProgram(
|
||||
new LabelBoundPcodeParser(provider, coordinates),
|
||||
(SleighLanguage) coordinates.getPlatform().getLanguage(), sourceName, source, library);
|
||||
}
|
||||
|
||||
@ -211,13 +213,14 @@ public enum DebuggerPcodeUtils {
|
||||
*
|
||||
* <p>
|
||||
* This has the same limitations as
|
||||
* {@link #compileProgram(PluginTool, DebuggerCoordinates, String, String, PcodeUseropLibrary)}
|
||||
* {@link #compileProgram(ServiceProvider, DebuggerCoordinates, String, String, PcodeUseropLibrary)}
|
||||
*
|
||||
* @see SleighProgramCompiler#compileExpression(PcodeParser, SleighLanguage, String)
|
||||
*/
|
||||
public static PcodeExpression compileExpression(PluginTool tool,
|
||||
public static PcodeExpression compileExpression(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates, String source) {
|
||||
return SleighProgramCompiler.compileExpression(new LabelBoundPcodeParser(tool, coordinates),
|
||||
return SleighProgramCompiler.compileExpression(
|
||||
new LabelBoundPcodeParser(provider, coordinates),
|
||||
(SleighLanguage) coordinates.getPlatform().getLanguage(), source);
|
||||
}
|
||||
|
||||
@ -228,11 +231,11 @@ public enum DebuggerPcodeUtils {
|
||||
* If a thread is included, the executor state will have access to both the memory and registers
|
||||
* in the context of that thread. Otherwise, only memory access is permitted.
|
||||
*
|
||||
* @param tool the plugin tool
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param coordinates the coordinates
|
||||
* @return the state
|
||||
*/
|
||||
public static PcodeExecutorState<byte[]> executorStateForCoordinates(PluginTool tool,
|
||||
public static PcodeExecutorState<byte[]> executorStateForCoordinates(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates) {
|
||||
Trace trace = coordinates.getTrace();
|
||||
if (trace == null) {
|
||||
@ -244,7 +247,7 @@ public enum DebuggerPcodeUtils {
|
||||
throw new IllegalArgumentException(
|
||||
"Given trace or platform does not use a Sleigh language");
|
||||
}
|
||||
DefaultPcodeDebuggerAccess access = new DefaultPcodeDebuggerAccess(tool,
|
||||
DefaultPcodeDebuggerAccess access = new DefaultPcodeDebuggerAccess(provider,
|
||||
coordinates.getTarget(), platform, coordinates.getViewSnap());
|
||||
PcodeExecutorState<byte[]> shared =
|
||||
new RWTargetMemoryPcodeExecutorState(access.getDataForSharedState(), Mode.RW);
|
||||
@ -270,13 +273,13 @@ public enum DebuggerPcodeUtils {
|
||||
* If a thread is included, the executor will have access to both the memory and registers in
|
||||
* the context of that thread. Otherwise, only memory access is permitted.
|
||||
*
|
||||
* @param tool the plugin tool. TODO: This shouldn't be required
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param coordinates the coordinates
|
||||
* @return the executor
|
||||
*/
|
||||
public static PcodeExecutor<byte[]> executorForCoordinates(PluginTool tool,
|
||||
public static PcodeExecutor<byte[]> executorForCoordinates(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates) {
|
||||
PcodeExecutorState<byte[]> state = executorStateForCoordinates(tool, coordinates);
|
||||
PcodeExecutorState<byte[]> state = executorStateForCoordinates(provider, coordinates);
|
||||
|
||||
SleighLanguage slang = (SleighLanguage) state.getLanguage();
|
||||
return new PcodeExecutor<>(slang, BytesPcodeArithmetic.forLanguage(slang), state,
|
||||
@ -695,12 +698,12 @@ public enum DebuggerPcodeUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static WatchValuePcodeExecutorState buildWatchState(PluginTool tool,
|
||||
public static WatchValuePcodeExecutorState buildWatchState(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates) {
|
||||
PcodeTraceDataAccess data = new DefaultPcodeTraceAccess(coordinates.getPlatform(),
|
||||
coordinates.getViewSnap(), coordinates.getSnap())
|
||||
.getDataForThreadState(coordinates.getThread(), coordinates.getFrame());
|
||||
PcodeExecutorState<byte[]> bytesState = executorStateForCoordinates(tool, coordinates);
|
||||
PcodeExecutorState<byte[]> bytesState = executorStateForCoordinates(provider, coordinates);
|
||||
return new WatchValuePcodeExecutorState(new WatchValuePcodeExecutorStatePiece(
|
||||
bytesState,
|
||||
new TraceMemoryStatePcodeExecutorStatePiece(data),
|
||||
@ -717,18 +720,18 @@ public enum DebuggerPcodeUtils {
|
||||
* machine state, if applicable. Use the executor in a background thread to avoid locking the
|
||||
* GUI.
|
||||
*
|
||||
* @param tool this plugin tool
|
||||
* @param provider the service provider (usually the tool)
|
||||
* @param coordinates the coordinates providing context for the evaluation
|
||||
* @return an executor for evaluating the watch
|
||||
*/
|
||||
public static PcodeExecutor<WatchValue> buildWatchExecutor(PluginTool tool,
|
||||
public static PcodeExecutor<WatchValue> buildWatchExecutor(ServiceProvider provider,
|
||||
DebuggerCoordinates coordinates) {
|
||||
TracePlatform platform = coordinates.getPlatform();
|
||||
Language language = platform.getLanguage();
|
||||
if (!(language instanceof SleighLanguage slang)) {
|
||||
throw new IllegalArgumentException("Watch expressions require a Sleigh language");
|
||||
}
|
||||
WatchValuePcodeExecutorState state = buildWatchState(tool, coordinates);
|
||||
WatchValuePcodeExecutorState state = buildWatchState(provider, coordinates);
|
||||
return new PcodeExecutor<>(slang, state.getArithmetic(), state, Reason.INSPECT);
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,15 @@ public class DefaultEnumeratedColumnTableModel<C extends Enum<C> & EnumeratedTab
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this column should be visible by default
|
||||
*
|
||||
* @return true if visible
|
||||
*/
|
||||
default public boolean isVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default sort direction for this column
|
||||
*
|
||||
@ -217,10 +226,15 @@ public class DefaultEnumeratedColumnTableModel<C extends Enum<C> & EnumeratedTab
|
||||
if (cols != null) { // Smells
|
||||
List<C> defaultOrder = defaultSortOrder();
|
||||
for (C col : cols) {
|
||||
descriptor.addVisibleColumn(
|
||||
new EnumeratedDynamicTableColumn<R>(col),
|
||||
defaultOrder.indexOf(col), // -1 means not found, not sorted
|
||||
col.defaultSortDirection().isAscending());
|
||||
EnumeratedDynamicTableColumn<R> ecol = new EnumeratedDynamicTableColumn<R>(col);
|
||||
if (col.isVisible()) {
|
||||
descriptor.addVisibleColumn(ecol,
|
||||
defaultOrder.indexOf(col), // -1 means not found, not sorted
|
||||
col.defaultSortDirection().isAscending());
|
||||
}
|
||||
else {
|
||||
descriptor.addHiddenColumn(ecol);
|
||||
}
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
|
Loading…
Reference in New Issue
Block a user