Merge remote-tracking branch 'origin/GP-1822_d-millar_navigation_improvements' into patch

This commit is contained in:
Ryan Kurtz 2022-03-19 01:18:21 -04:00
commit ded1ba47ab
9 changed files with 138 additions and 99 deletions

View file

@ -170,6 +170,7 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
}));
}
@Override
public Map<String, byte[]> getCachedRegisters() {
return values;
}

View file

@ -25,9 +25,14 @@ import ghidra.dbg.target.TargetRegister;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "RegisterDescriptor", elements = {
@TargetElementType(type = Void.class) }, attributes = {
@TargetAttributeType(name = TargetRegister.CONTAINER_ATTRIBUTE_NAME, type = DbgModelTargetRegisterContainerImpl.class),
@TargetObjectSchemaInfo(
name = "RegisterDescriptor",
elements = {
@TargetElementType(type = Void.class) },
attributes = {
@TargetAttributeType(
name = TargetRegister.CONTAINER_ATTRIBUTE_NAME,
type = DbgModelTargetRegisterContainerImpl.class),
@TargetAttributeType(type = Void.class) })
public class DbgModelTargetRegisterImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetRegister {

View file

@ -27,6 +27,7 @@ import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
@TargetObjectSchemaInfo(
name = "StackFrame",
@ -41,16 +42,16 @@ import ghidra.program.model.address.Address;
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.INST_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.FRAME_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.RETURN_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.STACK_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.VIRTUAL_ATTRIBUTE_NAME,
type = Boolean.class),
@ -141,15 +142,16 @@ public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl
// TODO: module? "from"
this.frame = frame;
AddressSpace space = getModel().getAddressSpace("ram");
changeAttributes(List.of(), List.of(), Map.of( //
PC_ATTRIBUTE_NAME, pc, //
DISPLAY_ATTRIBUTE_NAME, display = computeDisplay(frame), //
FUNC_ATTRIBUTE_NAME, func, //
FUNC_TABLE_ENTRY_ATTRIBUTE_NAME, Long.toHexString(funcTableEntry), //
INST_OFFSET_ATTRIBUTE_NAME, Long.toHexString(lval), //
FRAME_OFFSET_ATTRIBUTE_NAME, Long.toHexString(frameOffset), //
RETURN_OFFSET_ATTRIBUTE_NAME, Long.toHexString(returnOffset), //
STACK_OFFSET_ATTRIBUTE_NAME, Long.toHexString(stackOffset), //
INST_OFFSET_ATTRIBUTE_NAME, space.getAddress(lval), //
FRAME_OFFSET_ATTRIBUTE_NAME, space.getAddress(frameOffset), //
RETURN_OFFSET_ATTRIBUTE_NAME, space.getAddress(returnOffset), //
STACK_OFFSET_ATTRIBUTE_NAME, space.getAddress(stackOffset), //
VIRTUAL_ATTRIBUTE_NAME, virtual //
), "Refreshed");
changeAttributes(List.of(), List.of(), Map.of( //

View file

@ -104,7 +104,8 @@ public class GdbModelTargetStackFrame extends DefaultTargetObject<TargetObject,
), Map.of( //
PC_ATTRIBUTE_NAME, pc, //
FUNC_ATTRIBUTE_NAME, func, //
DISPLAY_ATTRIBUTE_NAME, display = computeDisplay(frame) //
DISPLAY_ATTRIBUTE_NAME, display = computeDisplay(frame), //
VALUE_ATTRIBUTE_NAME, pc //
), "Refreshed");
}

View file

@ -31,6 +31,7 @@ import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
@TargetObjectSchemaInfo(
name = "StackFrame",
@ -50,19 +51,19 @@ import ghidra.program.model.address.Address;
type = String.class),
@TargetAttributeType(
name = LldbModelTargetStackFrame.INST_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = LldbModelTargetStackFrame.FRAME_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = LldbModelTargetStackFrame.RETURN_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = LldbModelTargetStackFrame.CALL_FRAME_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(
name = LldbModelTargetStackFrame.STACK_OFFSET_ATTRIBUTE_NAME,
type = String.class),
type = Address.class),
@TargetAttributeType(type = Void.class) })
public class LldbModelTargetStackFrameImpl extends LldbModelTargetObjectImpl
implements LldbModelTargetStackFrame {
@ -100,7 +101,7 @@ public class LldbModelTargetStackFrameImpl extends LldbModelTargetObjectImpl
function = null;
return;
}
this.registers = new LldbModelTargetStackFrameRegisterContainerImpl(this);
this.function = new LldbModelTargetFunctionImpl(this, frame.GetFunction());
@ -116,6 +117,7 @@ public class LldbModelTargetStackFrameImpl extends LldbModelTargetObjectImpl
getManager().addEventsListener(this);
}
@Override
public String getDescription(int level) {
SBStream stream = new SBStream();
SBFrame frame = (SBFrame) getModelObject();
@ -127,7 +129,8 @@ public class LldbModelTargetStackFrameImpl extends LldbModelTargetObjectImpl
if (frame.GetFunction() == null) {
return String.format("#%d 0x%s", DebugClient.getId(frame), frame.GetPC().toString(16));
}
return String.format("#%d 0x%s in %s ()", DebugClient.getId(frame), frame.GetPC().toString(16),
return String.format("#%d 0x%s in %s ()", DebugClient.getId(frame),
frame.GetPC().toString(16),
frame.GetDisplayFunctionName());
}
@ -163,14 +166,15 @@ public class LldbModelTargetStackFrameImpl extends LldbModelTargetObjectImpl
this.stackOffset = frame.GetSP().longValue();
this.callFrameOffset = frame.GetCFA().longValue();
AddressSpace space = getModel().getAddressSpace("ram");
changeAttributes(List.of(), List.of(), Map.of( //
PC_ATTRIBUTE_NAME, pc, //
DISPLAY_ATTRIBUTE_NAME, display = getDescription(0), //computeDisplay(frame), //
FUNC_ATTRIBUTE_NAME, func, //
INST_OFFSET_ATTRIBUTE_NAME, Long.toHexString(lval), //
FRAME_OFFSET_ATTRIBUTE_NAME, Long.toHexString(frameOffset), //
STACK_OFFSET_ATTRIBUTE_NAME, Long.toHexString(stackOffset), //
CALL_FRAME_OFFSET_ATTRIBUTE_NAME, Long.toHexString(callFrameOffset) //
INST_OFFSET_ATTRIBUTE_NAME, space.getAddress(lval), //
FRAME_OFFSET_ATTRIBUTE_NAME, space.getAddress(frameOffset), //
STACK_OFFSET_ATTRIBUTE_NAME, space.getAddress(stackOffset), //
CALL_FRAME_OFFSET_ATTRIBUTE_NAME, space.getAddress(callFrameOffset) //
), "Refreshed");
}

