diff --git a/Ghidra/Debug/Debugger/data/ExtensionPoint.manifest b/Ghidra/Debug/Debugger/data/ExtensionPoint.manifest index 0275af0d94..7c0a051073 100644 --- a/Ghidra/Debug/Debugger/data/ExtensionPoint.manifest +++ b/Ghidra/Debug/Debugger/data/ExtensionPoint.manifest @@ -1,5 +1,6 @@ +AutoReadMemorySpec DebuggerBot DebuggerMappingOpinion DebuggerModelFactory DisassemblyInject - +LocationTrackingSpec 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 new file mode 100644 index 0000000000..1cdcf3e5d4 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/AutoReadMemorySpec.java @@ -0,0 +1,99 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.CompletableFuture; + +import javax.swing.Icon; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils; +import ghidra.framework.options.SaveState; +import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.AddressSetView; +import ghidra.util.classfinder.ClassSearcher; +import ghidra.util.classfinder.ExtensionPoint; + +public interface AutoReadMemorySpec extends ExtensionPoint { + class Private { + private final Map specsByName = new TreeMap<>(); + private final ChangeListener classListener = this::classesChanged; + + private Private() { + ClassSearcher.addChangeListener(classListener); + } + + private synchronized void classesChanged(ChangeEvent evt) { + MiscellaneousUtils.collectUniqueInstances(AutoReadMemorySpec.class, specsByName, + AutoReadMemorySpec::getConfigName); + } + } + + Private PRIVATE = new Private(); + + public static class AutoReadMemorySpecConfigFieldCodec + implements ConfigFieldCodec { + @Override + public AutoReadMemorySpec read(SaveState state, String name, + AutoReadMemorySpec current) { + String specName = state.getString(name, null); + return fromConfigName(specName); + } + + @Override + public void write(SaveState state, String name, AutoReadMemorySpec value) { + state.putString(name, value.getConfigName()); + } + } + + static AutoReadMemorySpec fromConfigName(String name) { + synchronized (PRIVATE) { + return PRIVATE.specsByName.get(name); + } + } + + static Map allSpecs() { + synchronized (PRIVATE) { + return Map.copyOf(PRIVATE.specsByName); + } + } + + String getConfigName(); + + String getMenuName(); + + Icon getMenuIcon(); + + /** + * Perform the automatic read, if applicable + * + *

+ * Note, the implementation should perform all the error handling. The returned future is for + * follow-up purposes only, and should always complete normally. + * + * @param tool the tool containing the provider + * @param coordinates the provider's current coordinates + * @param visible the provider's visible addresses + * @return a future that completes when the memory has been read + */ + CompletableFuture readMemory(PluginTool tool, DebuggerCoordinates coordinates, + AddressSetView visible); +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerAutoReadMemoryAction.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerAutoReadMemoryAction.java new file mode 100644 index 0000000000..bb23cef13f --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerAutoReadMemoryAction.java @@ -0,0 +1,33 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import docking.action.builder.MultiStateActionBuilder; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.AutoReadMemoryAction; +import ghidra.framework.plugintool.Plugin; + +public interface DebuggerAutoReadMemoryAction extends AutoReadMemoryAction { + // TODO: Update the action when new specs enter the class path? + static MultiStateActionBuilder builder(Plugin owner) { + MultiStateActionBuilder builder = AutoReadMemoryAction.builder(owner); + builder.toolBarGroup(NAME); + builder.performActionOnButtonClick(true); + for (AutoReadMemorySpec spec : AutoReadMemorySpec.allSpecs().values()) { + builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec); + } + return builder; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationAction.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationAction.java new file mode 100644 index 0000000000..988c0dc29f --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/DebuggerTrackLocationAction.java @@ -0,0 +1,33 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import docking.action.builder.MultiStateActionBuilder; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; +import ghidra.framework.plugintool.Plugin; + +public interface DebuggerTrackLocationAction extends TrackLocationAction { + // TODO: Update the action when new specs enter the class path? + static MultiStateActionBuilder builder(Plugin owner) { + MultiStateActionBuilder builder = TrackLocationAction.builder(owner); + builder.toolBarGroup(owner.getName()); + builder.performActionOnButtonClick(true); + for (LocationTrackingSpec spec : LocationTrackingSpec.allSpecs().values()) { + builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec); + } + return builder; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/LocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/LocationTrackingSpec.java new file mode 100644 index 0000000000..b23a7b40ea --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/LocationTrackingSpec.java @@ -0,0 +1,155 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import java.util.Map; +import java.util.TreeMap; + +import javax.swing.Icon; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils; +import ghidra.framework.options.SaveState; +import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.Address; +import ghidra.trace.model.TraceAddressSnapRange; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.util.TraceAddressSpace; +import ghidra.util.classfinder.ClassSearcher; +import ghidra.util.classfinder.ExtensionPoint; + +/** + * A "specification" for automatic navigation of the dynamic listing + * + *

+ * TODO: Some of these should be configurable, and permit multiple instances, so that common + * configurations can be saved. The most obvious use case would be a SLEIGH expression. A user may + * want 3 different common expressions readily available in the drop-down list. + */ +public interface LocationTrackingSpec extends ExtensionPoint { + class Private { + private final Map specsByName = new TreeMap<>(); + private final ChangeListener classListener = this::classesChanged; + + private Private() { + ClassSearcher.addChangeListener(classListener); + } + + private synchronized void classesChanged(ChangeEvent evt) { + MiscellaneousUtils.collectUniqueInstances(LocationTrackingSpec.class, specsByName, + LocationTrackingSpec::getConfigName); + } + } + + Private PRIVATE = new Private(); + + public static class TrackingSpecConfigFieldCodec + implements ConfigFieldCodec { + @Override + public LocationTrackingSpec read(SaveState state, String name, + LocationTrackingSpec current) { + String specName = state.getString(name, null); + return fromConfigName(specName); + } + + @Override + public void write(SaveState state, String name, LocationTrackingSpec value) { + state.putString(name, value.getConfigName()); + } + } + + static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range, + DebuggerCoordinates current) { + if (space == null || space.getThread() != current.getThread()) { + return false; + } + if (space.getFrameLevel() != current.getFrame()) { + return false; + } + if (!range.getLifespan().contains(current.getSnap())) { + return false; + } + return true; + } + + static LocationTrackingSpec fromConfigName(String name) { + synchronized (PRIVATE) { + return PRIVATE.specsByName.get(name); + } + } + + static Map allSpecs() { + synchronized (PRIVATE) { + return Map.copyOf(PRIVATE.specsByName); + } + } + + String getConfigName(); + + String getMenuName(); + + Icon getMenuIcon(); + + /** + * Compute a title prefix to indicate this tracking specification + * + * @param thread the provider's current thread + * @return a prefix, or {@code null} to use a default + */ + String computeTitle(DebuggerCoordinates coordinates); + + /** + * Compute the trace address to "goto" + * + *

+ * If the coordinates indicate emulation, i.e., the schedule is non-empty, the trace manager + * will already have performed the emulation and stored the results in a "scratch" snap. In + * general, the location should be computed using that snap (@code emuSnap) rather than the one + * indicated in {@code coordinates}. + * + * @param tool the tool containing the provider + * @param coordinates the trace, thread, snap, etc., of the tool + * @param emuSnap the "scratch" snap storing emulated state + * @return the address to navigate to + */ + Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, long emuSnap); + + // TODO: Is there a way to generalize these so that other dependencies need not + // have their own bespoke methods? + + /** + * Check if the address should be recomputed given the indicated register value change + * + * @param space the space (address space, thread, frame) where the change occurred + * @param range the range (time and space) where the change occurred + * @param coordinates the provider's current coordinates + * @return true if re-computation and "goto" is warranted + */ + boolean affectedByRegisterChange(TraceAddressSpace space, + TraceAddressSnapRange range, DebuggerCoordinates coordinates); + + /** + * Check if the address should be recomputed given the indicated stack change + * + * @param stack the stack that changed (usually it's PC / return offset) + * @param coordinates the provider's current coordinates + * @return true if re-computation and "goto" is warranted + */ + boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates); +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneAutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneAutoReadMemorySpec.java new file mode 100644 index 0000000000..65ef9a8503 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneAutoReadMemorySpec.java @@ -0,0 +1,51 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import java.util.concurrent.CompletableFuture; + +import javax.swing.Icon; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.AutoReadMemoryAction; +import ghidra.async.AsyncUtils; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.AddressSetView; + +public class NoneAutoReadMemorySpec implements AutoReadMemorySpec { + public static final String CONFIG_NAME = "READ_NONE"; + + @Override + public String getConfigName() { + return CONFIG_NAME; + } + + @Override + public String getMenuName() { + return AutoReadMemoryAction.NAME_NONE; + } + + @Override + public Icon getMenuIcon() { + return AutoReadMemoryAction.ICON_NONE; + } + + @Override + public CompletableFuture readMemory(PluginTool tool, DebuggerCoordinates coordinates, + AddressSetView visible) { + return AsyncUtils.NIL; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java new file mode 100644 index 0000000000..f0df0c5f50 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/NoneLocationTrackingSpec.java @@ -0,0 +1,67 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import javax.swing.Icon; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.Address; +import ghidra.trace.model.TraceAddressSnapRange; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.util.TraceAddressSpace; + +public class NoneLocationTrackingSpec implements LocationTrackingSpec { + public static final String CONFIG_NAME = "TRACK_NONE"; + + @Override + public String getConfigName() { + return CONFIG_NAME; + } + + @Override + public String getMenuName() { + return TrackLocationAction.NAME_NONE; + } + + @Override + public Icon getMenuIcon() { + return TrackLocationAction.ICON_NONE; + } + + @Override + public String computeTitle(DebuggerCoordinates coordinates) { + return null; + } + + @Override + public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, + long emuSnap) { + return null; + } + + @Override + public boolean affectedByRegisterChange(TraceAddressSpace space, + TraceAddressSnapRange range, DebuggerCoordinates coordinates) { + return false; + } + + @Override + public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { + return false; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java new file mode 100644 index 0000000000..93b9ce0f71 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/PCLocationTrackingSpec.java @@ -0,0 +1,109 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import javax.swing.Icon; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; +import ghidra.program.model.lang.Register; +import ghidra.trace.model.Trace; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.stack.TraceStackFrame; +import ghidra.trace.model.thread.TraceThread; + +public class PCLocationTrackingSpec implements RegisterLocationTrackingSpec { + public static final String CONFIG_NAME = "TRACK_PC"; + + @Override + public String getConfigName() { + return CONFIG_NAME; + } + + @Override + public String getMenuName() { + return TrackLocationAction.NAME_PC; + } + + @Override + public Icon getMenuIcon() { + return TrackLocationAction.ICON_PC; + } + + @Override + public Register computeRegister(DebuggerCoordinates coordinates) { + Trace trace = coordinates.getTrace(); + if (trace == null) { + return null; + } + return trace.getBaseLanguage().getProgramCounter(); + } + + @Override + public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) { + return coordinates.getTrace().getBaseLanguage().getDefaultSpace(); + } + + public Address computePCViaStack(DebuggerCoordinates coordinates) { + Trace trace = coordinates.getTrace(); + TraceThread thread = coordinates.getThread(); + long snap = coordinates.getSnap(); + TraceStack stack = trace.getStackManager().getLatestStack(thread, snap); + if (stack == null) { + return null; + } + int level = coordinates.getFrame(); + TraceStackFrame frame = stack.getFrame(level, false); + if (frame == null) { + return null; + } + return frame.getProgramCounter(); + } + + @Override + public Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, + long emuSnap) { + if (coordinates.getTime().isSnapOnly()) { + Address pc = computePCViaStack(coordinates); + if (pc != null) { + return pc; + } + } + return RegisterLocationTrackingSpec.super.computeTraceAddress(tool, coordinates, emuSnap); + } + + // Note it does no good to override affectByRegChange. It must do what we'd avoid anyway. + @Override + public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { + if (stack.getThread() != coordinates.getThread()) { + return false; + } + if (!coordinates.getTime().isSnapOnly()) { + return false; + } + // TODO: Would be nice to have stack lifespan... + TraceStack curStack = coordinates.getTrace() + .getStackManager() + .getLatestStack(stack.getThread(), coordinates.getSnap()); + if (stack != curStack) { + return false; + } + return true; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java new file mode 100644 index 0000000000..11e31a1374 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/RegisterLocationTrackingSpec.java @@ -0,0 +1,97 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.*; +import ghidra.program.model.lang.Register; +import ghidra.program.model.lang.RegisterValue; +import ghidra.trace.model.Trace; +import ghidra.trace.model.TraceAddressSnapRange; +import ghidra.trace.model.memory.TraceMemoryRegisterSpace; +import ghidra.trace.model.memory.TraceMemoryState; +import ghidra.trace.model.stack.TraceStack; +import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.util.TraceAddressSpace; +import ghidra.trace.util.TraceRegisterUtils; + +// TODO: Use this, or allow arbitrary expressions +public interface RegisterLocationTrackingSpec extends LocationTrackingSpec { + Register computeRegister(DebuggerCoordinates coordinates); + + AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates); + + @Override + default String computeTitle(DebuggerCoordinates coordinates) { + Register register = computeRegister(coordinates); + if (register == null) { + return null; + } + return register.getName(); + } + + @Override + default Address computeTraceAddress(PluginTool tool, DebuggerCoordinates coordinates, + long emuSnap) { + Trace trace = coordinates.getTrace(); + TraceThread thread = coordinates.getThread(); + long snap = coordinates.getSnap(); + int frame = coordinates.getFrame(); + Register reg = computeRegister(coordinates); + if (reg == null) { + return null; + } + if (!thread.getLifespan().contains(snap)) { + return null; + } + TraceMemoryRegisterSpace regs = + trace.getMemoryManager().getMemoryRegisterSpace(thread, frame, false); + if (regs == null) { + return null; + } + RegisterValue value; + if (regs.getState(emuSnap, reg) == TraceMemoryState.KNOWN) { + value = regs.getValue(emuSnap, reg); + } + else { + value = regs.getValue(snap, reg); + } + if (value == null) { + return null; + } + // TODO: Action to select the address space + // Could use code unit, but that can't specify space, yet, either.... + return computeDefaultAddressSpace(coordinates) + .getAddress(value.getUnsignedValue().longValue()); + } + + @Override + default boolean affectedByRegisterChange(TraceAddressSpace space, + TraceAddressSnapRange range, DebuggerCoordinates coordinates) { + if (!LocationTrackingSpec.changeIsCurrent(space, range, coordinates)) { + return false; + } + Register register = computeRegister(coordinates); + AddressRange regRng = TraceRegisterUtils.rangeForRegister(register); + return range.getRange().intersects(regRng); + } + + @Override + default boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { + return false; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java new file mode 100644 index 0000000000..922db2fbf3 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/SPLocationTrackingSpec.java @@ -0,0 +1,57 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import javax.swing.Icon; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; +import ghidra.program.model.address.AddressSpace; +import ghidra.program.model.lang.Register; +import ghidra.trace.model.Trace; + +public class SPLocationTrackingSpec implements RegisterLocationTrackingSpec { + public static final String CONFIG_NAME = "TRACK_SP"; + + @Override + public String getConfigName() { + return CONFIG_NAME; + } + + @Override + public String getMenuName() { + return TrackLocationAction.NAME_SP; + } + + @Override + public Icon getMenuIcon() { + return TrackLocationAction.ICON_SP; + } + + @Override + public Register computeRegister(DebuggerCoordinates coordinates) { + Trace trace = coordinates.getTrace(); + if (trace == null) { + return null; + } + return trace.getBaseCompilerSpec().getStackPointer(); + } + + @Override + public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) { + return coordinates.getTrace().getBaseLanguage().getDefaultDataSpace(); + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java new file mode 100644 index 0000000000..48bededf40 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleAutoReadMemorySpec.java @@ -0,0 +1,72 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import java.util.concurrent.CompletableFuture; + +import javax.swing.Icon; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.AutoReadMemoryAction; +import ghidra.app.services.TraceRecorder; +import ghidra.async.AsyncUtils; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.AddressSet; +import ghidra.program.model.address.AddressSetView; +import ghidra.trace.model.memory.TraceMemoryManager; +import ghidra.trace.model.memory.TraceMemoryState; +import ghidra.util.task.TaskMonitor; + +public class VisibleAutoReadMemorySpec implements AutoReadMemorySpec { + public static final String CONFIG_NAME = "READ_VISIBLE"; + + @Override + public String getConfigName() { + return CONFIG_NAME; + } + + @Override + public String getMenuName() { + return AutoReadMemoryAction.NAME_VISIBLE; + } + + @Override + public Icon getMenuIcon() { + return AutoReadMemoryAction.ICON_VISIBLE; + } + + @Override + public CompletableFuture readMemory(PluginTool tool, DebuggerCoordinates coordinates, + AddressSetView visible) { + if (!coordinates.isAliveAndReadsPresent()) { + return AsyncUtils.NIL; + } + TraceRecorder recorder = coordinates.getRecorder(); + AddressSet visibleAccessible = + recorder.getAccessibleProcessMemory().intersect(visible); + TraceMemoryManager mm = coordinates.getTrace().getMemoryManager(); + AddressSetView alreadyKnown = + mm.getAddressesWithState(coordinates.getSnap(), visibleAccessible, + s -> s == TraceMemoryState.KNOWN); + AddressSet toRead = visibleAccessible.subtract(alreadyKnown); + + if (toRead.isEmpty()) { + return AsyncUtils.NIL; + } + + return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY); + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java new file mode 100644 index 0000000000..3db7d1a2e3 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/VisibleROOnceAutoReadMemorySpec.java @@ -0,0 +1,97 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ghidra.app.plugin.core.debug.gui.action; + +import java.util.Map.Entry; +import java.util.concurrent.CompletableFuture; + +import javax.swing.Icon; + +import com.google.common.collect.Range; + +import ghidra.app.plugin.core.debug.DebuggerCoordinates; +import ghidra.app.plugin.core.debug.gui.DebuggerResources.AutoReadMemoryAction; +import ghidra.app.services.TraceRecorder; +import ghidra.async.AsyncUtils; +import ghidra.framework.plugintool.PluginTool; +import ghidra.program.model.address.*; +import ghidra.trace.model.TraceAddressSnapRange; +import ghidra.trace.model.memory.*; +import ghidra.util.task.TaskMonitor; + +public class VisibleROOnceAutoReadMemorySpec implements AutoReadMemorySpec { + public static final String CONFIG_NAME = "READ_VIS_RO_ONCE"; + + @Override + public String getConfigName() { + return CONFIG_NAME; + } + + @Override + public String getMenuName() { + return AutoReadMemoryAction.NAME_VIS_RO_ONCE; + } + + @Override + public Icon getMenuIcon() { + return AutoReadMemoryAction.ICON_VIS_RO_ONCE; + } + + @Override + public CompletableFuture readMemory(PluginTool tool, DebuggerCoordinates coordinates, + AddressSetView visible) { + if (!coordinates.isAliveAndReadsPresent()) { + return AsyncUtils.NIL; + } + TraceRecorder recorder = coordinates.getRecorder(); + AddressSet visibleAccessible = + recorder.getAccessibleProcessMemory().intersect(visible); + TraceMemoryManager mm = coordinates.getTrace().getMemoryManager(); + AddressSetView alreadyKnown = + mm.getAddressesWithState(coordinates.getSnap(), visibleAccessible, + s -> s == TraceMemoryState.KNOWN); + AddressSet toRead = visibleAccessible.subtract(alreadyKnown); + + if (toRead.isEmpty()) { + return AsyncUtils.NIL; + } + + AddressSet everKnown = new AddressSet(); + for (AddressRange range : visible) { + for (Entry ent : mm + .getMostRecentStates(coordinates.getSnap(), range)) { + everKnown.add(ent.getKey().getRange()); + } + } + AddressSet readOnly = new AddressSet(); + for (AddressRange range : visible) { + for (TraceMemoryRegion region : mm + .getRegionsIntersecting(Range.singleton(coordinates.getSnap()), range)) { + if (region.isWrite()) { + continue; + } + readOnly.add(region.getRange()); + } + } + toRead.delete(everKnown.intersect(readOnly)); + + if (toRead.isEmpty()) { + return AsyncUtils.NIL; + } + + return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY); + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingAutoReadMemoryAction.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingAutoReadMemoryAction.java deleted file mode 100644 index 9632b5a487..0000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingAutoReadMemoryAction.java +++ /dev/null @@ -1,190 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.debug.gui.listing; - -import java.util.Map.Entry; -import java.util.concurrent.CompletableFuture; - -import com.google.common.collect.Range; - -import docking.action.builder.MultiStateActionBuilder; -import ghidra.app.plugin.core.debug.DebuggerCoordinates; -import ghidra.app.plugin.core.debug.gui.DebuggerResources.AutoReadMemoryAction; -import ghidra.app.services.TraceRecorder; -import ghidra.async.AsyncUtils; -import ghidra.framework.options.SaveState; -import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec; -import ghidra.framework.plugintool.Plugin; -import ghidra.program.model.address.*; -import ghidra.trace.model.TraceAddressSnapRange; -import ghidra.trace.model.memory.*; -import ghidra.util.task.TaskMonitor; - -public interface DebuggerListingAutoReadMemoryAction extends AutoReadMemoryAction { - public interface AutoReadMemorySpec { - AutoReadMemorySpec READ_NONE = new ReadNoneMemorySpec(); - AutoReadMemorySpec READ_VISIBLE = new ReadVisibleMemorySpec(); - AutoReadMemorySpec READ_VIS_RO_ONCE = new ReadVisibleROOnceMemorySpec(); - - public static class AutoReadMemorySpecConfigFieldCodec - implements ConfigFieldCodec { - @Override - public AutoReadMemorySpec read(SaveState state, String name, - AutoReadMemorySpec current) { - String specName = state.getString(name, null); - return fromConfigName(specName); - } - - @Override - public void write(SaveState state, String name, AutoReadMemorySpec value) { - state.putString(name, value.getConfigName()); - } - } - - static AutoReadMemorySpec fromConfigName(String spec) { - switch (spec) { - default: - case "READ_VIS_RO_ONCE": - return READ_VIS_RO_ONCE; - } - } - - String getConfigName(); - - /** - * Perform the automatic read, if applicable - * - *

- * Note, the implementation should perform all the error handling. The returned future is - * for follow-up purposes only, and should always complete normally. - * - * @param coordinates the listing's current coordinates - * @param visible the listing's visible addresses - * @return a future that completes when the memory has been read - */ - CompletableFuture readMemory(DebuggerCoordinates coordinates, AddressSetView visible); - } - - class ReadNoneMemorySpec implements AutoReadMemorySpec { - static final String CONFIG_NAME = "READ_NONE"; - - @Override - public String getConfigName() { - return CONFIG_NAME; - } - - @Override - public CompletableFuture readMemory(DebuggerCoordinates coordinates, - AddressSetView visible) { - return AsyncUtils.NIL; - } - } - - class ReadVisibleMemorySpec implements AutoReadMemorySpec { - static final String CONFIG_NAME = "READ_VISIBLE"; - - @Override - public String getConfigName() { - return CONFIG_NAME; - } - - @Override - public CompletableFuture readMemory(DebuggerCoordinates coordinates, - AddressSetView visible) { - if (!coordinates.isAliveAndReadsPresent()) { - return AsyncUtils.NIL; - } - TraceRecorder recorder = coordinates.getRecorder(); - AddressSet visibleAccessible = - recorder.getAccessibleProcessMemory().intersect(visible); - TraceMemoryManager mm = coordinates.getTrace().getMemoryManager(); - AddressSetView alreadyKnown = - mm.getAddressesWithState(coordinates.getSnap(), visibleAccessible, - s -> s == TraceMemoryState.KNOWN); - AddressSet toRead = visibleAccessible.subtract(alreadyKnown); - - if (toRead.isEmpty()) { - return AsyncUtils.NIL; - } - - return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY); - } - } - - class ReadVisibleROOnceMemorySpec implements AutoReadMemorySpec { - static final String CONFIG_NAME = "READ_VIS_RO_ONCE"; - - @Override - public String getConfigName() { - return CONFIG_NAME; - } - - @Override - public CompletableFuture readMemory(DebuggerCoordinates coordinates, - AddressSetView visible) { - if (!coordinates.isAliveAndReadsPresent()) { - return AsyncUtils.NIL; - } - TraceRecorder recorder = coordinates.getRecorder(); - AddressSet visibleAccessible = - recorder.getAccessibleProcessMemory().intersect(visible); - TraceMemoryManager mm = coordinates.getTrace().getMemoryManager(); - AddressSetView alreadyKnown = - mm.getAddressesWithState(coordinates.getSnap(), visibleAccessible, - s -> s == TraceMemoryState.KNOWN); - AddressSet toRead = visibleAccessible.subtract(alreadyKnown); - - if (toRead.isEmpty()) { - return AsyncUtils.NIL; - } - - AddressSet everKnown = new AddressSet(); - for (AddressRange range : visible) { - for (Entry ent : mm - .getMostRecentStates(coordinates.getSnap(), range)) { - everKnown.add(ent.getKey().getRange()); - } - } - AddressSet readOnly = new AddressSet(); - for (AddressRange range : visible) { - for (TraceMemoryRegion region : mm - .getRegionsIntersecting(Range.singleton(coordinates.getSnap()), range)) { - if (region.isWrite()) { - continue; - } - readOnly.add(region.getRange()); - } - } - toRead.delete(everKnown.intersect(readOnly)); - - if (toRead.isEmpty()) { - return AsyncUtils.NIL; - } - - return recorder.captureProcessMemory(toRead, TaskMonitor.DUMMY); - } - } - - static MultiStateActionBuilder builder(Plugin owner) { - MultiStateActionBuilder builder = AutoReadMemoryAction.builder(owner); - return builder - .toolBarGroup(NAME) - .performActionOnButtonClick(true) - .addState(NAME_NONE, ICON_NONE, AutoReadMemorySpec.READ_NONE) - .addState(NAME_VISIBLE, ICON_VISIBLE, AutoReadMemorySpec.READ_VISIBLE) - .addState(NAME_VIS_RO_ONCE, ICON_VIS_RO_ONCE, AutoReadMemorySpec.READ_VIS_RO_ONCE); - } -} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPlugin.java index b38f78266b..06e41a3823 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingPlugin.java @@ -34,7 +34,8 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates; import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.event.*; import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractNewListingAction; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingTrackLocationAction.LocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.action.NoneLocationTrackingSpec; import ghidra.app.services.*; import ghidra.app.util.viewer.format.FormatManager; import ghidra.framework.options.AutoOptions; @@ -426,7 +427,8 @@ public class DebuggerListingPlugin extends CodeBrowserPlugin implements Debugger provider.readConfigState(providerState); // Yes, config } else { - provider.setTrackingSpec(LocationTrackingSpec.TRACK_NONE); + provider.setTrackingSpec( + LocationTrackingSpec.fromConfigName(NoneLocationTrackingSpec.CONFIG_NAME)); } } } 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 67b08b37c3..a25a9fc5ed 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 @@ -46,10 +46,9 @@ import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel; import ghidra.app.plugin.core.debug.DebuggerCoordinates; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources.*; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingAutoReadMemoryAction.AutoReadMemorySpec; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingAutoReadMemoryAction.AutoReadMemorySpec.AutoReadMemorySpecConfigFieldCodec; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingTrackLocationAction.LocationTrackingSpec; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingTrackLocationAction.LocationTrackingSpec.TrackingSpecConfigFieldCodec; +import ghidra.app.plugin.core.debug.gui.action.*; +import ghidra.app.plugin.core.debug.gui.action.AutoReadMemorySpec.AutoReadMemorySpecConfigFieldCodec; +import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec.TrackingSpecConfigFieldCodec; import ghidra.app.plugin.core.debug.utils.BackgroundUtils; import ghidra.app.plugin.core.debug.utils.ProgramURLUtils; import ghidra.app.plugin.core.exporter.ExporterDialog; @@ -92,9 +91,7 @@ import utilities.util.SuppressableCallback; import utilities.util.SuppressableCallback.Suppression; public class DebuggerListingProvider extends CodeViewerProvider implements ListingDisplayListener { - private static final LocationTrackingSpec DEFAULT_TRACKING_SPEC = LocationTrackingSpec.TRACK_PC; - private static final AutoReadMemorySpec DEFAULT_READ_MEMORY_SPEC = - AutoReadMemorySpec.READ_VIS_RO_ONCE; + private static final AutoConfigState.ClassHandler CONFIG_STATE_HANDLER = AutoConfigState.wireHandler(DebuggerListingProvider.class, MethodHandles.lookup()); private static final String KEY_DEBUGGER_COORDINATES = "DebuggerCoordinates"; @@ -314,6 +311,11 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi } } + private final LocationTrackingSpec defaultTrackingSpec = + LocationTrackingSpec.fromConfigName(PCLocationTrackingSpec.CONFIG_NAME); + private final AutoReadMemorySpec defaultReadMemorySpec = + AutoReadMemorySpec.fromConfigName(VisibleROOnceAutoReadMemorySpec.CONFIG_NAME); + private final DebuggerListingPlugin plugin; //@AutoServiceConsumed via method @@ -356,7 +358,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi protected final DebuggerGoToDialog goToDialog; @AutoConfigStateField(codec = TrackingSpecConfigFieldCodec.class) - protected LocationTrackingSpec trackingSpec = DEFAULT_TRACKING_SPEC; + protected LocationTrackingSpec trackingSpec = defaultTrackingSpec; @AutoConfigStateField protected boolean syncToStaticListing; @AutoConfigStateField @@ -364,7 +366,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi @AutoConfigStateField protected boolean followsCurrentThread = true; @AutoConfigStateField(codec = AutoReadMemorySpecConfigFieldCodec.class) - protected AutoReadMemorySpec autoReadMemorySpec = DEFAULT_READ_MEMORY_SPEC; + protected AutoReadMemorySpec autoReadMemorySpec = defaultReadMemorySpec; // TODO: followsCurrentSnap protected ForTrackingAndLabelingTraceListener forTrackingTraceListener = @@ -698,11 +700,11 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi // TODO: Add "other" option, and present most-recent in menu, too // TODO: "other" as in arbitrary expression? // Only those applicable to the current thread's registers, though. - actionTrackLocation = DebuggerListingTrackLocationAction.builder(plugin) + actionTrackLocation = DebuggerTrackLocationAction.builder(plugin) .onAction(this::activatedLocationTracking) .onActionStateChanged(this::changedLocationTracking) .buildAndInstallLocal(this); - actionTrackLocation.setCurrentActionStateByUserData(DEFAULT_TRACKING_SPEC); + actionTrackLocation.setCurrentActionStateByUserData(defaultTrackingSpec); actionGoTo = GoToAction.builder(plugin) .enabledWhen(ctx -> current.getView() != null) @@ -721,11 +723,11 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi actionFollowsCurrentThread = new FollowsCurrentThreadAction(); } actionCaptureSelectedMemory = new CaptureSelectedMemoryAction(); - actionAutoReadMemory = DebuggerListingAutoReadMemoryAction.builder(plugin) + actionAutoReadMemory = DebuggerAutoReadMemoryAction.builder(plugin) .onAction(this::activatedAutoReadMemory) .onActionStateChanged(this::changedAutoReadMemory) .buildAndInstallLocal(this); - actionAutoReadMemory.setCurrentActionStateByUserData(DEFAULT_READ_MEMORY_SPEC); + actionAutoReadMemory.setCurrentActionStateByUserData(defaultReadMemorySpec); actionExportView = ExportTraceViewAction.builder(plugin) .enabledWhen(ctx -> current.getView() != null) @@ -1059,7 +1061,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi return null; } // NB: view's snap may be forked for emulation - Address address = trackingSpec.computeTraceAddress(cur, current.getView().getSnap()); + Address address = trackingSpec.computeTraceAddress(tool, cur, current.getView().getSnap()); return address == null ? null : new ProgramLocation(current.getView(), address); } @@ -1112,7 +1114,7 @@ public class DebuggerListingProvider extends CodeViewerProvider implements Listi } protected void doAutoReadMemory() { - autoReadMemorySpec.readMemory(current, visible).exceptionally(ex -> { + autoReadMemorySpec.readMemory(tool, current, visible).exceptionally(ex -> { Msg.error(this, "Could not auto-read memory: " + ex); return null; }); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingTrackLocationAction.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingTrackLocationAction.java deleted file mode 100644 index c4c4f280b1..0000000000 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingTrackLocationAction.java +++ /dev/null @@ -1,302 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.debug.gui.listing; - -import docking.action.builder.MultiStateActionBuilder; -import ghidra.app.plugin.core.debug.DebuggerCoordinates; -import ghidra.app.plugin.core.debug.gui.DebuggerResources.TrackLocationAction; -import ghidra.framework.options.SaveState; -import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec; -import ghidra.framework.plugintool.Plugin; -import ghidra.program.model.address.*; -import ghidra.program.model.lang.Register; -import ghidra.program.model.lang.RegisterValue; -import ghidra.trace.model.Trace; -import ghidra.trace.model.TraceAddressSnapRange; -import ghidra.trace.model.memory.TraceMemoryRegisterSpace; -import ghidra.trace.model.memory.TraceMemoryState; -import ghidra.trace.model.stack.TraceStack; -import ghidra.trace.model.stack.TraceStackFrame; -import ghidra.trace.model.thread.TraceThread; -import ghidra.trace.util.TraceAddressSpace; -import ghidra.trace.util.TraceRegisterUtils; - -public interface DebuggerListingTrackLocationAction extends TrackLocationAction { - public interface LocationTrackingSpec { - LocationTrackingSpec TRACK_PC = new PCLocationTrackingSpec(); - LocationTrackingSpec TRACK_SP = new SPLocationTrackingSpec(); - LocationTrackingSpec TRACK_NONE = new NoneLocationTrackingSpec(); - - public static class TrackingSpecConfigFieldCodec - implements ConfigFieldCodec { - @Override - public LocationTrackingSpec read(SaveState state, String name, - LocationTrackingSpec current) { - String specName = state.getString(name, null); - return fromConfigName(specName); - } - - @Override - public void write(SaveState state, String name, LocationTrackingSpec value) { - state.putString(name, value.getConfigName()); - } - } - - static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range, - DebuggerCoordinates current) { - if (space == null || space.getThread() != current.getThread()) { - return false; - } - if (space.getFrameLevel() != current.getFrame()) { - return false; - } - if (!range.getLifespan().contains(current.getSnap())) { - return false; - } - return true; - } - - static LocationTrackingSpec fromConfigName(String spec) { - switch (spec) { - default: - case PCLocationTrackingSpec.CONFIG_NAME: - return TRACK_PC; - case SPLocationTrackingSpec.CONFIG_NAME: - return TRACK_SP; - case NoneLocationTrackingSpec.CONFIG_NAME: - return TRACK_NONE; - } - } - - String getConfigName(); - - /** - * Compute a title prefix to indicate this tracking specification - * - * @param thread the provider's current thread - * @return a prefix, or {@code null} to use a default - */ - String computeTitle(DebuggerCoordinates coordinates); - - Address computeTraceAddress(DebuggerCoordinates coordinates, long emuSnap); - - // TODO: Is there a way to generalize these so that other dependencies need not - // have their own bespoke methods? - - boolean affectedByRegisterChange(TraceAddressSpace space, - TraceAddressSnapRange range, DebuggerCoordinates coordinates); - - boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates); - } - - class NoneLocationTrackingSpec implements LocationTrackingSpec { - static final String CONFIG_NAME = "TRACK_NONE"; - - @Override - public String getConfigName() { - return CONFIG_NAME; - } - - @Override - public String computeTitle(DebuggerCoordinates coordinates) { - return null; - } - - @Override - public Address computeTraceAddress(DebuggerCoordinates coordinates, long emuSnap) { - return null; - } - - @Override - public boolean affectedByRegisterChange(TraceAddressSpace space, - TraceAddressSnapRange range, DebuggerCoordinates coordinates) { - return false; - } - - @Override - public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { - return false; - } - } - - // TODO: Use this, or allow arbitrary expressions - interface RegisterLocationTrackingSpec extends LocationTrackingSpec { - Register computeRegister(DebuggerCoordinates coordinates); - - AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates); - - @Override - default String computeTitle(DebuggerCoordinates coordinates) { - Register register = computeRegister(coordinates); - if (register == null) { - return null; - } - return register.getName(); - } - - @Override - default Address computeTraceAddress(DebuggerCoordinates coordinates, long emuSnap) { - Trace trace = coordinates.getTrace(); - TraceThread thread = coordinates.getThread(); - long snap = coordinates.getSnap(); - int frame = coordinates.getFrame(); - Register reg = computeRegister(coordinates); - if (reg == null) { - return null; - } - if (!thread.getLifespan().contains(snap)) { - return null; - } - TraceMemoryRegisterSpace regs = - trace.getMemoryManager().getMemoryRegisterSpace(thread, frame, false); - if (regs == null) { - return null; - } - RegisterValue value; - if (regs.getState(emuSnap, reg) == TraceMemoryState.KNOWN) { - value = regs.getValue(emuSnap, reg); - } - else { - value = regs.getValue(snap, reg); - } - if (value == null) { - return null; - } - // TODO: Action to select the address space - // Could use code unit, but that can't specify space, yet, either.... - return computeDefaultAddressSpace(coordinates) - .getAddress(value.getUnsignedValue().longValue()); - } - - @Override - default boolean affectedByRegisterChange(TraceAddressSpace space, - TraceAddressSnapRange range, DebuggerCoordinates coordinates) { - if (!LocationTrackingSpec.changeIsCurrent(space, range, coordinates)) { - return false; - } - Register register = computeRegister(coordinates); - AddressRange regRng = TraceRegisterUtils.rangeForRegister(register); - return range.getRange().intersects(regRng); - } - - @Override - default boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { - return false; - } - } - - class PCLocationTrackingSpec implements RegisterLocationTrackingSpec { - static final String CONFIG_NAME = "TRACK_PC"; - - @Override - public String getConfigName() { - return CONFIG_NAME; - } - - @Override - public Register computeRegister(DebuggerCoordinates coordinates) { - Trace trace = coordinates.getTrace(); - if (trace == null) { - return null; - } - return trace.getBaseLanguage().getProgramCounter(); - } - - @Override - public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) { - return coordinates.getTrace().getBaseLanguage().getDefaultSpace(); - } - - public Address computePCViaStack(DebuggerCoordinates coordinates) { - Trace trace = coordinates.getTrace(); - TraceThread thread = coordinates.getThread(); - long snap = coordinates.getSnap(); - TraceStack stack = trace.getStackManager().getLatestStack(thread, snap); - if (stack == null) { - return null; - } - int level = coordinates.getFrame(); - TraceStackFrame frame = stack.getFrame(level, false); - if (frame == null) { - return null; - } - return frame.getProgramCounter(); - } - - @Override - public Address computeTraceAddress(DebuggerCoordinates coordinates, long emuSnap) { - if (coordinates.getTime().isSnapOnly()) { - Address pc = computePCViaStack(coordinates); - if (pc != null) { - return pc; - } - } - return RegisterLocationTrackingSpec.super.computeTraceAddress(coordinates, emuSnap); - } - - // Note it does no good to override affectByRegChange. It must do what we'd avoid anyway. - @Override - public boolean affectedByStackChange(TraceStack stack, DebuggerCoordinates coordinates) { - if (stack.getThread() != coordinates.getThread()) { - return false; - } - if (!coordinates.getTime().isSnapOnly()) { - return false; - } - // TODO: Would be nice to have stack lifespan... - TraceStack curStack = coordinates.getTrace() - .getStackManager() - .getLatestStack(stack.getThread(), coordinates.getSnap()); - if (stack != curStack) { - return false; - } - return true; - } - } - - class SPLocationTrackingSpec implements RegisterLocationTrackingSpec { - static final String CONFIG_NAME = "TRACK_SP"; - - @Override - public String getConfigName() { - return CONFIG_NAME; - } - - @Override - public Register computeRegister(DebuggerCoordinates coordinates) { - Trace trace = coordinates.getTrace(); - if (trace == null) { - return null; - } - return trace.getBaseCompilerSpec().getStackPointer(); - } - - @Override - public AddressSpace computeDefaultAddressSpace(DebuggerCoordinates coordinates) { - return coordinates.getTrace().getBaseLanguage().getDefaultDataSpace(); - } - } - - static MultiStateActionBuilder builder(Plugin owner) { - MultiStateActionBuilder builder = TrackLocationAction.builder(owner); - return builder - .toolBarGroup(owner.getName()) - .performActionOnButtonClick(true) - .addState(NAME_NONE, ICON_NONE, LocationTrackingSpec.TRACK_NONE) - .addState(NAME_PC, ICON_PC, LocationTrackingSpec.TRACK_PC) - .addState(NAME_SP, ICON_SP, LocationTrackingSpec.TRACK_SP); - } -} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java index 682ee1a6d2..618a38e4d4 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/utils/MiscellaneousUtils.java @@ -17,8 +17,13 @@ package ghidra.app.plugin.core.debug.utils; import java.awt.Component; import java.beans.PropertyEditor; +import java.util.Map; +import java.util.function.Function; +import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec; import ghidra.framework.options.*; +import ghidra.util.Msg; +import ghidra.util.classfinder.ClassSearcher; public enum MiscellaneousUtils { ; @@ -57,4 +62,21 @@ public enum MiscellaneousUtils { throw new IllegalStateException( "Ghidra does not know how to use PropertyEditor: " + editor.getClass().getName()); } + + public static void collectUniqueInstances(Class cls, Map map, + Function keyFunc) { + // This is wasteful. Existing instances will be re-instantiated and thrown away + for (T t : ClassSearcher.getInstances(cls)) { + String key = keyFunc.apply(t); + T exists = map.get(key); + if (exists != null) { + if (exists.getClass().equals(t.getClass())) { + continue; + } + Msg.error(LocationTrackingSpec.class, + cls.getSimpleName() + " conflict over key: " + key); + } + map.put(key, t); + } + } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerListingService.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerListingService.java index 8c6a1a5b85..6e2999f5e9 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerListingService.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/services/DebuggerListingService.java @@ -15,9 +15,8 @@ */ package ghidra.app.services; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingTrackLocationAction.LocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.listing.*; import ghidra.framework.plugintool.ServiceInfo; import ghidra.program.model.address.Address; import ghidra.program.util.ProgramSelection; diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsPluginScreenShots.java index d5d2d7be11..632a33b9bd 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsPluginScreenShots.java @@ -28,14 +28,13 @@ import generic.Unique; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest.TestDebuggerTargetTraceMapper; import ghidra.app.plugin.core.debug.service.breakpoint.DebuggerLogicalBreakpointServicePlugin; import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceProxyPlugin; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin; import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin; import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin; import ghidra.app.services.*; import ghidra.dbg.model.TestDebuggerModelBuilder; -import ghidra.dbg.target.TargetBreakpointSpecContainer; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind; +import ghidra.dbg.target.TargetBreakpointSpecContainer; import ghidra.dbg.testutil.DebuggerModelTestUtils; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Program; @@ -51,10 +50,6 @@ import help.screenshot.GhidraScreenShotGenerator; public class DebuggerBreakpointsPluginScreenShots extends GhidraScreenShotGenerator implements DebuggerModelTestUtils { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - TestDebuggerModelBuilder mb = new TestDebuggerModelBuilder(); DebuggerModelServiceProxyPlugin modelService; DebuggerStaticMappingService mappingService; diff --git a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java index 6772bd1052..c08a148bcf 100644 --- a/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java +++ b/Ghidra/Debug/Debugger/src/screen/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsPluginScreenShots.java @@ -21,7 +21,6 @@ import org.junit.Test; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest.TestDebuggerTargetTraceMapper; import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceProxyPlugin; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin; import ghidra.app.services.DebuggerTraceManagerService; import ghidra.app.services.TraceRecorder; @@ -32,10 +31,6 @@ import help.screenshot.GhidraScreenShotGenerator; public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - // NOTE: Using model builder to capture "recording" icon in tabs TestDebuggerModelBuilder mb = new TestDebuggerModelBuilder(); DebuggerModelServiceProxyPlugin modelService; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginTest.java index b07f81c80a..30ab4d58a0 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPluginTest.java @@ -41,12 +41,11 @@ import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources.*; import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.*; import ghidra.app.services.LogicalBreakpoint.Enablement; import ghidra.app.util.viewer.listingpanel.ListingPanel; -import ghidra.dbg.target.TargetBreakpointSpecContainer; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind; +import ghidra.dbg.target.TargetBreakpointSpecContainer; import ghidra.framework.store.LockException; import ghidra.program.disassemble.Disassembler; import ghidra.program.model.address.Address; @@ -74,10 +73,6 @@ public class DebuggerBreakpointMarkerPluginTest extends AbstractGhidraHeadedDebu protected static final Color DE_COLOR = new Color(255, 192, 128); protected static final Color ED_COLOR = new Color(255, 128, 192); - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - protected DebuggerBreakpointMarkerPlugin breakpointMarkerPlugin; protected DebuggerListingPlugin listingPlugin; protected CodeBrowserPlugin codeBrowserPlugin; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java index 7c2e8f4743..21eb216527 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProviderTest.java @@ -31,7 +31,6 @@ import generic.Unique; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.DebuggerResources.*; import ghidra.app.plugin.core.debug.gui.breakpoint.DebuggerBreakpointsProvider.LogicalBreakpointTableModel; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.*; import ghidra.async.AsyncTestUtils; import ghidra.dbg.model.TestTargetProcess; @@ -56,10 +55,6 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge protected static final long TIMEOUT_MILLIS = SystemUtilities.isInTestingBatchMode() ? 5000 : Long.MAX_VALUE; - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - protected DebuggerBreakpointsPlugin breakpointsPlugin; protected DebuggerBreakpointsProvider breakpointsProvider; protected DebuggerStaticMappingService mappingService; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java index a455f2d532..35cee1e9d5 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/listing/DebuggerListingProviderTest.java @@ -35,9 +35,7 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.DebuggerResources; import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractFollowsCurrentThreadAction; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingAutoReadMemoryAction.AutoReadMemorySpec; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingTrackLocationAction.LocationTrackingSpec; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; +import ghidra.app.plugin.core.debug.gui.action.*; import ghidra.app.services.*; import ghidra.app.util.viewer.listingpanel.ListingPanel; import ghidra.async.SwingExecutorService; @@ -59,16 +57,34 @@ import ghidra.trace.model.time.TraceSnapshot; import ghidra.util.database.UndoableTransaction; public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUITest { + static LocationTrackingSpec getLocationTrackingSpec(String name) { + return /*waitForValue(() ->*/ LocationTrackingSpec.fromConfigName(name)/*)*/; + } + + static AutoReadMemorySpec getAutoReadMemorySpec(String name) { + return AutoReadMemorySpec.fromConfigName(name); + } + + final LocationTrackingSpec trackNone = + getLocationTrackingSpec(NoneLocationTrackingSpec.CONFIG_NAME); + final LocationTrackingSpec trackPc = + getLocationTrackingSpec(PCLocationTrackingSpec.CONFIG_NAME); + final LocationTrackingSpec trackSp = + getLocationTrackingSpec(SPLocationTrackingSpec.CONFIG_NAME); + + final AutoReadMemorySpec readNone = + getAutoReadMemorySpec(NoneAutoReadMemorySpec.CONFIG_NAME); + final AutoReadMemorySpec readVisible = + getAutoReadMemorySpec(VisibleAutoReadMemorySpec.CONFIG_NAME); + final AutoReadMemorySpec readVisROOnce = + getAutoReadMemorySpec(VisibleROOnceAutoReadMemorySpec.CONFIG_NAME); + protected DebuggerListingPlugin listingPlugin; protected DebuggerListingProvider listingProvider; protected DebuggerStaticMappingService mappingService; protected CodeViewerService codeViewer; - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - @Before public void setUpListingProviderTest() throws Exception { listingPlugin = addPlugin(tool, DebuggerListingPlugin.class); @@ -230,7 +246,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI TraceThread thread1; TraceThread thread2; DebuggerListingProvider extraListing = SwingExecutorService.INSTANCE.submit( - () -> listingPlugin.createListingIfMissing(LocationTrackingSpec.TRACK_PC, true)).get(); + () -> listingPlugin.createListingIfMissing(trackPc, true)).get(); try (UndoableTransaction tid = tb.startTransaction()) { DBTraceMemoryManager memory = tb.trace.getMemoryManager(); memory.addRegion("exe:.text", Range.atLeast(0L), tb.range(0x00400000, 0x0040ffff), @@ -288,7 +304,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI //Pre-check assertEquals(tb.addr(0x00400000), listingProvider.getLocation().getAddress()); - listingProvider.setTrackingSpec(LocationTrackingSpec.TRACK_SP); + listingProvider.setTrackingSpec(trackSp); waitForSwing(); ProgramLocation loc = listingProvider.getLocation(); @@ -299,7 +315,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testFollowsCurrentTraceOnTraceChangeWithoutRegisterTracking() throws Exception { - listingProvider.setTrackingSpec(LocationTrackingSpec.TRACK_NONE); + listingProvider.setTrackingSpec(trackNone); try ( // ToyDBTraceBuilder b1 = new ToyDBTraceBuilder(name.getMethodName() + "_1", LANGID_TOYBE64); // @@ -356,7 +372,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testFollowsCurrentThreadOnThreadChangeWithoutRegisterTracking() throws Exception { - listingProvider.setTrackingSpec(LocationTrackingSpec.TRACK_NONE); + listingProvider.setTrackingSpec(trackNone); try ( // ToyDBTraceBuilder b1 = new ToyDBTraceBuilder(name.getMethodName() + "_1", LANGID_TOYBE64); // @@ -635,8 +651,8 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI byte[] data = incBlock(); byte[] zero = new byte[data.length]; ByteBuffer buf = ByteBuffer.allocate(data.length); - assertEquals(AutoReadMemorySpec.READ_VIS_RO_ONCE, listingProvider.getAutoReadMemorySpec()); - listingProvider.setAutoReadMemorySpec(AutoReadMemorySpec.READ_NONE); + assertEquals(readVisROOnce, listingProvider.getAutoReadMemorySpec()); + listingProvider.setAutoReadMemorySpec(readNone); createTestModel(); mb.createTestProcessesAndThreads(); @@ -678,7 +694,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI * NOTE: Should read immediately upon setting auto-read, but we're not focused on the * written block */ - listingProvider.setAutoReadMemorySpec(AutoReadMemorySpec.READ_VIS_RO_ONCE); + listingProvider.setAutoReadMemorySpec(readVisROOnce); waitForDomainObject(trace); buf.clear(); assertEquals(data.length, @@ -731,7 +747,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI listingProvider.locationLabel.getText()); DebuggerListingProvider extraProvider = runSwing( - () -> listingPlugin.createListingIfMissing(LocationTrackingSpec.TRACK_NONE, false)); + () -> listingPlugin.createListingIfMissing(trackNone, false)); waitForSwing(); assertEquals(traceManager.getCurrentView(), extraProvider.getProgram()); assertEquals("dynamic-testCloseCurrentTraceBlanksListings", @@ -819,8 +835,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI waitForSwing(); // Check the default is track pc - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress()); runSwing(() -> goToDyn(tb.addr(0x00400000))); @@ -831,15 +846,14 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI performAction(listingProvider.actionTrackLocation); assertEquals(tb.addr(0x00401234), listingProvider.getLocation().getAddress()); - setActionStateWithTrigger(listingProvider.actionTrackLocation, - LocationTrackingSpec.TRACK_SP, EventTrigger.GUI_ACTION); + setActionStateWithTrigger(listingProvider.actionTrackLocation, trackSp, + EventTrigger.GUI_ACTION); waitForSwing(); assertEquals(tb.addr(0x1fff8765), listingProvider.getLocation().getAddress()); - listingProvider.setTrackingSpec(LocationTrackingSpec.TRACK_NONE); + listingProvider.setTrackingSpec(trackNone); waitForSwing(); - assertEquals(LocationTrackingSpec.TRACK_NONE, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackNone, listingProvider.actionTrackLocation.getCurrentUserData()); } @Test @@ -922,7 +936,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI // NOTE: Action does not exist for main dynamic listing DebuggerListingProvider extraProvider = runSwing( - () -> listingPlugin.createListingIfMissing(LocationTrackingSpec.TRACK_NONE, true)); + () -> listingPlugin.createListingIfMissing(trackNone, true)); waitForSwing(); assertTrue(extraProvider.actionFollowsCurrentThread.isEnabled()); assertTrue(extraProvider.actionFollowsCurrentThread.isSelected()); @@ -950,7 +964,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI byte[] zero = new byte[data.length]; ByteBuffer buf = ByteBuffer.allocate(data.length); assertFalse(listingProvider.actionCaptureSelectedMemory.isEnabled()); - listingProvider.setAutoReadMemorySpec(AutoReadMemorySpec.READ_NONE); + listingProvider.setAutoReadMemorySpec(readNone); // To verify enabled requires live target createAndOpenTrace(); @@ -1045,28 +1059,24 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI public void testActionAutoReadMemory() { assertTrue(listingProvider.actionAutoReadMemory.isEnabled()); - assertEquals(AutoReadMemorySpec.READ_VIS_RO_ONCE, listingProvider.getAutoReadMemorySpec()); - assertEquals(AutoReadMemorySpec.READ_VIS_RO_ONCE, - listingProvider.actionAutoReadMemory.getCurrentUserData()); + assertEquals(readVisROOnce, listingProvider.getAutoReadMemorySpec()); + assertEquals(readVisROOnce, listingProvider.actionAutoReadMemory.getCurrentUserData()); listingProvider.actionAutoReadMemory - .setCurrentActionStateByUserData(AutoReadMemorySpec.READ_NONE); + .setCurrentActionStateByUserData(readNone); waitForSwing(); - assertEquals(AutoReadMemorySpec.READ_NONE, listingProvider.getAutoReadMemorySpec()); - assertEquals(AutoReadMemorySpec.READ_NONE, - listingProvider.actionAutoReadMemory.getCurrentUserData()); + assertEquals(readNone, listingProvider.getAutoReadMemorySpec()); + assertEquals(readNone, listingProvider.actionAutoReadMemory.getCurrentUserData()); - listingProvider.setAutoReadMemorySpec(AutoReadMemorySpec.READ_VIS_RO_ONCE); + listingProvider.setAutoReadMemorySpec(readVisROOnce); waitForSwing(); - assertEquals(AutoReadMemorySpec.READ_VIS_RO_ONCE, listingProvider.getAutoReadMemorySpec()); - assertEquals(AutoReadMemorySpec.READ_VIS_RO_ONCE, - listingProvider.actionAutoReadMemory.getCurrentUserData()); + assertEquals(readVisROOnce, listingProvider.getAutoReadMemorySpec()); + assertEquals(readVisROOnce, listingProvider.actionAutoReadMemory.getCurrentUserData()); - listingProvider.setAutoReadMemorySpec(AutoReadMemorySpec.READ_NONE); + listingProvider.setAutoReadMemorySpec(readNone); waitForSwing(); - assertEquals(AutoReadMemorySpec.READ_NONE, listingProvider.getAutoReadMemorySpec()); - assertEquals(AutoReadMemorySpec.READ_NONE, - listingProvider.actionAutoReadMemory.getCurrentUserData()); + assertEquals(readNone, listingProvider.getAutoReadMemorySpec()); + assertEquals(readNone, listingProvider.actionAutoReadMemory.getCurrentUserData()); } @Test @@ -1154,8 +1164,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testActivateThreadTracks() throws Exception { - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); createAndOpenTrace(); Register pc = tb.language.getProgramCounter(); @@ -1186,8 +1195,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testActivateSnapTracks() throws Exception { - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); createAndOpenTrace(); Register pc = tb.language.getProgramCounter(); @@ -1215,8 +1223,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testActivateFrameTracks() throws Exception { - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); createAndOpenTrace(); TraceThread thread; @@ -1244,8 +1251,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testRegsPCChangedTracks() throws Exception { - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); createAndOpenTrace(); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); @@ -1275,8 +1281,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testRegsPCChangedTracksDespiteStackWithNoPC() throws Exception { - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); createAndOpenTrace(); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); @@ -1310,8 +1315,7 @@ public class DebuggerListingProviderTest extends AbstractGhidraHeadedDebuggerGUI @Test public void testStackPCChangedTracks() throws Exception { - assertEquals(LocationTrackingSpec.TRACK_PC, - listingProvider.actionTrackLocation.getCurrentUserData()); + assertEquals(trackPc, listingProvider.actionTrackLocation.getCurrentUserData()); createAndOpenTrace(); DBTraceStackManager sm = tb.trace.getStackManager(); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java index 37942f8061..8551280e29 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/modules/DebuggerModulesProviderTest.java @@ -35,7 +35,6 @@ import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingProvider; import ghidra.app.plugin.core.debug.gui.modules.DebuggerBlockChooserDialog.MemoryBlockRow; import ghidra.app.plugin.core.debug.gui.modules.DebuggerModuleMapProposalDialog.ModuleMapTableColumns; import ghidra.app.plugin.core.debug.gui.modules.DebuggerSectionMapProposalDialog.SectionMapTableColumns; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.DebuggerListingService; import ghidra.app.services.DebuggerStaticMappingService.ModuleMapEntry; import ghidra.app.services.DebuggerStaticMappingService.SectionMapEntry; @@ -76,10 +75,6 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerGUI protected TraceSection secLibText; protected TraceSection secLibData; - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - @Before public void setUpModulesProviderTest() throws Exception { modulesPlugin = addPlugin(tool, DebuggerModulesPlugin.class); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProviderTest.java index 18ceae5375..d3c89e7a1c 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProviderTest.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.debug.gui.register; -import static ghidra.lifecycle.Unfinished.*; +import static ghidra.lifecycle.Unfinished.TODO; import static org.junit.Assert.*; import java.math.BigInteger; @@ -27,8 +27,9 @@ import org.junit.*; import com.google.common.collect.Range; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; -import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingTrackLocationAction.LocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.action.LocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.action.NoneLocationTrackingSpec; +import ghidra.app.plugin.core.debug.gui.listing.*; import ghidra.app.plugin.core.debug.gui.register.DebuggerRegistersProvider.RegisterTableColumns; import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.TraceRecorder; @@ -48,9 +49,6 @@ import ghidra.util.exception.DuplicateNameException; public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerGUITest implements AsyncTestUtils { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } protected DebuggerRegistersPlugin registersPlugin; protected DebuggerRegistersProvider registersProvider; @@ -701,7 +699,8 @@ public class DebuggerRegistersProviderTest extends AbstractGhidraHeadedDebuggerG addRegisterValues(thread); addRegisterTypes(thread); // Ensure cause is goto PC, not register tracking - listingPlugin.setTrackingSpec(LocationTrackingSpec.TRACK_NONE); + listingPlugin.setTrackingSpec( + LocationTrackingSpec.fromConfigName(NoneLocationTrackingSpec.CONFIG_NAME)); traceManager.activateThread(thread); waitForSwing(); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java index 262f29aafe..9ee7a08ba9 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/thread/DebuggerThreadsProviderTest.java @@ -29,7 +29,6 @@ import com.google.common.collect.Range; import docking.widgets.EventTrigger; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.TraceRecorder; import ghidra.trace.model.Trace; import ghidra.trace.model.thread.TraceThread; @@ -39,9 +38,6 @@ import ghidra.trace.model.time.TraceTimeManager; import ghidra.util.database.UndoableTransaction; public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerGUITest { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } protected DebuggerThreadsPlugin threadsPlugin; protected DebuggerThreadsProvider threadsProvider; diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java index 3a1c87c5a8..8b09279d48 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProviderTest.java @@ -26,7 +26,6 @@ import org.junit.*; import generic.Unique; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.TraceRecorder; import ghidra.dbg.model.TestTargetRegisterBankInThread; import ghidra.program.model.address.Address; @@ -43,9 +42,6 @@ import ghidra.util.Msg; import ghidra.util.database.UndoableTransaction; public class DebuggerWatchesProviderTest extends AbstractGhidraHeadedDebuggerGUITest { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } protected static void assertNoErr(WatchRow row) { Throwable error = row.getError(); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapperTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapperTest.java index 20e53d5bab..c3298da1b2 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapperTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/mapping/LargestSubDebuggerRegisterMapperTest.java @@ -24,7 +24,6 @@ import org.junit.Before; import org.junit.Test; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.TraceRecorder; import ghidra.dbg.model.TestTargetRegister; import ghidra.dbg.target.*; @@ -34,9 +33,6 @@ import ghidra.test.ToyProgramBuilder; import ghidra.trace.model.thread.TraceThread; public class LargestSubDebuggerRegisterMapperTest extends AbstractGhidraHeadedDebuggerGUITest { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } static class TestTargetMapper extends AbstractDebuggerTargetTraceMapper { public TestTargetMapper(TargetObject target) diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServiceTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServiceTest.java index 99edff76e3..e80cd87bf8 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServiceTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/breakpoint/DebuggerLogicalBreakpointServiceTest.java @@ -26,7 +26,6 @@ import org.junit.*; import generic.Unique; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.*; import ghidra.app.services.LogicalBreakpoint.Enablement; import ghidra.async.AsyncReference; @@ -54,10 +53,6 @@ public class DebuggerLogicalBreakpointServiceTest extends AbstractGhidraHeadedDe protected static final long TIMEOUT_MILLIS = SystemUtilities.isInTestingBatchMode() ? 5000 : Long.MAX_VALUE; - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - /** * Tracks the current set of logical breakpoints. * diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServiceTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServiceTest.java index 8e9c0c4902..1889c3b723 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServiceTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServiceTest.java @@ -34,8 +34,6 @@ import ghidra.dbg.DebuggerObjectModel; import ghidra.dbg.model.TestDebuggerObjectModel; import ghidra.dbg.model.TestLocalDebuggerModelFactory; import ghidra.dbg.testutil.DebuggerModelTestUtils; -import ghidra.dbg.util.PathMatcher; -import ghidra.dbg.util.PathUtils; import ghidra.trace.model.Trace; import ghidra.trace.model.thread.TraceThread; import ghidra.util.SystemUtilities; @@ -54,58 +52,6 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes protected static final long TIMEOUT_MILLIS = SystemUtilities.isInTestingBatchMode() ? 5000 : Long.MAX_VALUE; - public static final PathMatcher HARDCODED_MATCHER = new PathMatcher() { - { - // Paths for GDB - addPattern(PathUtils.parse("Breakpoints[].")); - addPattern(PathUtils.parse("Inferiors[].Memory[]")); - addPattern(PathUtils.parse("Inferiors[].Modules[].Sections[]")); - addPattern(PathUtils.parse("Inferiors[].Registers[]")); - addPattern(PathUtils.parse("Inferiors[].Threads[]")); - addPattern(PathUtils.parse("Inferiors[].Threads[].Stack[]")); - - // Paths for dbgeng - addPattern(PathUtils.parse("Sessions[].Processes[].Memory[]")); - addPattern(PathUtils.parse("Sessions[].Processes[].Modules[]")); - addPattern(PathUtils.parse("Sessions[].Processes[].Threads[].Registers[]")); - addPattern(PathUtils.parse("Sessions[].Processes[].Threads[].Stack[]")); - addPattern(PathUtils.parse("Sessions[].Processes[].Debug.Breakpoints[]")); - - // (Additional) paths for dbgmodel - addPattern(PathUtils.parse("Sessions[].Attributes")); - addPattern(PathUtils.parse("Sessions[].Processes[].Threads[].Stack.Frames[]")); - addPattern(PathUtils.parse("Sessions[].Processes[].Threads[].TTD.Position")); - addPattern(PathUtils.parse("Sessions[].Processes[].Threads[].Registers.User.")); - - // Paths for JDI - addPattern(PathUtils.parse("VirtualMachines[]")); - addPattern(PathUtils.parse("VirtualMachines[].Breakpoints")); - addPattern(PathUtils.parse("VirtualMachines[].Classes[]")); - addPattern(PathUtils.parse("VirtualMachines[].Classes[].Sections[]")); - addPattern(PathUtils.parse("VirtualMachines[].Threads[]")); - addPattern(PathUtils.parse("VirtualMachines[].Threads[].Registers[]")); - addPattern(PathUtils.parse("VirtualMachines[].Threads[].Stack[]")); - - } - }; - - public static void addTestModelPathPatterns() { - PathMatcher m = HARDCODED_MATCHER; - m.addPattern(PathUtils.parse("Processes[]")); - m.addPattern(PathUtils.parse("Processes[].Breakpoints[]")); - m.addPattern(PathUtils.parse("Processes[].Memory[]")); - m.addPattern(PathUtils.parse("Processes[].Modules[]")); - m.addPattern(PathUtils.parse("Processes[].Registers[]")); - m.addPattern(PathUtils.parse("Processes[].Threads[]")); - m.addPattern(PathUtils.parse("Processes[].Threads[].RegisterBank")); - m.addPattern(PathUtils.parse("Processes[].Threads[].Stack[]")); - m.addPattern(PathUtils.parse("Processes[].Threads[].Stack[].RegisterBank")); - } - - static { - addTestModelPathPatterns(); - } - /** * Exists just for mocking, because jmockit does Bad Things (TM) to * CollectionChangeListener.of() if I try to mock one of those or a subclass directly. I'm diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorderTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorderTest.java index 7b3b0d30b7..4962894f07 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorderTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/model/DefaultTraceRecorderTest.java @@ -40,16 +40,8 @@ import ghidra.trace.model.memory.*; import ghidra.trace.model.thread.TraceThread; import ghidra.util.database.UndoableTransaction; -/** - * NOTE: I'd like to avoid putting too much stuff in here until schemas are done, but I suppose - * refactoring tests is all part of the refactoring game when it comes down to it. - */ public class DefaultTraceRecorderTest extends AbstractGhidraHeadedDebuggerGUITest { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - @Test public void testThreadsRecorded() throws Exception { createTestModel(); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java index 9d82efc7ec..b8fa475a49 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServiceTest.java @@ -26,7 +26,6 @@ import org.junit.Test; import ghidra.app.plugin.core.debug.DebuggerCoordinates; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.services.TraceRecorder; import ghidra.dbg.model.TestTargetStack; import ghidra.dbg.model.TestTargetStackFrameHasRegisterBank; @@ -41,10 +40,6 @@ public class DebuggerTraceManagerServiceTest extends AbstractGhidraHeadedDebugge protected static final long TIMEOUT_MILLIS = SystemUtilities.isInTestingBatchMode() ? 5000 : Long.MAX_VALUE; - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } - @Test public void testGetOpenTraces() throws Exception { assertEquals(Set.of(), traceManager.getOpenTraces()); diff --git a/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java b/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java index b0fa832abc..f2c6f13daa 100644 --- a/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java +++ b/Ghidra/Debug/Debugger/src/test/java/ghidra/pcode/exec/TraceRecorderAsyncPcodeExecTest.java @@ -24,7 +24,6 @@ import java.util.Map; import org.junit.Test; import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest; -import ghidra.app.plugin.core.debug.service.model.DebuggerModelServiceTest; import ghidra.app.plugin.processors.sleigh.SleighLanguage; import ghidra.app.services.TraceRecorder; import ghidra.dbg.model.TestTargetRegisterBankInThread; @@ -37,9 +36,6 @@ import ghidra.trace.model.thread.TraceThread; public class TraceRecorderAsyncPcodeExecTest extends AbstractGhidraHeadedDebuggerGUITest implements DebuggerModelTestUtils { - static { - DebuggerModelServiceTest.addTestModelPathPatterns(); - } @Test public void testExecutorEval() throws Throwable {