GP-884: Improved location label (subheader) in dynamic listing

This commit is contained in:
Dan 2021-04-27 15:36:23 -04:00
parent 983b78333e
commit c70496680d
5 changed files with 74 additions and 20 deletions

View file

@ -90,6 +90,7 @@ public class DbgModelTargetMemoryRegionImpl extends DbgModelTargetObjectImpl
isExec = region.isExec(); isExec = region.isExec();
this.changeAttributes(List.of(), List.of(), Map.of( // this.changeAttributes(List.of(), List.of(), Map.of( //
DISPLAY_ATTRIBUTE_NAME, computeDisplay(region), //
MEMORY_ATTRIBUTE_NAME, memory, // MEMORY_ATTRIBUTE_NAME, memory, //
RANGE_ATTRIBUTE_NAME, doGetRange(section), // RANGE_ATTRIBUTE_NAME, doGetRange(section), //
READABLE_ATTRIBUTE_NAME, isReadable(), // READABLE_ATTRIBUTE_NAME, isReadable(), //
@ -110,6 +111,10 @@ public class DbgModelTargetMemoryRegionImpl extends DbgModelTargetObjectImpl
), "Initialized"); ), "Initialized");
} }
protected String computeDisplay(DbgModuleMemory region) {
return region.getType() + " " + getName(); // NB. Name will contain []s
}
protected AddressRange doGetRange(DbgModuleMemory s) { protected AddressRange doGetRange(DbgModuleMemory s) {
AddressSpace addressSpace = getModel().getAddressSpace("ram"); AddressSpace addressSpace = getModel().getAddressSpace("ram");
Address min = addressSpace.getAddress(s.getVmaStart()); Address min = addressSpace.getAddress(s.getVmaStart());

View file

@ -52,10 +52,10 @@ public class GdbModelTargetMemoryRegion
protected static String computeDisplay(GdbMemoryMapping mapping) { protected static String computeDisplay(GdbMemoryMapping mapping) {
// NOTE: This deviates from GDB's table display, as it'd be confusing in isolation // NOTE: This deviates from GDB's table display, as it'd be confusing in isolation
if (mapping.getObjfile() == null || mapping.getObjfile().length() == 0) { if (mapping.getObjfile() == null || mapping.getObjfile().length() == 0) {
return String.format("[0x%x-0x%x] (no file)", mapping.getStart(), mapping.getEnd()); return String.format("?? [0x%x-0x%x]", mapping.getStart(), mapping.getEnd());
} }
return String.format("[0x%x-0x%x] %s(0x%x)", mapping.getStart(), mapping.getEnd(), return String.format("%s [0x%x-0x%x] (0x%x)", mapping.getObjfile(), mapping.getStart(),
mapping.getObjfile(), mapping.getOffset()); mapping.getEnd(), mapping.getOffset());
} }
protected AddressRangeImpl range; protected AddressRangeImpl range;

View file

@ -30,6 +30,7 @@ import javax.swing.JLabel;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import org.apache.commons.collections4.ComparatorUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jdom.Element; import org.jdom.Element;
@ -72,7 +73,6 @@ import ghidra.pcode.utils.Utils;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.*; import ghidra.trace.model.*;
@ -656,7 +656,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
setSubTitle(computeSubTitle()); setSubTitle(computeSubTitle());
} }
protected TraceSection getSmallestSectionAt(Address address) { protected TraceSection getNearestSectionContaining(Address address) {
if (current.getView() == null) { if (current.getView() == null) {
return null; return null;
} }
@ -666,8 +666,36 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
if (sections.isEmpty()) { if (sections.isEmpty()) {
return null; return null;
} }
sections.sort(Comparator.comparing(s -> s.getRange().getLength())); // TODO: DB's R-Tree could probably do this natively
return sections.get(0); sections.sort(ComparatorUtils.chainedComparator(List.of(
Comparator.comparing(s -> s.getRange().getMinAddress()),
Comparator.comparing(s -> -s.getRange().getLength()))));
return sections.get(sections.size() - 1);
}
protected TraceModule getNearestModuleContaining(Address address) {
if (current.getView() == null) {
return null;
}
Trace trace = current.getTrace();
List<TraceModule> modules =
new ArrayList<>(trace.getModuleManager().getModulesAt(current.getSnap(), address));
if (modules.isEmpty()) {
return null;
}
// TODO: DB's R-Tree could probably do this natively
modules.sort(ComparatorUtils.chainedComparator(List.of(
Comparator.comparing(m -> m.getRange().getMinAddress()),
Comparator.comparing(m -> -m.getRange().getLength()))));
return modules.get(modules.size() - 1);
}
protected TraceMemoryRegion getRegionContaining(Address address) {
if (current.getView() == null) {
return null;
}
Trace trace = current.getTrace();
return trace.getMemoryManager().getRegionContaining(current.getSnap(), address);
} }
protected String computeLocationString() { protected String computeLocationString() {
@ -677,19 +705,22 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi
} }
ProgramLocation location = getListingPanel().getProgramLocation(); ProgramLocation location = getListingPanel().getProgramLocation();
if (location == null) { if (location == null) {
return view.getDomainFile().getName(); return "(nowhere)";
} }
Address address = location.getAddress(); Address address = location.getAddress();
TraceSection section = getSmallestSectionAt(address); TraceSection section = getNearestSectionContaining(address);
if (section != null) { if (section != null) {
return view.getDomainFile().getName() + " (" + section.getModule().getName() + ":" + return section.getModule().getName() + ":" + section.getName();
section.getName() + ")";
} }
MemoryBlock block = view.getMemory().getBlock(address); TraceModule module = getNearestModuleContaining(address);
if (block == null) { if (module != null) {
return view.getDomainFile().getName(); return module.getName();
} }
return view.getDomainFile().getName() + " (" + block.getName() + ")"; TraceMemoryRegion region = getRegionContaining(address);
if (region != null) {
return region.getName();
}
return "(unknown)";
} }
protected void updateLocationLabel() { protected void updateLocationLabel() {

View file

@ -25,7 +25,6 @@ import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
import ghidra.dbg.target.TargetMemory; import ghidra.dbg.target.TargetMemory;
import ghidra.dbg.target.TargetMemoryRegion; import ghidra.dbg.target.TargetMemoryRegion;
import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.model.Trace; import ghidra.trace.model.Trace;
import ghidra.trace.model.memory.*; import ghidra.trace.model.memory.*;
@ -101,7 +100,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
TargetMemory mem = region.getMemory(); TargetMemory mem = region.getMemory();
recorder.getProcessMemory().addRegion(region, mem); recorder.getProcessMemory().addRegion(region, mem);
//recorder.objectManager.addMemory(mem); //recorder.objectManager.addMemory(mem);
String path = PathUtils.toString(region.getPath()); String path = region.getJoinedPath(".");
long snap = recorder.getSnap(); long snap = recorder.getSnap();
recorder.parTx.execute("Memory region " + path + " added", () -> { recorder.parTx.execute("Memory region " + path + " added", () -> {
try { try {
@ -114,7 +113,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
traceRegion = memoryManager.addRegion(path, Range.atLeast(snap), traceRegion = memoryManager.addRegion(path, Range.atLeast(snap),
recorder.getMemoryMapper().targetToTrace(region.getRange()), recorder.getMemoryMapper().targetToTrace(region.getRange()),
getTraceFlags(region)); getTraceFlags(region));
traceRegion.setName(region.getName()); traceRegion.setName(region.getDisplay());
} }
catch (TraceOverlappedRegionException e) { catch (TraceOverlappedRegionException e) {
Msg.error(this, "Failed to create region due to overlap: " + e); Msg.error(this, "Failed to create region due to overlap: " + e);
@ -128,7 +127,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
@Override @Override
public void removeProcessRegion(TargetMemoryRegion region) { public void removeProcessRegion(TargetMemoryRegion region) {
// Already removed from processMemory. That's how we knew to go here. // Already removed from processMemory. That's how we knew to go here.
String path = PathUtils.toString(region.getPath()); String path = region.getJoinedPath(".");
long snap = recorder.getSnap(); long snap = recorder.getSnap();
recorder.parTx.execute("Memory region " + path + " removed", () -> { recorder.parTx.execute("Memory region " + path + " removed", () -> {
try { try {
@ -148,7 +147,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
@Override @Override
public TraceMemoryRegion getTraceMemoryRegion(TargetMemoryRegion region) { public TraceMemoryRegion getTraceMemoryRegion(TargetMemoryRegion region) {
String path = PathUtils.toString(region.getPath()); String path = region.getJoinedPath(".");
return memoryManager.getLiveRegionByPath(recorder.getSnap(), path); return memoryManager.getLiveRegionByPath(recorder.getSnap(), path);
} }
@ -167,4 +166,16 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder {
return flags; return flags;
} }
public void regionChanged(TargetMemoryRegion region, String display) {
String path = region.getJoinedPath(".");
long snap = recorder.getSnap();
recorder.parTx.execute("Memory region " + path + " changed display", () -> {
TraceMemoryRegion traceRegion = memoryManager.getLiveRegionByPath(snap, path);
if (traceRegion == null) {
Msg.warn(this, "Could not find region " + path + " in trace to rename");
return;
}
traceRegion.setName(display);
}, path);
}
} }

View file

@ -117,6 +117,7 @@ public class TraceObjectManager {
putAttributesHandler(TargetBreakpointSpec.class, this::attributesChangedBreakpointSpec); putAttributesHandler(TargetBreakpointSpec.class, this::attributesChangedBreakpointSpec);
putAttributesHandler(TargetBreakpointLocation.class, putAttributesHandler(TargetBreakpointLocation.class,
this::attributesChangedBreakpointLocation); this::attributesChangedBreakpointLocation);
putAttributesHandler(TargetMemoryRegion.class, this::attributesChangedMemoryRegion);
putAttributesHandler(TargetRegister.class, this::attributesChangedRegister); putAttributesHandler(TargetRegister.class, this::attributesChangedRegister);
putAttributesHandler(TargetStackFrame.class, this::attributesChangedStackFrame); putAttributesHandler(TargetStackFrame.class, this::attributesChangedStackFrame);
putAttributesHandler(TargetThread.class, this::attributesChangedThread); putAttributesHandler(TargetThread.class, this::attributesChangedThread);
@ -494,6 +495,12 @@ public class TraceObjectManager {
} }
} }
public void attributesChangedMemoryRegion(TargetObject region, Map<String, ?> added) {
if (added.containsKey(TargetObject.DISPLAY_ATTRIBUTE_NAME)) {
recorder.memoryRecorder.regionChanged((TargetMemoryRegion) region, region.getDisplay());
}
}
public void attributesChangedRegister(TargetObject parent, Map<String, ?> added) { public void attributesChangedRegister(TargetObject parent, Map<String, ?> added) {
if (added.containsKey(TargetRegister.CONTAINER_ATTRIBUTE_NAME)) { if (added.containsKey(TargetRegister.CONTAINER_ATTRIBUTE_NAME)) {
TargetRegister register = (TargetRegister) parent; TargetRegister register = (TargetRegister) parent;