View file

@ -60,6 +60,7 @@ public class LldbModelTargetStackFrameRegisterImpl
), "Initialized");
}
@Override
public String getDescription(int level) {
SBStream stream = new SBStream();
SBValue val = (SBValue) getModelObject();
@ -89,6 +90,7 @@ public class LldbModelTargetStackFrameRegisterImpl
return (SBValue) getModelObject();
}
@Override
public byte[] getBytes() {
String oldValue = value;
value = getValue();
@ -115,6 +117,7 @@ public class LldbModelTargetStackFrameRegisterImpl
return bytes;
}
@Override
public String getDisplay() {
return getValue() == null ? getName() : getName() + " : " + getValue();
}

View file

@ -45,6 +45,7 @@ import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
import ghidra.app.plugin.core.debug.gui.objects.actions.*;
import ghidra.app.plugin.core.debug.gui.objects.components.*;
import ghidra.app.plugin.core.debug.mapping.DebuggerMemoryMapper;
import ghidra.app.services.*;
import ghidra.async.*;
import ghidra.dbg.*;
@ -63,8 +64,7 @@ import ghidra.framework.options.annotation.*;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.annotation.AutoConfigStateField;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.trace.model.Trace;
import ghidra.trace.model.thread.TraceThread;
@ -1252,6 +1252,21 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
.buildAndInstallLocal(this);
groupTargetIndex++;
new ActionBuilder("GoTo", plugin.getName())
.keyBinding("G")
.toolBarGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex)
.popupMenuPath("&GoTo")
.popupMenuGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex)
.helpLocation(AbstractToggleAction.help(plugin))
.enabledWhen(ctx -> isInstance(ctx, TargetObject.class))
.popupWhen(ctx -> isInstance(ctx, TargetObject.class))
.onAction(ctx -> performNavigate(ctx))
.enabled(false)
.buildAndInstallLocal(this);
groupTargetIndex++;
displayAsTreeAction = new DisplayAsTreeAction(tool, plugin.getName(), this);
displayAsTableAction = new DisplayAsTableAction(tool, plugin.getName(), this);
@ -1545,6 +1560,15 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
}, "Couldn't configure one or more options");
}
public void performNavigate(ActionContext context) {
performAction(context, false, TargetObject.class, t -> {
if (t != null) {
navigateToSelectedObject(t, null);
}
return AsyncUtils.NIL;
}, "Couldn't navigate");
}
public void initiateConsole(ActionContext context) {
performAction(context, false, TargetInterpreter.class, interpreter -> {
getPlugin().showConsole(interpreter);
@ -1840,4 +1864,68 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
return listener.queue.in;
}
public void navigateToSelectedObject(TargetObject object, Object value) {
if (listingService == null || listingService == null) {
return;
}
if (value == null) {
value =
object.getCachedAttribute(TargetBreakpointLocation.ADDRESS_ATTRIBUTE_NAME);
}
if (value == null) {
value = object.getCachedAttribute(TargetObject.PREFIX_INVISIBLE + "range");
}
if (value == null) {
value = object.getCachedAttribute(TargetObject.VALUE_ATTRIBUTE_NAME);
}
if (value == null) {
return;
}
Address addr = null;
if (value instanceof Address) {
addr = (Address) value;
}
else if (value instanceof AddressRangeImpl) {
AddressRangeImpl range = (AddressRangeImpl) value;
addr = range.getMinAddress();
}
else if (value instanceof Long) {
Long lval = (Long) value;
addr = object.getModel().getAddress("ram", lval);
}
else if (value instanceof String) {
String sval = (String) value;
addr = stringToAddress(object, addr, sval);
}
if (addr != null) {
TraceRecorder recorder = modelService.getRecorderForSuccessor(object);
if (recorder == null) {
recorder = modelService.getRecorder(currentTrace);
if (recorder == null) {
return;
}
}
DebuggerMemoryMapper memoryMapper = recorder.getMemoryMapper();
Address traceAddr = memoryMapper.targetToTrace(addr);
listingService.goTo(traceAddr, true);
}
}
private Address stringToAddress(TargetObject selectedObject, Address addr, String sval) {
Integer base = 16;
if (selectedObject instanceof TargetConfigurable) {
TargetConfigurable configurable = (TargetConfigurable) selectedObject;
base =
(Integer) configurable.getCachedAttribute(TargetConfigurable.BASE_ATTRIBUTE_NAME);
}
try {
Long lval = Long.parseLong(sval, base);
addr = selectedObject.getModel().getAddress("ram", lval);
}
catch (NumberFormatException nfe) {
// IGNORE
}
return addr;
}
}

View file

@ -27,11 +27,7 @@ import docking.widgets.table.AbstractSortedTableModel;
import docking.widgets.table.EnumeratedColumnTableModel;
import ghidra.app.plugin.core.debug.gui.objects.DebuggerObjectsProvider;
import ghidra.app.plugin.core.debug.gui.objects.ObjectContainer;
import ghidra.app.plugin.core.debug.mapping.DebuggerMemoryMapper;
import ghidra.app.services.*;
import ghidra.dbg.target.TargetObject;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRangeImpl;
import ghidra.util.Swing;
import ghidra.util.table.GhidraTable;
import resources.ResourceManager;
@ -45,8 +41,6 @@ public class ObjectTable<R> implements ObjectPane {
private AbstractSortedTableModel<R> model;
private GhidraTable table;
private JScrollPane component;
private DebuggerListingService listingService;
private DebuggerModelService modelService;
public ObjectTable(ObjectContainer container, Class<R> clazz,
AbstractSortedTableModel<R> model) {
@ -55,8 +49,6 @@ public class ObjectTable<R> implements ObjectPane {
this.container = container;
this.clazz = clazz;
this.model = model;
this.listingService = container.getProvider().getListingService();
this.modelService = container.getProvider().getModelService();
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
@ -72,7 +64,11 @@ public class ObjectTable<R> implements ObjectPane {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
navigateToSelectedObject();
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
Object value = table.getValueAt(selectedRow, selectedColumn);
container.getProvider()
.navigateToSelectedObject(container.getTargetObject(), value);
}
}
});
@ -279,31 +275,4 @@ public class ObjectTable<R> implements ObjectPane {
container.setTargetObject(targetObject);
}
protected void navigateToSelectedObject() {
if (listingService != null) {
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
Object value = table.getValueAt(selectedRow, selectedColumn);
Address addr = null;
if (value instanceof Address) {
addr = (Address) value;
}
if (value instanceof AddressRangeImpl) {
AddressRangeImpl range = (AddressRangeImpl) value;
addr = range.getMinAddress();
}
if (value instanceof Long) {
Long lval = (Long) value;
addr = container.getTargetObject().getModel().getAddress("ram", lval);
}
if (modelService != null) {
TraceRecorder recorder =
modelService.getRecorderForSuccessor(container.getTargetObject());
DebuggerMemoryMapper memoryMapper = recorder.getMemoryMapper();
Address traceAddr = memoryMapper.targetToTrace(addr);
listingService.goTo(traceAddr, true);
}
}
}
}

