mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 13:43:00 +00:00
Merge remote-tracking branch 'origin/GP-1822_d-millar_navigation_improvements' into patch
This commit is contained in:
commit
ded1ba47ab
|
@ -170,6 +170,7 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
|
|||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, byte[]> getCachedRegisters() {
|
||||
return values;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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( //
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue