diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceHighlightPluginEvent.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceHighlightPluginEvent.java new file mode 100644 index 0000000000..a602378241 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceHighlightPluginEvent.java @@ -0,0 +1,38 @@ +/* ### + * 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.event; + +import java.util.Objects; + +import ghidra.app.events.AbstractHighlightPluginEvent; +import ghidra.program.util.ProgramSelection; +import ghidra.trace.model.program.TraceProgramView; + +public class TraceHighlightPluginEvent extends AbstractHighlightPluginEvent { + public static final String NAME = "TraceHighlight"; + + private final TraceProgramView view; + + public TraceHighlightPluginEvent(String src, ProgramSelection highlight, + TraceProgramView view) { + super(src, NAME, highlight, view); + this.view = Objects.requireNonNull(view); + } + + public TraceProgramView getTraceProgramView() { + return view; + } +} diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceLocationPluginEvent.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceLocationPluginEvent.java index 58bede035a..b23f09961a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceLocationPluginEvent.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceLocationPluginEvent.java @@ -4,9 +4,9 @@ * 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. @@ -15,34 +15,21 @@ */ package ghidra.app.plugin.core.debug.event; -import java.util.Objects; - -import ghidra.framework.plugintool.PluginEvent; +import ghidra.app.events.AbstractLocationPluginEvent; import ghidra.program.util.ProgramLocation; import ghidra.trace.model.program.TraceProgramView; -public class TraceLocationPluginEvent extends PluginEvent { +public class TraceLocationPluginEvent extends AbstractLocationPluginEvent { public static final String NAME = "TraceLocation"; - private final ProgramLocation loc; private final TraceProgramView view; public TraceLocationPluginEvent(String src, ProgramLocation loc) { - super(src, NAME); - this.loc = Objects.requireNonNull(loc); + super(src, NAME, loc, loc.getProgram()); this.view = (TraceProgramView) loc.getProgram(); } - public ProgramLocation getLocation() { - return loc; - } - public TraceProgramView getTraceProgramView() { return view; } - - @Override - protected String getDetails() { - return loc.getClass() + " addr==> " + loc.getAddress(); - } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceSelectionPluginEvent.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceSelectionPluginEvent.java index d9572a9a04..b45cc7a29d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceSelectionPluginEvent.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TraceSelectionPluginEvent.java @@ -4,9 +4,9 @@ * 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. @@ -17,33 +17,22 @@ package ghidra.app.plugin.core.debug.event; import java.util.Objects; -import ghidra.framework.plugintool.PluginEvent; +import ghidra.app.events.AbstractSelectionPluginEvent; import ghidra.program.util.ProgramSelection; import ghidra.trace.model.program.TraceProgramView; -public class TraceSelectionPluginEvent extends PluginEvent { +public class TraceSelectionPluginEvent extends AbstractSelectionPluginEvent { public static final String NAME = "TraceSelection"; - private ProgramSelection selection; - private TraceProgramView view; + private final TraceProgramView view; - public TraceSelectionPluginEvent(String src, ProgramSelection sel, TraceProgramView view) { - super(src, NAME); - - this.selection = Objects.requireNonNull(sel); + public TraceSelectionPluginEvent(String src, ProgramSelection selection, + TraceProgramView view) { + super(src, NAME, selection, view); this.view = Objects.requireNonNull(view); } - public ProgramSelection getSelection() { - return selection; - } - public TraceProgramView getTraceProgramView() { return view; } - - @Override - protected String getDetails() { - return getClass() + " ==> " + selection; - } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TrackingChangedPluginEvent.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TrackingChangedPluginEvent.java new file mode 100644 index 0000000000..c41beb3fd9 --- /dev/null +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/event/TrackingChangedPluginEvent.java @@ -0,0 +1,34 @@ +/* ### + * 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.event; + +import ghidra.debug.api.action.LocationTrackingSpec; +import ghidra.framework.plugintool.PluginEvent; + +public class TrackingChangedPluginEvent extends PluginEvent { + public static final String NAME = "TrackingChanged"; + + private final LocationTrackingSpec spec; + + public TrackingChangedPluginEvent(String sourceName, LocationTrackingSpec spec) { + super(sourceName, NAME); + this.spec = spec; + } + + public LocationTrackingSpec getLocationTrackingSpec() { + return spec; + } +} 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 a2fd97c6f2..307131ffe4 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 @@ -62,7 +62,6 @@ import utilities.util.SuppressableCallback.Suppression; packageName = DebuggerPluginPackage.NAME, status = PluginStatus.RELEASED, eventsConsumed = { - // ProgramHighlightPluginEvent.class, // TODO: Later or remove ProgramOpenedPluginEvent.class, // For auto-open log cleanup ProgramClosedPluginEvent.class, // For marker set cleanup ProgramActivatedPluginEvent.class, // To track the static program for sync @@ -70,19 +69,25 @@ import utilities.util.SuppressableCallback.Suppression; ProgramSelectionPluginEvent.class, // For static listing sync TraceActivatedPluginEvent.class, // Trace/thread activation and register tracking TraceClosedPluginEvent.class, + TraceLocationPluginEvent.class, + TraceSelectionPluginEvent.class, + TraceHighlightPluginEvent.class, + TrackingChangedPluginEvent.class, }, eventsProduced = { ProgramLocationPluginEvent.class, ProgramSelectionPluginEvent.class, TraceLocationPluginEvent.class, - TraceSelectionPluginEvent.class + TraceSelectionPluginEvent.class, + TraceHighlightPluginEvent.class, + TrackingChangedPluginEvent.class, }, servicesRequired = { DebuggerStaticMappingService.class, // For static listing sync. TODO: Optional? DebuggerEmulationService.class, // TODO: Optional? ProgramManager.class, // For static listing sync ClipboardService.class, - MarkerService.class // TODO: Make optional? + MarkerService.class, // TODO: Make optional? }, servicesProvided = { DebuggerListingService.class, @@ -208,11 +213,16 @@ public class DebuggerListingPlugin extends AbstractCodeBrowserPlugin { + switch (event) { + case ProgramLocationPluginEvent ev -> cbProgramLocationEvents.invoke(() -> { if (heedLocationEvent(ev)) { connectedProvider.staticProgramLocationChanged(ev.getLocation()); } }); - } - if (event instanceof ProgramSelectionPluginEvent ev) { - cbProgramSelectionEvents.invoke(() -> { + case ProgramSelectionPluginEvent ev -> cbProgramSelectionEvents.invoke(() -> { if (heedSelectionEvent(ev)) { connectedProvider.staticProgramSelectionChanged(ev.getProgram(), ev.getSelection()); } }); - } - if (event instanceof ProgramOpenedPluginEvent ev) { - allProviders(p -> p.programOpened(ev.getProgram())); - } - if (event instanceof ProgramClosedPluginEvent ev) { - allProviders(p -> p.programClosed(ev.getProgram())); - } - if (event instanceof ProgramActivatedPluginEvent ev) { - allProviders(p -> p.staticProgramActivated(ev.getActiveProgram())); - } - if (event instanceof TraceActivatedPluginEvent ev) { - current = ev.getActiveCoordinates(); - allProviders(p -> p.coordinatesActivated(current)); - } - if (event instanceof TraceClosedPluginEvent ev) { - if (current.getTrace() == ev.getTrace()) { - current = DebuggerCoordinates.NOWHERE; + case ProgramOpenedPluginEvent ev -> allProviders(p -> p.programOpened(ev.getProgram())); + case ProgramClosedPluginEvent ev -> allProviders(p -> p.programClosed(ev.getProgram())); + case ProgramActivatedPluginEvent ev -> allProviders( + p -> p.staticProgramActivated(ev.getActiveProgram())); + case TraceActivatedPluginEvent ev -> { + current = ev.getActiveCoordinates(); + allProviders(p -> p.coordinatesActivated(current)); + } + case TraceClosedPluginEvent ev -> { + if (current.getTrace() == ev.getTrace()) { + current = DebuggerCoordinates.NOWHERE; + } + allProviders(p -> p.traceClosed(ev.getTrace())); + } + case TraceLocationPluginEvent ev -> { + // For those comparing to CodeBrowserPlugin, there is no "viewManager" here. + connectedProvider.goTo(ev.getTraceProgramView(), ev.getLocation()); + } + case TraceSelectionPluginEvent ev -> { + if (ev.getTraceProgramView() == current.getView()) { + connectedProvider.setSelection(ev.getSelection()); + } + } + case TraceHighlightPluginEvent ev -> { + if (ev.getTraceProgramView() == current.getView()) { + connectedProvider.setHighlight(ev.getHighlight()); + } + } + case TrackingChangedPluginEvent ev -> connectedProvider + .setTrackingSpec(ev.getLocationTrackingSpec()); + default -> { } - allProviders(p -> p.traceClosed(ev.getTrace())); } } 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 e81963aca8..a559cd96b0 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 @@ -52,6 +52,7 @@ import ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel; import ghidra.app.plugin.core.debug.disassemble.CurrentPlatformTraceDisassembleCommand; import ghidra.app.plugin.core.debug.disassemble.CurrentPlatformTraceDisassembleCommand.Reqs; import ghidra.app.plugin.core.debug.disassemble.DebuggerDisassemblerPlugin; +import ghidra.app.plugin.core.debug.event.TrackingChangedPluginEvent; import ghidra.app.plugin.core.debug.gui.*; import ghidra.app.plugin.core.debug.gui.DebuggerResources.FollowsCurrentThreadAction; import ghidra.app.plugin.core.debug.gui.DebuggerResources.OpenProgramAction; @@ -240,6 +241,9 @@ public class DebuggerListingProvider extends CodeViewerProvider { @Override protected void specChanged(LocationTrackingSpec spec) { + if (isMainListing()) { + plugin.firePluginEvent(new TrackingChangedPluginEvent(getName(), spec)); + } updateTitle(); trackingLabel.setText(""); trackingLabel.setToolTipText(""); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPlugin.java index 7e8bb50e1e..44bfb3d0cb 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesPlugin.java @@ -4,9 +4,9 @@ * 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. @@ -22,10 +22,9 @@ import java.util.stream.Collectors; import org.jdom.Element; import docking.action.DockingAction; -import ghidra.app.events.ProgramLocationPluginEvent; -import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.plugin.PluginCategoryNames; -import ghidra.app.plugin.core.byteviewer.*; +import ghidra.app.plugin.core.byteviewer.AbstractByteViewerPlugin; +import ghidra.app.plugin.core.byteviewer.ByteViewerComponentProvider; import ghidra.app.plugin.core.debug.DebuggerPluginPackage; import ghidra.app.plugin.core.debug.event.*; import ghidra.app.plugin.core.debug.gui.DebuggerResources.NewMemoryAction; @@ -37,8 +36,8 @@ import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.annotation.AutoServiceConsumed; import ghidra.framework.plugintool.util.PluginStatus; -import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramSelection; +import ghidra.trace.model.program.TraceProgramView; @PluginInfo( shortDescription = "View bytes of trace (possibly live) memory", @@ -53,10 +52,16 @@ import ghidra.program.util.ProgramSelection; // ProgramHighlightPluginEvent.class, // TODO: Later or remove TraceActivatedPluginEvent.class, // Trace/thread activation and register tracking TraceClosedPluginEvent.class, + TraceLocationPluginEvent.class, + TraceSelectionPluginEvent.class, + TraceHighlightPluginEvent.class, + TrackingChangedPluginEvent.class, }, eventsProduced = { TraceLocationPluginEvent.class, TraceSelectionPluginEvent.class, + TraceHighlightPluginEvent.class, + TrackingChangedPluginEvent.class, }, servicesRequired = { ClipboardService.class, @@ -116,29 +121,12 @@ public class DebuggerMemoryBytesPlugin } } - @Override - protected void updateLocation( - ProgramByteViewerComponentProvider programByteViewerComponentProvider, - ProgramLocationPluginEvent event, boolean export) { - // TODO - } - - @Override - protected void fireProgramLocationPluginEvent( - ProgramByteViewerComponentProvider programByteViewerComponentProvider, - ProgramLocationPluginEvent pluginEvent) { - // TODO - } - - @Override - public void updateSelection(ByteViewerComponentProvider provider, - ProgramSelectionPluginEvent event, Program program) { - // TODO - } - @Override public void highlightChanged(ByteViewerComponentProvider provider, ProgramSelection highlight) { - // TODO + if (provider == connectedProvider) { + tool.firePluginEvent(new TraceHighlightPluginEvent(getName(), highlight, + (TraceProgramView) connectedProvider.getProgram())); + } } protected void allProviders(Consumer action) { @@ -150,17 +138,22 @@ public class DebuggerMemoryBytesPlugin @Override public void processEvent(PluginEvent event) { + // do not delegate to super if (event instanceof TraceActivatedPluginEvent ev) { current = ev.getActiveCoordinates(); allProviders(p -> p.coordinatesActivated(current)); } - if (event instanceof TraceClosedPluginEvent ev) { + else if (event instanceof TraceClosedPluginEvent ev) { if (current.getTrace() == ev.getTrace()) { current = DebuggerCoordinates.NOWHERE; } allProviders(p -> p.traceClosed(ev.getTrace())); } - // TODO: Sync among dynamic providers? + else if (event instanceof TraceLocationPluginEvent ev) { + currentLocation = ev.getLocation(); + } + + connectedProvider.doHandleTraceEvent(event); } @AutoServiceConsumed diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java index 34316f89b9..af28dafa1f 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryBytesProvider.java @@ -36,13 +36,15 @@ import docking.action.ToggleDockingAction; import docking.menu.MultiStateDockingAction; import docking.widgets.fieldpanel.support.ViewerPosition; import generic.theme.GThemeDefaults.Colors; +import ghidra.app.events.AbstractLocationPluginEvent; +import ghidra.app.events.AbstractSelectionPluginEvent; import ghidra.app.plugin.core.byteviewer.*; +import ghidra.app.plugin.core.debug.event.*; import ghidra.app.plugin.core.debug.gui.*; import ghidra.app.plugin.core.debug.gui.DebuggerResources.FollowsCurrentThreadAction; import ghidra.app.plugin.core.debug.gui.action.*; import ghidra.app.plugin.core.debug.gui.action.AutoReadMemorySpec.AutoReadMemorySpecConfigFieldCodec; -import ghidra.app.plugin.core.format.ByteBlock; -import ghidra.app.plugin.core.format.ByteBlockAccessException; +import ghidra.app.plugin.core.format.*; import ghidra.app.services.*; import ghidra.app.services.DebuggerControlService.ControlModeChangeListener; import ghidra.debug.api.action.GoToInput; @@ -133,18 +135,21 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi DebuggerMemoryBytesProvider.this); } - @Override - protected void locationTracked() { - doGoToTracked(); - } - @Override protected void specChanged(LocationTrackingSpec spec) { + if (isMainViewer()) { + plugin.firePluginEvent(new TrackingChangedPluginEvent(getName(), spec)); + } updateTitle(); trackingLabel.setText(""); trackingLabel.setToolTipText(""); trackingLabel.setForeground(Colors.FOREGROUND); } + + @Override + protected void locationTracked() { + doGoToTracked(); + } } protected class ForMemoryBytesReadsMemoryTrait extends DebuggerReadsMemoryTrait { @@ -380,15 +385,32 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi } class TargetByteBlockSet extends ProgramByteBlockSet { + private final DebuggerMemoryBytesProvider provider; + protected TargetByteBlockSet(ByteBlockChangeManager changeManager) { super(DebuggerMemoryBytesProvider.this, DebuggerMemoryBytesProvider.this.program, changeManager); + this.provider = DebuggerMemoryBytesProvider.this; } @Override protected MemoryByteBlock newMemoryByteBlock(Memory memory, MemoryBlock memBlock) { return new TargetByteBlock(program, memory, memBlock); } + + @Override + public AbstractLocationPluginEvent getPluginEvent(String source, ByteBlock block, + BigInteger offset, int column) { + ProgramLocation loc = provider.getLocation(block, offset, column); + return new TraceLocationPluginEvent(source, loc); + } + + @Override + public AbstractSelectionPluginEvent getPluginEvent(String source, + ByteBlockSelection selection) { + ProgramSelection pSel = convertSelection(selection); + return new TraceSelectionPluginEvent(source, pSel, (TraceProgramView) program); + } } @Override @@ -604,6 +626,20 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi } } + void doHandleTraceEvent(PluginEvent event) { + if (getByteBlocks() == null) { + return; + } + switch (event) { + case TraceLocationPluginEvent ev -> processLocationEvent(ev); + case TraceSelectionPluginEvent ev -> processSelectionEvent(ev); + case TraceHighlightPluginEvent ev -> processHighlightEvent(ev); + case TrackingChangedPluginEvent ev -> setTrackingSpec(ev.getLocationTrackingSpec()); + default -> { + } + } + } + public void setFollowsCurrentThread(boolean follows) { if (isMainViewer()) { throw new IllegalStateException( diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractHighlightPluginEvent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractHighlightPluginEvent.java new file mode 100644 index 0000000000..df39d508c4 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractHighlightPluginEvent.java @@ -0,0 +1,69 @@ +/* ### + * 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.events; + +import java.lang.ref.WeakReference; + +import ghidra.framework.plugintool.PluginEvent; +import ghidra.program.model.listing.Program; +import ghidra.program.util.ProgramSelection; + +/** + * Plugin event generated when the highlight in a program changes. + */ +public abstract class AbstractHighlightPluginEvent extends PluginEvent { + + private final ProgramSelection highlight; + private final WeakReference programRef; + + /** + * Construct a new event. + * + * @param sourceName the name of the plugin that generated this event + * @param eventName the name of the event type + * @param highlight the program highlight + * @param program the program associated with this event + */ + public AbstractHighlightPluginEvent(String sourceName, String eventName, + ProgramSelection highlight, Program program) { + super(sourceName, eventName); + this.highlight = highlight; + this.programRef = new WeakReference(program); + } + + /** + * Get the program highlight contained in this event. + * + * @return the program highlight in this event. + */ + public ProgramSelection getHighlight() { + return highlight; + } + + /** + * Get the program that the highlight refers to. + * + * @return the program + */ + public Program getProgram() { + return programRef.get(); + } + + @Override + protected String getDetails() { + return getClass() + " ==> " + highlight; + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractLocationPluginEvent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractLocationPluginEvent.java new file mode 100644 index 0000000000..10fedbe161 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractLocationPluginEvent.java @@ -0,0 +1,79 @@ +/* ### + * 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.events; + +import java.lang.ref.WeakReference; + +import ghidra.framework.plugintool.PluginEvent; +import ghidra.program.model.listing.Program; +import ghidra.program.util.ProgramLocation; +import ghidra.util.Msg; + +public abstract class AbstractLocationPluginEvent extends PluginEvent { + + private final ProgramLocation location; + private final WeakReference programRef; + + /** + * Construct a new event + * + * @param sourceName the name of the plugin that generated this event. + * @param eventName the name of the event type + * @param location the new location + * @param program the program for which the location object refers. + */ + protected AbstractLocationPluginEvent(String sourceName, String eventName, + ProgramLocation location, Program program) { + super(sourceName, eventName); + + // don't allow a null for a program location + if (location == null) { + NullPointerException exc = new NullPointerException( + "Null ProgramLocation passed to create a Plugin event"); + Msg.showError(this, + null, "Error", + "Null LocationEvent being created. Trace and remove this problem", exc); + } + this.location = location; + this.programRef = new WeakReference(program); + } + + /** + * Get the location stored in this event. + * + * @return the location + */ + public ProgramLocation getLocation() { + return location; + } + + /** + * Get the program that the location refers to. + * + * @return the program + */ + public Program getProgram() { + return programRef.get(); + } + + @Override + protected String getDetails() { + if (location != null) { + return location.getClass().getName() + " addr==> " + location.getAddress() + "\n"; + } + return super.getDetails(); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractSelectionPluginEvent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractSelectionPluginEvent.java new file mode 100644 index 0000000000..65838fc490 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/events/AbstractSelectionPluginEvent.java @@ -0,0 +1,80 @@ +/* ### + * 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.events; + +import java.lang.ref.WeakReference; + +import ghidra.framework.plugintool.PluginEvent; +import ghidra.program.model.listing.Program; +import ghidra.program.util.ProgramSelection; +import ghidra.util.Msg; + +/** + * Plugin event generated when the selection in a program changes. + */ +public abstract class AbstractSelectionPluginEvent extends PluginEvent { + + private final ProgramSelection selection; + private final WeakReference programRef; + + /** + * Construct a new plugin event + * + * @param sourceName the name of the plugin that generated this event + * @param eventName the name of the event type + * @param selection the program selection + * @param program the program associated with this event + */ + public AbstractSelectionPluginEvent(String sourceName, String eventName, + ProgramSelection selection, Program program) { + super(sourceName, eventName); + + // don't allow null program selection + if (selection == null) { + NullPointerException exc = new NullPointerException( + "Null ProgramSelection in creating Selection Plugin Event"); + Msg.showError(this, + null, "Internal Error", + "Null SelectionEvent being created. Trace and remove this problem", exc); + } + + this.selection = selection; + this.programRef = new WeakReference(program); + } + + /** + * Get the program selection contained in this event. + * + * @return the program selection in this event. + */ + public ProgramSelection getSelection() { + return selection; + } + + /** + * Get the program that the selection refers to. + * + * @return the program + */ + public Program getProgram() { + return programRef.get(); + } + + @Override + protected String getDetails() { + return getClass() + " ==> " + selection; + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramHighlightPluginEvent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramHighlightPluginEvent.java index 376bbe7444..0c653af5fc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramHighlightPluginEvent.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramHighlightPluginEvent.java @@ -4,9 +4,9 @@ * 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. @@ -15,46 +15,23 @@ */ package ghidra.app.events; -import java.lang.ref.WeakReference; - -import ghidra.framework.plugintool.PluginEvent; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramSelection; /** - * Plugin event generated when the highlight in a program changes. + * Plugin event generated when the highlight in a program changes. */ -public final class ProgramHighlightPluginEvent extends PluginEvent { +public final class ProgramHighlightPluginEvent extends AbstractHighlightPluginEvent { public static final String NAME = "ProgramHighlight"; - private ProgramSelection highlight; - private WeakReference programRef; - /** * Construct a new event. + * * @param src name of the plugin that generated the event * @param hl Program selection containing the selected address set. * @param program program being highlighted */ public ProgramHighlightPluginEvent(String src, ProgramSelection hl, Program program) { - super(src, NAME); - this.highlight = hl; - this.programRef = new WeakReference(program); - } - - /** - * Returns the program selection contained in this event. - * @return ProgramSelection contained in this event. - */ - public ProgramSelection getHighlight() { - return highlight; - } - - /** - * Returns the Program object that the highlight refers to. - * @return the Program object that the highlight refers to. - */ - public Program getProgram() { - return programRef.get(); + super(src, NAME, hl, program); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramLocationPluginEvent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramLocationPluginEvent.java index 2c3d5b327d..3509545c60 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramLocationPluginEvent.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramLocationPluginEvent.java @@ -1,13 +1,12 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * 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. @@ -16,67 +15,32 @@ */ package ghidra.app.events; -import ghidra.framework.plugintool.PluginEvent; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; -import ghidra.util.Msg; - -import java.lang.ref.WeakReference; /** * This plugin event class provides program location information. - * The event is fired when a plugin's program location has changed. - * Typically, a plugin does not actually generate the event unless it is - * processing some user action, - * e.g., the user mouse clicks somewhere on a plugin component to cause - * the program location to change. + * + *

+ * The event is fired when a plugin's program location has changed. Typically, a plugin does not + * actually generate the event unless it is processing some user action, e.g., the user mouse clicks + * somewhere on a plugin component to cause the program location to change. */ -public final class ProgramLocationPluginEvent extends PluginEvent { +public final class ProgramLocationPluginEvent extends AbstractLocationPluginEvent { /** * The name of this plugin event. */ - public static final String NAME = "ProgramLocationChange"; + public static final String NAME = "ProgramLocationChange"; - private ProgramLocation loc; - private WeakReference programRef; - /** - * Construct a new ProgramLocationEvent. - * @param src the name of the plugin that generated this event. - * @param loc the ProgramLocation object that contains the new location. - * @param program the Program for which the loc object refers. - */ - public ProgramLocationPluginEvent(String src, ProgramLocation loc, Program program) { - super(src,NAME); - // don't allow a null for a program location - if (loc == null) { - NullPointerException exc = new NullPointerException( - "Null ProgramLocation passed to create a Plugin event"); - Msg.showError(this, - null, "Error", "Null ProgramLocationEvent being created. Trace and remove this problem", exc); - } - this.loc = loc; - this.programRef = new WeakReference(program); - } - /** - * Returns the ProgramLocation stored in this event. - */ - public ProgramLocation getLocation() { - return loc; - } - - /** - * Returns the Program object that the location refers to. - */ - public Program getProgram() { - return programRef.get(); - } - - @Override - protected String getDetails() { - if (loc != null) { - return loc.getClass().getName() + " addr==> " + loc.getAddress() +"\n"; - } - return super.getDetails(); - } + /** + * Construct a new ProgramLocationEvent. + * + * @param src the name of the plugin that generated this event. + * @param loc the ProgramLocation object that contains the new location. + * @param program the Program for which the loc object refers. + */ + public ProgramLocationPluginEvent(String src, ProgramLocation loc, Program program) { + super(src, NAME, loc, program); + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramSelectionPluginEvent.java b/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramSelectionPluginEvent.java index efd4c00fd0..a644d06d07 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramSelectionPluginEvent.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/events/ProgramSelectionPluginEvent.java @@ -1,13 +1,12 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * 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. @@ -16,65 +15,28 @@ */ package ghidra.app.events; -import ghidra.framework.plugintool.PluginEvent; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramSelection; -import ghidra.util.Msg; - -import java.lang.ref.WeakReference; /** - * Plugin event generated when the selection in a program changes. + * Plugin event generated when the selection in a program changes. */ -public final class ProgramSelectionPluginEvent extends PluginEvent { - +public final class ProgramSelectionPluginEvent extends AbstractSelectionPluginEvent { + /** * The name of this plugin event. */ - public static final String NAME = "ProgramSelection"; - - private ProgramSelection selection; - private WeakReference programRef; + public static final String NAME = "ProgramSelection"; /** * Construct a new plugin event + * * @param src the name of the plugin that generated this event * @param sel the program selection * @param program the program associated with this event */ - public ProgramSelectionPluginEvent(String src,ProgramSelection sel, - Program program) { - super(src,NAME); - - // don't allow null program selection - if (sel == null) { - NullPointerException exc = new NullPointerException( - "Null ProgramSelection in creating Selection Plugin Event"); - Msg.showError(this, - null, "Internal Error", "Null ProgramSelectionEvent being created. Trace and remove this problem", exc); - } - - this.selection = sel; - this.programRef = new WeakReference(program); - } - - /** - * Returns the program selection contained in this event. - * @return ProgramSelection the program selection in this event. - */ - public ProgramSelection getSelection() { - return selection; - } - - /** - * Returns the Program object that the selection refers to. - */ - public Program getProgram() { - return programRef.get(); - } - - @Override - protected String getDetails() { - return "Address Set ==> " + selection; - } + public ProgramSelectionPluginEvent(String src, ProgramSelection sel, + Program program) { + super(src, NAME, sel, program); + } } diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/AbstractByteViewerPlugin.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/AbstractByteViewerPlugin.java index c456a7bd51..6e70731620 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/AbstractByteViewerPlugin.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/AbstractByteViewerPlugin.java @@ -4,9 +4,9 @@ * 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. @@ -19,8 +19,8 @@ import java.util.*; import org.jdom.Element; -import ghidra.app.events.ProgramLocationPluginEvent; -import ghidra.app.events.ProgramSelectionPluginEvent; +import ghidra.app.events.AbstractLocationPluginEvent; +import ghidra.app.events.AbstractSelectionPluginEvent; import ghidra.app.services.*; import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainObject; @@ -30,6 +30,7 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; +import ghidra.util.SystemUtilities; import utility.function.Callback; public abstract class AbstractByteViewerPlugin

@@ -270,8 +271,12 @@ public abstract class AbstractByteViewerPlugin