View file

@ -35,15 +35,11 @@ import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin;
import docking.widgets.tree.support.GTreeSelectionListener;
import ghidra.app.plugin.core.debug.gui.objects.DebuggerObjectsProvider;
import ghidra.app.plugin.core.debug.gui.objects.ObjectContainer;
import ghidra.app.plugin.core.debug.mapping.DebuggerMemoryMapper;
import ghidra.app.services.*;
import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec;
import ghidra.dbg.DebugModelConventions;
import ghidra.dbg.target.TargetAccessConditioned;
import ghidra.dbg.target.TargetObject;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRangeImpl;
import ghidra.util.*;
import ghidra.util.task.SwingUpdateManager;
import resources.ResourceManager;
@ -63,17 +59,11 @@ public class ObjectTree implements ObjectPane {
private SwingUpdateManager restoreTreeStateManager =
new SwingUpdateManager(this::restoreTreeState);
private DebuggerListingService listingService;
private DebuggerModelService modelService;
public ObjectTree(ObjectContainer container) {
this.root = new ObjectNode(this, null, container);
addToMap(null, container, root);
this.tree = new GTree(root);
this.listingService = container.getProvider().getListingService();
this.modelService = container.getProvider().getModelService();
tree.addGTreeSelectionListener(new GTreeSelectionListener() {
@Override
public void valueChanged(GTreeSelectionEvent e) {
@ -165,7 +155,10 @@ public class ObjectTree implements ObjectPane {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
navigateToSelectedObject();
TargetObject selectedObject = getSelectedObject();
if (selectedObject != null) {
container.getProvider().navigateToSelectedObject(selectedObject, null);
}
}
}
});
@ -407,31 +400,4 @@ public class ObjectTree implements ObjectPane {
nodeMap.remove(path(node.getContainer()));
}
protected void navigateToSelectedObject() {
if (listingService != null) {
TargetObject selectedObject = getSelectedObject();
if (selectedObject == null) {
return;
}
Object value = selectedObject.getCachedAttribute(TargetObject.VALUE_ATTRIBUTE_NAME);
Address addr = null;
if (value instanceof Address) {
addr = (Address) value;
}
if (value instanceof AddressRangeImpl) {
AddressRangeImpl range = (AddressRangeImpl) value;
addr = range.getMinAddress();
}
if (value instanceof Long) {
Long lval = (Long) value;
addr = selectedObject.getModel().getAddress("ram", lval);
}
if (modelService != null && addr != null) {
TraceRecorder recorder = modelService.getRecorderForSuccessor(selectedObject);
DebuggerMemoryMapper memoryMapper = recorder.getMemoryMapper();
Address traceAddr = memoryMapper.targetToTrace(addr);
listingService.goTo(traceAddr, true);
}
}
}
}