diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetModuleContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetModuleContainerImpl.java index 0ef65f415f..b211bd07c5 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetModuleContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetModuleContainerImpl.java @@ -75,11 +75,7 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl //modulesByName.remove(name); module = getTargetModule(name); } - TargetThread eventThread = - (TargetThread) getModel().getModelObject(getManager().getEventThread()); changeElements(List.of(), List.of(module), Map.of(), "Loaded"); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED, - "Library " + name + " loaded", List.of(module)); } @Override @@ -87,10 +83,6 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl public void libraryUnloaded(String name) { DbgModelTargetModule targetModule = getTargetModule(name); if (targetModule != null) { - TargetThread eventThread = - (TargetThread) getModel().getModelObject(getManager().getEventThread()); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED, - "Library " + name + " unloaded", List.of(targetModule)); DbgModelImpl impl = (DbgModelImpl) model; impl.deleteModelObject(targetModule.getDbgModule()); } diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetRootImpl.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetRootImpl.java index 71d7bbc43e..6501ded7d6 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetRootImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetRootImpl.java @@ -181,9 +181,8 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot public void objectSelected(Object object) { List objPath = findObject(object); - model.fetchModelObject(objPath, RefreshBehavior.REFRESH_WHEN_ABSENT).thenAccept(obj -> - update(obj) - ); + model.fetchModelObject(objPath, RefreshBehavior.REFRESH_WHEN_ABSENT) + .thenAccept(obj -> update(obj)); } @Override @@ -241,11 +240,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot if (mod == null) { return; } - getObject(getManager().getEventThread()).thenAccept(t -> { - TargetThread eventThread = (TargetThread) t; - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED, - "Library " + info.getModuleName() + " loaded", List.of(mod)); - }); getObject(getManager().getEventProcess()).thenAccept(p -> { DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p; DbgModel2TargetObjectImpl memory = @@ -262,11 +256,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot if (mod == null) { return; } - getObject(getManager().getEventThread()).thenAccept(t -> { - TargetThread eventThread = (TargetThread) t; - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED, - "Library " + info.getModuleName() + " unloaded", List.of(mod)); - }); getObject(getManager().getEventProcess()).thenAccept(p -> { DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p; DbgModel2TargetObjectImpl memory = @@ -604,7 +593,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot stateful.fetchAttributes(RefreshBehavior.REFRESH_ALWAYS); } } - + private TargetEventType getEventType(DbgState state, DbgCause cause, DbgReason reason) { switch (state) { case RUNNING: diff --git a/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetKernelModuleContainerImpl.java b/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetKernelModuleContainerImpl.java index 876d225ac0..feebbad837 100644 --- a/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetKernelModuleContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetKernelModuleContainerImpl.java @@ -69,12 +69,7 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO Msg.error(this, "Module " + info.getModuleName(index) + " not found!"); return; } - FridaThread thread = getManager().getCurrentThread(); - TargetThread eventThread = - (TargetThread) getModel().getModelObject(thread); changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded"); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED, - "Library " + info.getModuleName(index) + " loaded", List.of(targetModule)); } @Override @@ -91,11 +86,6 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO FridaCause cause) { FridaModelTargetModule targetModule = getTargetModule(info.getModule(index)); if (targetModule != null) { - FridaThread thread = getManager().getCurrentThread(); - TargetThread eventThread = - (TargetThread) getModel().getModelObject(thread); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED, - "Library " + info.getModuleName(index) + " unloaded", List.of(targetModule)); FridaModelImpl impl = (FridaModelImpl) model; impl.deleteModelObject(targetModule.getModule()); } diff --git a/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetModuleContainerImpl.java b/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetModuleContainerImpl.java index 4e4a0131a2..134f4d3430 100644 --- a/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetModuleContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-frida/src/main/java/agent/frida/model/impl/FridaModelTargetModuleContainerImpl.java @@ -87,12 +87,7 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI Msg.error(this, "Module " + info.getModuleName(index) + " not found!"); return; } - FridaThread thread = getManager().getCurrentThread(); - TargetThread eventThread = - (TargetThread) getModel().getModelObject(thread); changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded"); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED, - "Library " + info.getModuleName(index) + " loaded", List.of(targetModule)); } @Override @@ -109,11 +104,6 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI FridaCause cause) { FridaModelTargetModule targetModule = getTargetModule(info.getModule(index)); if (targetModule != null) { - FridaThread thread = getManager().getCurrentThread(); - TargetThread eventThread = - (TargetThread) getModel().getModelObject(thread); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED, - "Library " + info.getModuleName(index) + " unloaded", List.of(targetModule)); FridaModelImpl impl = (FridaModelImpl) model; impl.deleteModelObject(targetModule.getModule()); } diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java index 7a726c2901..d6bf7f2231 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetInferiorContainer.java @@ -107,17 +107,12 @@ public class GdbModelTargetInferiorContainer @Override public void libraryLoaded(GdbInferior inf, String name, GdbCause cause) { GdbModelTargetInferior inferior = getTargetInferior(inf); - GdbModelTargetModule module = inferior.modules.libraryLoaded(name); - broadcast().event(parent, null, TargetEventType.MODULE_LOADED, - "Library " + name + " loaded", List.of(module)); + inferior.modules.libraryLoaded(name); } @Override public void libraryUnloaded(GdbInferior inf, String name, GdbCause cause) { GdbModelTargetInferior inferior = getTargetInferior(inf); - GdbModelTargetModule module = inferior.modules.getTargetModuleIfPresent(name); - broadcast().event(parent, null, TargetEventType.MODULE_UNLOADED, - "Library " + name + " unloaded", List.of(module)); inferior.modules.libraryUnloaded(name); } diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetModuleContainer.java b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetModuleContainer.java index 3ea6490b0b..a438729a6a 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetModuleContainer.java +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/java/agent/gdb/model/impl/GdbModelTargetModuleContainer.java @@ -53,7 +53,11 @@ public class GdbModelTargetModuleContainer @Internal public GdbModelTargetModule libraryLoaded(String name) { - GdbModule mod = Objects.requireNonNull(inferior.getKnownModules().get(name)); + GdbModule mod = inferior.getKnownModules().get(name); + if (mod == null) { + // We'll catch it the next time around. + return null; + } GdbModelTargetModule module = getTargetModule(mod); changeElements(List.of(), List.of(module), "Loaded"); return module; diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/java/agent/lldb/model/impl/LldbModelTargetModuleContainerImpl.java b/Ghidra/Debug/Debugger-agent-lldb/src/main/java/agent/lldb/model/impl/LldbModelTargetModuleContainerImpl.java index ca25ceebbd..93daeb3df0 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/java/agent/lldb/model/impl/LldbModelTargetModuleContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/java/agent/lldb/model/impl/LldbModelTargetModuleContainerImpl.java @@ -69,12 +69,7 @@ public class LldbModelTargetModuleContainerImpl extends LldbModelTargetObjectImp System.err.println("Module " + info.getModuleName(index) + " not found!"); return; } - SBThread thread = getManager().getEventThread(); - TargetThread eventThread = - (TargetThread) getModel().getModelObject(thread); changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded"); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED, - "Library " + info.getModuleName(index) + " loaded", List.of(targetModule)); } @Override @@ -82,11 +77,6 @@ public class LldbModelTargetModuleContainerImpl extends LldbModelTargetObjectImp public void libraryUnloaded(DebugModuleInfo info, int index) { LldbModelTargetModule targetModule = getTargetModule(info.getModule(index)); if (targetModule != null) { - SBThread thread = getManager().getEventThread(); - TargetThread eventThread = - (TargetThread) getModel().getModelObject(thread); - broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED, - "Library " + info.getModuleName(index) + " unloaded", List.of(targetModule)); LldbModelImpl impl = (LldbModelImpl) model; impl.deleteModelObject(targetModule.getModule()); } diff --git a/Ghidra/Debug/Debugger-gadp/src/main/java/ghidra/dbg/gadp/client/GadpValueUtils.java b/Ghidra/Debug/Debugger-gadp/src/main/java/ghidra/dbg/gadp/client/GadpValueUtils.java index 5a5001f759..22711e823e 100644 --- a/Ghidra/Debug/Debugger-gadp/src/main/java/ghidra/dbg/gadp/client/GadpValueUtils.java +++ b/Ghidra/Debug/Debugger-gadp/src/main/java/ghidra/dbg/gadp/client/GadpValueUtils.java @@ -234,10 +234,6 @@ public enum GadpValueUtils { return TargetEventType.THREAD_CREATED; case EV_THREAD_EXITED: return TargetEventType.THREAD_EXITED; - case EV_MODULE_LOADED: - return TargetEventType.MODULE_LOADED; - case EV_MODULE_UNLOADED: - return TargetEventType.MODULE_UNLOADED; case EV_BREAKPOINT_HIT: return TargetEventType.BREAKPOINT_HIT; case EV_STEP_COMPLETED: @@ -264,10 +260,6 @@ public enum GadpValueUtils { return Gadp.TargetEventType.EV_THREAD_CREATED; case THREAD_EXITED: return Gadp.TargetEventType.EV_THREAD_EXITED; - case MODULE_LOADED: - return Gadp.TargetEventType.EV_MODULE_LOADED; - case MODULE_UNLOADED: - return Gadp.TargetEventType.EV_MODULE_UNLOADED; case BREAKPOINT_HIT: return Gadp.TargetEventType.EV_BREAKPOINT_HIT; case STEP_COMPLETED: diff --git a/Ghidra/Debug/Debugger-gadp/src/main/proto/gadp.proto b/Ghidra/Debug/Debugger-gadp/src/main/proto/gadp.proto index 920ec60e1d..f6d4b0f03c 100644 --- a/Ghidra/Debug/Debugger-gadp/src/main/proto/gadp.proto +++ b/Ghidra/Debug/Debugger-gadp/src/main/proto/gadp.proto @@ -484,8 +484,6 @@ enum TargetEventType { EV_PROCESS_EXITED = 3; EV_THREAD_CREATED = 4; EV_THREAD_EXITED = 5; - EV_MODULE_LOADED = 6; - EV_MODULE_UNLOADED = 7; EV_BREAKPOINT_HIT = 8; EV_STEP_COMPLETED = 9; EV_EXCEPTION = 10; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/AutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/AutoReadMemorySpec.java index 1cdcf3e5d4..331894795a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/AutoReadMemorySpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/AutoReadMemorySpec.java @@ -15,8 +15,7 @@ */ package ghidra.app.plugin.core.debug.gui.action; -import java.util.Map; -import java.util.TreeMap; +import java.util.*; import java.util.concurrent.CompletableFuture; import javax.swing.Icon; @@ -34,7 +33,7 @@ import ghidra.util.classfinder.ExtensionPoint; public interface AutoReadMemorySpec extends ExtensionPoint { class Private { - private final Map specsByName = new TreeMap<>(); + private final Map specsByName = new HashMap<>(); private final ChangeListener classListener = this::classesChanged; private Private() { @@ -72,7 +71,7 @@ public interface AutoReadMemorySpec extends ExtensionPoint { static Map allSpecs() { synchronized (PRIVATE) { - return Map.copyOf(PRIVATE.specsByName); + return new TreeMap<>(PRIVATE.specsByName); } } 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 68ab43afd7..d26ddd9fb1 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 @@ -17,8 +17,8 @@ package ghidra.app.plugin.core.debug.gui.listing; import static ghidra.app.plugin.core.debug.gui.DebuggerResources.ICON_REGISTER_MARKER; +import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Dimension; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.invoke.MethodHandles; @@ -26,8 +26,8 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.swing.Box; import javax.swing.JLabel; +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -336,11 +336,9 @@ public class DebuggerListingProvider extends CodeViewerProvider { addDisplayListener(readsMemTrait.getDisplayListener()); - Box northPanel = Box.createHorizontalBox(); + JPanel northPanel = new JPanel(new BorderLayout()); northPanel.add(locationLabel); - locationLabel.setMinimumSize(new Dimension(0, 0)); - northPanel.add(Box.createGlue()); - northPanel.add(trackingLabel); + northPanel.add(trackingLabel, BorderLayout.EAST); this.setNorthComponent(northPanel); if (isConnected) { setTitle(DebuggerResources.TITLE_PROVIDER_LISTING); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java index afcc606f25..46d1014850 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java @@ -16,14 +16,14 @@ package ghidra.app.plugin.core.debug.gui.memory; import java.awt.BorderLayout; -import java.awt.Dimension; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.invoke.MethodHandles; import java.math.BigInteger; import java.util.*; -import javax.swing.*; +import javax.swing.JLabel; +import javax.swing.JPanel; import org.apache.commons.lang3.StringUtils; @@ -207,11 +207,9 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi createActions(); addDisplayListener(readsMemTrait.getDisplayListener()); - Box northPanel = Box.createHorizontalBox(); + JPanel northPanel = new JPanel(new BorderLayout()); northPanel.add(locationLabel); - locationLabel.setMinimumSize(new Dimension(0, 0)); - northPanel.add(Box.createGlue()); - northPanel.add(trackingLabel); + northPanel.add(trackingLabel, BorderLayout.EAST); decorationComponent.add(northPanel, BorderLayout.NORTH); goToTrait.goToCoordinates(current); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerLegacyModulesPanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerLegacyModulesPanel.java index d9ade9941d..789241ffd0 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerLegacyModulesPanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerLegacyModulesPanel.java @@ -93,6 +93,7 @@ public class DebuggerLegacyModulesPanel extends JPanel { MAX("Max Address", Address.class, ModuleRow::getMaxAddress), SHORT_NAME("Name", String.class, ModuleRow::getShortName), NAME("Module Name", String.class, ModuleRow::getName, ModuleRow::setName), + MAPPING("Mapping", String.class, ModuleRow::getMapping), LIFESPAN("Lifespan", Lifespan.class, ModuleRow::getLifespan), LENGTH("Length", Long.class, ModuleRow::getLength); @@ -144,9 +145,9 @@ public class DebuggerLegacyModulesPanel extends JPanel { extends DebouncedRowWrappedEnumeratedColumnTableModel< // ModuleTableColumns, ObjectKey, ModuleRow, TraceModule> { - public ModuleTableModel(PluginTool tool) { + public ModuleTableModel(PluginTool tool, DebuggerModulesProvider provider) { super(tool, "Modules", ModuleTableColumns.class, TraceModule::getObjectKey, - ModuleRow::new, ModuleRow::getModule); + mod -> new ModuleRow(provider, mod), ModuleRow::getModule); } @Override @@ -197,7 +198,7 @@ public class DebuggerLegacyModulesPanel extends JPanel { super(new BorderLayout()); this.provider = provider; - moduleTableModel = new ModuleTableModel(provider.getTool()); + moduleTableModel = new ModuleTableModel(provider.getTool(), provider); moduleTable = new GhidraTable(moduleTableModel); moduleTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); add(new JScrollPane(moduleTable)); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java index 1a846af5d2..8fd6186556 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesPanel.java @@ -21,8 +21,10 @@ import javax.swing.event.ListSelectionEvent; import docking.widgets.table.TableColumnDescriptor; import ghidra.app.plugin.core.debug.gui.model.*; +import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueAttribute; import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow; import ghidra.app.plugin.core.debug.gui.model.columns.*; +import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils; import ghidra.dbg.target.TargetModule; import ghidra.dbg.target.TargetProcess; import ghidra.dbg.target.schema.TargetObjectSchema; @@ -81,6 +83,31 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel attr = + rowObject.getAttribute(TargetModule.RANGE_ATTRIBUTE_NAME, AddressRange.class); + if (attr == null) { + return ""; + } + AddressRange range = attr.getValue(); + + // TODO: Cache this? Would flush on: + // 1. Mapping changes + // 2. Range/Life changes to this module + // 3. Snapshot navigation + return DebuggerStaticMappingUtils.computeMappedFiles(data, rowObject.currentSnap(), + range); + } + } + private static class ModulePathColumn extends TraceValueKeyColumn { @Override public String getColumnName() { @@ -117,6 +144,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel { - TraceModule traceModule = recorder.getTraceModule(mod); - if (traceModule == null) { - return; - } - try { - traceModule.setLoadedSnap(snap); - } - catch (DuplicateNameException e) { - Msg.error(this, "Could not set module loaded snap", e); - } - }, modPath); - } } @AttributeCallback(TargetExecutionStateful.STATE_ATTRIBUTE_NAME) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/launch/AbstractDebuggerProgramLaunchOffer.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/launch/AbstractDebuggerProgramLaunchOffer.java index 949987d2ba..b6a9a796a3 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/launch/AbstractDebuggerProgramLaunchOffer.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/launch/AbstractDebuggerProgramLaunchOffer.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.debug.service.model.launch; -import static ghidra.async.AsyncUtils.*; +import static ghidra.async.AsyncUtils.loop; import java.io.IOException; import java.util.*; @@ -275,7 +275,8 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg for (Entry> entry : params.entrySet()) { map.put(entry.getKey(), entry.getValue().defaultValue); } - map.put(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, program.getExecutablePath()); + map.put(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, + TargetCmdLineLauncher.quoteImagePathIfSpaces(program.getExecutablePath())); return map; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java index ed1080e2ca..33079cb094 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/modules/DebuggerStaticMappingUtils.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.debug.service.modules; import java.net.URL; import java.util.*; +import java.util.stream.Collectors; import ghidra.app.plugin.core.debug.utils.ProgramURLUtils; import ghidra.app.services.MapEntry; @@ -238,4 +239,66 @@ public enum DebuggerStaticMappingUtils { } return new AddressRangeImpl(space.getAddress(min), space.getAddress(max)); } + + /** + * Parse the final file name from the given URL. + * + *

