From c70496680de9d0e69c5080dcfa487a4d6fdce1ed Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Tue, 27 Apr 2021 15:36:23 -0400 Subject: [PATCH] GP-884: Improved location label (subheader) in dynamic listing --- .../impl/DbgModelTargetMemoryRegionImpl.java | 5 ++ .../impl/GdbModelTargetMemoryRegion.java | 6 +- .../gui/listing/DebuggerListingProvider.java | 55 +++++++++++++++---- .../service/model/DefaultMemoryRecorder.java | 21 +++++-- .../service/model/TraceObjectManager.java | 7 +++ 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetMemoryRegionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetMemoryRegionImpl.java index c77e8cfdf4..a4bd855c5f 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetMemoryRegionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetMemoryRegionImpl.java @@ -90,6 +90,7 @@ public class DbgModelTargetMemoryRegionImpl extends DbgModelTargetObjectImpl isExec = region.isExec(); this.changeAttributes(List.of(), List.of(), Map.of( // + DISPLAY_ATTRIBUTE_NAME, computeDisplay(region), // MEMORY_ATTRIBUTE_NAME, memory, // RANGE_ATTRIBUTE_NAME, doGetRange(section), // READABLE_ATTRIBUTE_NAME, isReadable(), // @@ -110,6 +111,10 @@ public class DbgModelTargetMemoryRegionImpl extends DbgModelTargetObjectImpl ), "Initialized"); } + protected String computeDisplay(DbgModuleMemory region) { + return region.getType() + " " + getName(); // NB. Name will contain []s + } + protected AddressRange doGetRange(DbgModuleMemory s) { AddressSpace addressSpace = getModel().getAddressSpace("ram"); Address min = addressSpace.getAddress(s.getVmaStart()); diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetMemoryRegion.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetMemoryRegion.java index 348f8d917e..843b0869e3 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetMemoryRegion.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetMemoryRegion.java @@ -52,10 +52,10 @@ public class GdbModelTargetMemoryRegion protected static String computeDisplay(GdbMemoryMapping mapping) { // NOTE: This deviates from GDB's table display, as it'd be confusing in isolation 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(), - mapping.getObjfile(), mapping.getOffset()); + return String.format("%s [0x%x-0x%x] (0x%x)", mapping.getObjfile(), mapping.getStart(), + mapping.getEnd(), mapping.getOffset()); } protected AddressRangeImpl range; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java index a25a9fc5ed..932fc64903 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProvider.java @@ -30,6 +30,7 @@ import javax.swing.JLabel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.apache.commons.collections4.ComparatorUtils; import org.apache.commons.lang3.StringUtils; import org.jdom.Element; @@ -72,7 +73,6 @@ import ghidra.pcode.utils.Utils; import ghidra.program.model.address.*; import ghidra.program.model.lang.Language; import ghidra.program.model.listing.Program; -import ghidra.program.model.mem.MemoryBlock; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; import ghidra.trace.model.*; @@ -656,7 +656,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi setSubTitle(computeSubTitle()); } - protected TraceSection getSmallestSectionAt(Address address) { + protected TraceSection getNearestSectionContaining(Address address) { if (current.getView() == null) { return null; } @@ -666,8 +666,36 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi if (sections.isEmpty()) { return null; } - sections.sort(Comparator.comparing(s -> s.getRange().getLength())); - return sections.get(0); + // TODO: DB's R-Tree could probably do this natively + 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 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() { @@ -677,19 +705,22 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi } ProgramLocation location = getListingPanel().getProgramLocation(); if (location == null) { - return view.getDomainFile().getName(); + return "(nowhere)"; } Address address = location.getAddress(); - TraceSection section = getSmallestSectionAt(address); + TraceSection section = getNearestSectionContaining(address); if (section != null) { - return view.getDomainFile().getName() + " (" + section.getModule().getName() + ":" + - section.getName() + ")"; + return section.getModule().getName() + ":" + section.getName(); } - MemoryBlock block = view.getMemory().getBlock(address); - if (block == null) { - return view.getDomainFile().getName(); + TraceModule module = getNearestModuleContaining(address); + if (module != null) { + return module.getName(); } - return view.getDomainFile().getName() + " (" + block.getName() + ")"; + TraceMemoryRegion region = getRegionContaining(address); + if (region != null) { + return region.getName(); + } + return "(unknown)"; } protected void updateLocationLabel() { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java index db7431856f..0eaa1a2d2d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DefaultMemoryRecorder.java @@ -25,7 +25,6 @@ import ghidra.async.AsyncUtils; import ghidra.async.TypeSpec; import ghidra.dbg.target.TargetMemory; import ghidra.dbg.target.TargetMemoryRegion; -import ghidra.dbg.util.PathUtils; import ghidra.program.model.address.*; import ghidra.trace.model.Trace; import ghidra.trace.model.memory.*; @@ -101,7 +100,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { TargetMemory mem = region.getMemory(); recorder.getProcessMemory().addRegion(region, mem); //recorder.objectManager.addMemory(mem); - String path = PathUtils.toString(region.getPath()); + String path = region.getJoinedPath("."); long snap = recorder.getSnap(); recorder.parTx.execute("Memory region " + path + " added", () -> { try { @@ -114,7 +113,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { traceRegion = memoryManager.addRegion(path, Range.atLeast(snap), recorder.getMemoryMapper().targetToTrace(region.getRange()), getTraceFlags(region)); - traceRegion.setName(region.getName()); + traceRegion.setName(region.getDisplay()); } catch (TraceOverlappedRegionException e) { Msg.error(this, "Failed to create region due to overlap: " + e); @@ -128,7 +127,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { @Override public void removeProcessRegion(TargetMemoryRegion region) { // 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(); recorder.parTx.execute("Memory region " + path + " removed", () -> { try { @@ -148,7 +147,7 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { @Override public TraceMemoryRegion getTraceMemoryRegion(TargetMemoryRegion region) { - String path = PathUtils.toString(region.getPath()); + String path = region.getJoinedPath("."); return memoryManager.getLiveRegionByPath(recorder.getSnap(), path); } @@ -167,4 +166,16 @@ public class DefaultMemoryRecorder implements ManagedMemoryRecorder { 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); + } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/TraceObjectManager.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/TraceObjectManager.java index a7c0dce570..b891d1c456 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/TraceObjectManager.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/TraceObjectManager.java @@ -117,6 +117,7 @@ public class TraceObjectManager { putAttributesHandler(TargetBreakpointSpec.class, this::attributesChangedBreakpointSpec); putAttributesHandler(TargetBreakpointLocation.class, this::attributesChangedBreakpointLocation); + putAttributesHandler(TargetMemoryRegion.class, this::attributesChangedMemoryRegion); putAttributesHandler(TargetRegister.class, this::attributesChangedRegister); putAttributesHandler(TargetStackFrame.class, this::attributesChangedStackFrame); putAttributesHandler(TargetThread.class, this::attributesChangedThread); @@ -494,6 +495,12 @@ public class TraceObjectManager { } } + public void attributesChangedMemoryRegion(TargetObject region, Map added) { + if (added.containsKey(TargetObject.DISPLAY_ATTRIBUTE_NAME)) { + recorder.memoryRecorder.regionChanged((TargetMemoryRegion) region, region.getDisplay()); + } + } + public void attributesChangedRegister(TargetObject parent, Map added) { if (added.containsKey(TargetRegister.CONTAINER_ATTRIBUTE_NAME)) { TargetRegister register = (TargetRegister) parent;