+ * This is used when listing the "image" name for mappings, since displaying a full URL would + * probably clutter the table. This generally matches the "program name," but in certain cases + * may not. + * + * @param staticProgramURL the URL of the static program image + * @return the piece after the final "/" + */ + public static String getImageName(URL staticProgramURL) { + String[] parts = staticProgramURL.toExternalForm().split("/"); + return parts[parts.length - 1]; + } + + /** + * Compute a string suitable for displaying the mapped module names for a given range + * + *

+ * Ideally, the entire range is covered by a single mapping entry. In that case, the "image + * name" (see {@link #getImageName(URL)}) for that one mapping is returned. If a single mapping + * is found, but it only partially covers the given range, an asterisk is appended. If no + * mappings are found, the empty string is returned. If multiple mappings are found, they are + * each listed alphabetically. No asterisk is displayed in the case of multiple images, since + * it's implied that none cover the entire range. + * + * @param trace the trace whose mappings to query + * @param snap the relevant snapshot + * @param range the address range to consider + * @return the names of any mapped images + */ + public static String computeMappedFiles(Trace trace, long snap, AddressRange range) { + List mappings = List.copyOf( + trace.getStaticMappingManager().findAllOverlapping(range, Lifespan.at(snap))); + if (mappings.isEmpty()) { + return ""; + } + if (mappings.size() == 1) { + TraceStaticMapping single = mappings.get(0); + AddressRange mappedRange = single.getTraceAddressRange(); + if (mappedRange.contains(range.getMinAddress()) && + mappedRange.contains(range.getMaxAddress())) { + return getImageName(single.getStaticProgramURL()); + } + return getImageName(single.getStaticProgramURL()) + "*"; + } + /** + * Its possible multiple mappings to the same image are at play. This would happen if the + * user is mapping by sections instead of modules. + */ + List names = mappings.stream() + .map(m -> getImageName(m.getStaticProgramURL())) + .sorted() + .distinct() + .toList(); + if (names.size() == 1) { + return names.get(0) + "*"; + } + return names.stream().collect(Collectors.joining(",")); + } } diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetEventScope.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetEventScope.java index f930a2a6c1..a599a5599b 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetEventScope.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetEventScope.java @@ -64,17 +64,6 @@ public interface TargetEventScope extends TargetObject { * A target thread in this session has exited */ THREAD_EXITED(false), - /** - * A new module has been loaded by this session - * - *

- * The new module must be passed as a parameter. - */ - MODULE_LOADED(false), - /** - * A module has been unloaded by this session - */ - MODULE_UNLOADED(false), /** * The session has stopped, because one if its targets was trapped by a breakpoint * diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetLauncher.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetLauncher.java index 262811ad0a..9f08318f9d 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetLauncher.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetLauncher.java @@ -60,6 +60,25 @@ public interface TargetLauncher extends TargetObject { */ TargetParameterMap PARAMETERS = TargetMethod.makeParameters(PARAMETER_CMDLINE_ARGS); + /** + * Check if the given image path contains spaces, and surround it in double quotes + * ({@code "}) if necessary. + * + *

+ * Without the quotes the launcher will likely confuse the spaces for separating arguments. + * When constructing the command-line to launch a program, this method must be used, even if + * the image is the only "argument." + * + * @param imagePath the path to the image on the target platform. + * @return the path, possibly surrounded in quotes. + */ + static String quoteImagePathIfSpaces(String imagePath) { + if (imagePath.contains(" ")) { + return '"' + imagePath + '"'; + } + return imagePath; + } + @Override default public TargetParameterMap getParameters() { return PARAMETERS; diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/schema/TargetObjectSchema.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/schema/TargetObjectSchema.java index 1bb65a4cf2..52b26f9eca 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/schema/TargetObjectSchema.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/schema/TargetObjectSchema.java @@ -907,7 +907,9 @@ public interface TargetObjectSchema { return false; } AttributeSchema schema = getAttributeSchema(key); - if (schema == AttributeSchema.DEFAULT_ANY || schema == AttributeSchema.DEFAULT_OBJECT) { + if (schema == AttributeSchema.DEFAULT_ANY || + schema == AttributeSchema.DEFAULT_OBJECT || + schema == AttributeSchema.DEFAULT_VOID) { // FIXME: Remove this hack once we stop depending on this prefix return key.startsWith(TargetObject.PREFIX_INVISIBLE); } diff --git a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/testutil/EventValidator.java b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/testutil/EventValidator.java index 33d3559173..423151359f 100644 --- a/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/testutil/EventValidator.java +++ b/Ghidra/Debug/Framework-Debugging/src/test/java/ghidra/dbg/testutil/EventValidator.java @@ -203,12 +203,6 @@ public class EventValidator case THREAD_EXITED: validateDestroyed(type.name(), TargetThread.class, threads, parameters); break; - case MODULE_LOADED: - validateCreated(type.name(), TargetModule.class, modules, parameters); - break; - case MODULE_UNLOADED: - validateDestroyed(type.name(), TargetModule.class, modules, parameters); - break; case STOPPED: case RUNNING: case BREAKPOINT_HIT: diff --git a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java index dc47257532..e46af9b1d2 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/test/java/ghidra/trace/database/target/DBTraceObjectManagerTest.java @@ -46,6 +46,7 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT + @@ -1063,4 +1064,33 @@ public class DBTraceObjectManagerTest extends AbstractGhidraHeadlessIntegrationT assertFalse(split.isDeleted()); // Other values not affected } } + + @Test + public void testAttributeDefaultVisibility() { + try (Transaction tx = b.startTransaction()) { + TraceObjectValue rootVal = + manager.createRootObject(ctx.getSchema(new SchemaName("Session"))); + root = rootVal.getChild(); + + TraceObject object = manager.createObject(TraceObjectKeyPath.parse("OutsideSchema")); + object.insert(Lifespan.ALL, ConflictResolution.DENY); + assertFalse(object.getCanonicalParent(0).isHidden()); + + TraceObject elemOutside = + manager.createObject(TraceObjectKeyPath.parse("OutsideSchema[0]")); + elemOutside.insert(Lifespan.ALL, ConflictResolution.DENY); + assertFalse(elemOutside.getCanonicalParent(0).isHidden()); + + TraceObject attrOutside = + manager.createObject(TraceObjectKeyPath.parse("OutsideSchema.Attr")); + attrOutside.insert(Lifespan.ALL, ConflictResolution.DENY); + assertFalse(attrOutside.getCanonicalParent(0).isHidden()); + + // TODO: This underscore convention is deprecated, but still in use + TraceObject hiddenOutside = + manager.createObject(TraceObjectKeyPath.parse("OutsideSchema._Attr")); + hiddenOutside.insert(Lifespan.ALL, ConflictResolution.DENY); + assertTrue(hiddenOutside.getCanonicalParent(0).isHidden()); + } + } } diff --git a/Ghidra/Framework/Emulation/src/main/java/ghidra/pcode/exec/SleighUtils.java b/Ghidra/Framework/Emulation/src/main/java/ghidra/pcode/exec/SleighUtils.java index b0c0251289..aa8dbe11bc 100644 --- a/Ghidra/Framework/Emulation/src/main/java/ghidra/pcode/exec/SleighUtils.java +++ b/Ghidra/Framework/Emulation/src/main/java/ghidra/pcode/exec/SleighUtils.java @@ -308,9 +308,12 @@ public enum SleighUtils { match(tree, SleighParser.OP_DEREFERENCE, onSize, onOffset); return; default: - throw new AssertionError( - "OP_DEREFERENCE with 2 children where child[0] is " + - SleighParser.tokenNames[child0.getType()]); + matchTree(tree, SleighParser.OP_DEREFERENCE, children -> { + throw new AssertionError( + "OP_DEREFERENCE with 2 children where child[0] is " + + SleighParser.tokenNames[child0.getType()]); + }); + return; } case 1: match(tree, SleighParser.OP_DEREFERENCE, onOffset);