mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-2295 - fixes and debug code for a history actions stack trace
This commit is contained in:
parent
b8425e804d
commit
c8e15f0fe2
6 changed files with 133 additions and 95 deletions
|
@ -35,9 +35,9 @@ public interface Navigatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commands this navigatable to goto (display) the given program and location
|
* Commands this navigatable to goto (display) the given program and location
|
||||||
*
|
*
|
||||||
* @param program the program
|
* @param program the program
|
||||||
*
|
*
|
||||||
* @param location the location in that program to display
|
* @param location the location in that program to display
|
||||||
* @return true if the goto was successful
|
* @return true if the goto was successful
|
||||||
*/
|
*/
|
||||||
|
@ -45,35 +45,35 @@ public interface Navigatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current location of this Navigatable
|
* Returns the current location of this Navigatable
|
||||||
*
|
*
|
||||||
* @return the current location of this Navigatable
|
* @return the current location of this Navigatable
|
||||||
*/
|
*/
|
||||||
public ProgramLocation getLocation();
|
public ProgramLocation getLocation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current Program of this Navigatable
|
* Returns the current Program of this Navigatable
|
||||||
*
|
*
|
||||||
* @return the current Program of this Navigatable
|
* @return the current Program of this Navigatable
|
||||||
*/
|
*/
|
||||||
public Program getProgram();
|
public Program getProgram();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the view state for this navigatable
|
* Returns the view state for this navigatable
|
||||||
*
|
*
|
||||||
* @return the view state for this navigatable
|
* @return the view state for this navigatable
|
||||||
*/
|
*/
|
||||||
public LocationMemento getMemento();
|
public LocationMemento getMemento();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the view state for this navigatable. This is used later to restore the view state.
|
* Sets the view state for this navigatable. This is used later to restore the view state.
|
||||||
*
|
*
|
||||||
* @param memento the state of this navigatable
|
* @param memento the state of this navigatable
|
||||||
*/
|
*/
|
||||||
public void setMemento(LocationMemento memento);
|
public void setMemento(LocationMemento memento);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an icon that represents this Navigatable
|
* Returns an icon that represents this Navigatable
|
||||||
*
|
*
|
||||||
* @return the icon
|
* @return the icon
|
||||||
*/
|
*/
|
||||||
public Icon getNavigatableIcon();
|
public Icon getNavigatableIcon();
|
||||||
|
@ -81,7 +81,7 @@ public interface Navigatable {
|
||||||
/**
|
/**
|
||||||
* Returns true if this Navigatable is "connected". Navigatables are connected if they produce
|
* Returns true if this Navigatable is "connected". Navigatables are connected if they produce
|
||||||
* and consume location and selection events.
|
* and consume location and selection events.
|
||||||
*
|
*
|
||||||
* @return true if this Navigatable is "connected"
|
* @return true if this Navigatable is "connected"
|
||||||
*/
|
*/
|
||||||
public boolean isConnected();
|
public boolean isConnected();
|
||||||
|
@ -89,8 +89,8 @@ public interface Navigatable {
|
||||||
/**
|
/**
|
||||||
* Return true if this Navigatable is part of the "dynamic analysis" or "debugger" user
|
* Return true if this Navigatable is part of the "dynamic analysis" or "debugger" user
|
||||||
* interface.
|
* interface.
|
||||||
*
|
*
|
||||||
* @return tre if this Navigatable is "dynamic"
|
* @return true if this Navigatable is "dynamic"
|
||||||
*/
|
*/
|
||||||
default public boolean isDynamic() {
|
default public boolean isDynamic() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -98,7 +98,7 @@ public interface Navigatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently only the 'connected' windows support markers
|
* Currently only the 'connected' windows support markers
|
||||||
*
|
*
|
||||||
* @return true if this navigatable supports markers
|
* @return true if this navigatable supports markers
|
||||||
*/
|
*/
|
||||||
public boolean supportsMarkers();
|
public boolean supportsMarkers();
|
||||||
|
@ -110,78 +110,78 @@ public interface Navigatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this provider is visible
|
* Returns true if this provider is visible
|
||||||
*
|
*
|
||||||
* @return true if visible
|
* @return true if visible
|
||||||
*/
|
*/
|
||||||
public boolean isVisible();
|
public boolean isVisible();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells this Navigatable to set its selection to the given selection
|
* Tells this Navigatable to set its selection to the given selection
|
||||||
*
|
*
|
||||||
* @param selection the selection to set.
|
* @param selection the selection to set.
|
||||||
*/
|
*/
|
||||||
public void setSelection(ProgramSelection selection);
|
public void setSelection(ProgramSelection selection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells this Navigatable to set its highlight to the given highlight
|
* Tells this Navigatable to set its highlight to the given highlight
|
||||||
*
|
*
|
||||||
* @param highlight the highlight to set.
|
* @param highlight the highlight to set.
|
||||||
*/
|
*/
|
||||||
public void setHighlight(ProgramSelection highlight);
|
public void setHighlight(ProgramSelection highlight);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current selection of this Navigatable
|
* Returns the current selection of this Navigatable
|
||||||
*
|
*
|
||||||
* @return the current selection of this Navigatable
|
* @return the current selection of this Navigatable
|
||||||
*/
|
*/
|
||||||
public ProgramSelection getSelection();
|
public ProgramSelection getSelection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current highlight of this Navigatable
|
* Returns the current highlight of this Navigatable
|
||||||
*
|
*
|
||||||
* @return the current highlight of this Navigatable
|
* @return the current highlight of this Navigatable
|
||||||
*/
|
*/
|
||||||
public ProgramSelection getHighlight();
|
public ProgramSelection getHighlight();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current text selection or null
|
* Returns the current text selection or null
|
||||||
*
|
*
|
||||||
* @return the text selection
|
* @return the text selection
|
||||||
*/
|
*/
|
||||||
public String getTextSelection();
|
public String getTextSelection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a listener to be notified if this Navigatable is terminated
|
* Adds a listener to be notified if this Navigatable is terminated
|
||||||
*
|
*
|
||||||
* @param listener the listener to be notified when this Navigatable is closed
|
* @param listener the listener to be notified when this Navigatable is closed
|
||||||
*/
|
*/
|
||||||
public void addNavigatableListener(NavigatableRemovalListener listener);
|
public void addNavigatableListener(NavigatableRemovalListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a listener to be notified if this Navigatable is terminated.
|
* Removes a listener to be notified if this Navigatable is terminated.
|
||||||
*
|
*
|
||||||
* @param listener the listener that no longer should be notified when this Navigatable is
|
* @param listener the listener that no longer should be notified when this Navigatable is
|
||||||
* closed.
|
* closed.
|
||||||
*/
|
*/
|
||||||
public void removeNavigatableListener(NavigatableRemovalListener listener);
|
public void removeNavigatableListener(NavigatableRemovalListener listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this navigatable is no longer valid, false if it is still good
|
* Returns true if this navigatable is no longer valid
|
||||||
*
|
*
|
||||||
* @return true if this navigatable is no longer valid, false if it is still good
|
* @return true if this navigatable is no longer valid
|
||||||
*/
|
*/
|
||||||
public boolean isDisposed();
|
public boolean isDisposed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this navigatable supports highlighting
|
* Returns true if this navigatable supports highlighting
|
||||||
*
|
*
|
||||||
* @return true if this navigatable supports highlighting
|
* @return true if this navigatable supports highlighting
|
||||||
*/
|
*/
|
||||||
public boolean supportsHighlight();
|
public boolean supportsHighlight();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the highlight provider for the given program
|
* Set the highlight provider for the given program
|
||||||
*
|
*
|
||||||
* @param highlightProvider the provider
|
* @param highlightProvider the provider
|
||||||
* @param program the program
|
* @param program the program
|
||||||
*/
|
*/
|
||||||
|
@ -189,7 +189,7 @@ public interface Navigatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given highlight provider for the given program
|
* Removes the given highlight provider for the given program
|
||||||
*
|
*
|
||||||
* @param highlightProvider the provider
|
* @param highlightProvider the provider
|
||||||
* @param program the program
|
* @param program the program
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -41,7 +41,7 @@ import ghidra.util.bean.opteditor.OptionsVetoException;
|
||||||
* viewer plugins to change their focus to a certain address. As viewer plugins are directed to one
|
* viewer plugins to change their focus to a certain address. As viewer plugins are directed to one
|
||||||
* or more addresses it maintains information about where the viewers have been to support ability
|
* or more addresses it maintains information about where the viewers have been to support ability
|
||||||
* for the viewers to go back to a previous "focus" point.
|
* for the viewers to go back to a previous "focus" point.
|
||||||
*
|
*
|
||||||
* Services Provided: NavigationHistoryService Events Consumed: ProgramLocationPluginEvent,
|
* Services Provided: NavigationHistoryService Events Consumed: ProgramLocationPluginEvent,
|
||||||
* ProgramPluginEvent Event Produced: HistoryChangePluginEvent Actions: None.
|
* ProgramPluginEvent Event Produced: HistoryChangePluginEvent Actions: None.
|
||||||
*/
|
*/
|
||||||
|
@ -447,7 +447,7 @@ public class NavigationHistoryPlugin extends Plugin
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private static class HistoryList {
|
private static class HistoryList {
|
||||||
private List<LocationMemento> list = new ArrayList<>();
|
private List<LocationMemento> list = new ArrayList<>();
|
||||||
|
@ -551,7 +551,7 @@ public class NavigationHistoryPlugin extends Plugin
|
||||||
/**
|
/**
|
||||||
* Find the next history LocationMemento that contains a different function. If no such
|
* Find the next history LocationMemento that contains a different function. If no such
|
||||||
* LocationMemento is found, null is returned.
|
* LocationMemento is found, null is returned.
|
||||||
*
|
*
|
||||||
* @param navigatable the navigatable being navigated
|
* @param navigatable the navigatable being navigated
|
||||||
* @param moveTo true means after finding, get current location to it. false to just find
|
* @param moveTo true means after finding, get current location to it. false to just find
|
||||||
* and do nothing
|
* and do nothing
|
||||||
|
@ -595,7 +595,7 @@ public class NavigationHistoryPlugin extends Plugin
|
||||||
/**
|
/**
|
||||||
* Find the previous history LocationMemento that contains a different function. If no such
|
* Find the previous history LocationMemento that contains a different function. If no such
|
||||||
* LocationMemento is found, null is returned.
|
* LocationMemento is found, null is returned.
|
||||||
*
|
*
|
||||||
* @param navigatable the navigatable being navigated
|
* @param navigatable the navigatable being navigated
|
||||||
* @param moveTo true means after finding, get current location to it. false to just find
|
* @param moveTo true means after finding, get current location to it. false to just find
|
||||||
* and do nothing
|
* and do nothing
|
||||||
|
@ -627,35 +627,71 @@ public class NavigationHistoryPlugin extends Plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
private Function getPreviousStartFunction(Navigatable navigatable) {
|
private Function getPreviousStartFunction(Navigatable navigatable) {
|
||||||
ProgramLocation location = navigatable.getLocation();
|
ProgramLocation location = getProgramLocation(navigatable);
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address currentAddress = location.getAddress();
|
Address currentAddress = location.getAddress();
|
||||||
|
Program program = location.getProgram();
|
||||||
|
FunctionManager functionManager = program.getFunctionManager();
|
||||||
|
return functionManager.getFunctionContaining(currentAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProgramLocation getProgramLocation(Navigatable navigatable) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// The active component may still be showing the previously loaded function, instead
|
// The active component may still be showing the previously loaded function, instead
|
||||||
// of the current location when that location is not in a function. In that case,
|
// of the current location when that location is not in a function. In that case,
|
||||||
// when that provider is focused, prefer its notion of the current function so that
|
// when that provider is focused, prefer its notion of the current function so that
|
||||||
// users navigating from that view will go to the function before the one that is
|
// users navigating from that view will go to the function before the one that is
|
||||||
// on the history stack. This should feel more intuitive to the user, with the risk
|
// on the history stack. This should feel more intuitive to the user, with the risk
|
||||||
// that the navigation actions will sometimes feel inconsistent, depending upon
|
// that the navigation actions will sometimes feel inconsistent, depending upon
|
||||||
// what view is focused.
|
// what view is focused.
|
||||||
//
|
//
|
||||||
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
|
DockingWindowManager dwm = DockingWindowManager.getActiveInstance();
|
||||||
ComponentProvider provider = manager.getActiveComponentProvider();
|
ComponentProvider activeProvider = dwm.getActiveComponentProvider();
|
||||||
if (provider instanceof Navigatable) {
|
if (activeProvider instanceof Navigatable) {
|
||||||
LocationMemento memento = ((Navigatable) provider).getMemento();
|
Navigatable activeNavigatable = (Navigatable) activeProvider;
|
||||||
ProgramLocation otherLocation = memento.getProgramLocation();
|
LocationMemento memento = activeNavigatable.getMemento();
|
||||||
if (otherLocation != null) {
|
ProgramLocation location =
|
||||||
currentAddress = otherLocation.getAddress();
|
validateProgramLocation(activeNavigatable, memento.getProgramLocation());
|
||||||
|
if (location != null) {
|
||||||
|
// prefer the active natigatable's location
|
||||||
|
return location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProgramLocation location = navigatable.getLocation();
|
||||||
|
return validateProgramLocation(navigatable, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProgramLocation validateProgramLocation(Navigatable navigatable,
|
||||||
|
ProgramLocation location) {
|
||||||
|
if (location == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isClosedProgram(navigatable, location)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO debug code that can go away if we find the source of the lingering program location
|
||||||
|
// being used that causes the program closed exception
|
||||||
|
private boolean isClosedProgram(Navigatable navigatable, ProgramLocation location) {
|
||||||
Program program = location.getProgram();
|
Program program = location.getProgram();
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
if (program.isClosed()) {
|
||||||
return functionManager.getFunctionContaining(currentAddress);
|
|
||||||
|
Msg.showError(this, null, "Closed Program",
|
||||||
|
"The Navigation History Plugin is using a closed program.\n" + "Program: " +
|
||||||
|
program.getName() + "Navigatable: " +
|
||||||
|
navigatable.getClass().getSimpleName() + "\n" + "Location: " +
|
||||||
|
location.getClass().getSimpleName() + " @ " + location.getAddress());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(LocationMemento location) {
|
void remove(LocationMemento location) {
|
||||||
|
|
|
@ -30,28 +30,17 @@ import ghidra.util.SystemUtilities;
|
||||||
/**
|
/**
|
||||||
* Visible Plugin to show ByteBlock data in various formats.
|
* Visible Plugin to show ByteBlock data in various formats.
|
||||||
*/
|
*/
|
||||||
@PluginInfo(
|
@PluginInfo(status = PluginStatus.RELEASED, packageName = CorePluginPackage.NAME, category = PluginCategoryNames.BYTE_VIEWER, shortDescription = "Displays bytes in memory", description = "Provides a component for showing the bytes in memory. " +
|
||||||
status = PluginStatus.RELEASED,
|
"Additional plugins provide capabilites for this plugin" +
|
||||||
packageName = CorePluginPackage.NAME,
|
" to show the bytes in various formats (e.g., hex, octal, decimal)." +
|
||||||
category = PluginCategoryNames.BYTE_VIEWER,
|
" The hex format plugin is loaded by default when this plugin is loaded.", servicesRequired = {
|
||||||
shortDescription = "Displays bytes in memory",
|
|
||||||
description = "Provides a component for showing the bytes in memory. " +
|
|
||||||
"Additional plugins provide capabilites for this plugin" +
|
|
||||||
" to show the bytes in various formats (e.g., hex, octal, decimal)." +
|
|
||||||
" The hex format plugin is loaded by default when this plugin is loaded.",
|
|
||||||
servicesRequired = {
|
|
||||||
ProgramManager.class, GoToService.class, NavigationHistoryService.class,
|
ProgramManager.class, GoToService.class, NavigationHistoryService.class,
|
||||||
ClipboardService.class,
|
ClipboardService.class, }, eventsConsumed = { ProgramLocationPluginEvent.class,
|
||||||
},
|
ProgramActivatedPluginEvent.class, ProgramSelectionPluginEvent.class,
|
||||||
eventsConsumed = {
|
ProgramHighlightPluginEvent.class, ProgramClosedPluginEvent.class,
|
||||||
ProgramLocationPluginEvent.class, ProgramActivatedPluginEvent.class,
|
ByteBlockChangePluginEvent.class, }, eventsProduced = {
|
||||||
ProgramSelectionPluginEvent.class, ProgramHighlightPluginEvent.class,
|
ProgramLocationPluginEvent.class, ProgramSelectionPluginEvent.class,
|
||||||
ProgramClosedPluginEvent.class, ByteBlockChangePluginEvent.class,
|
ByteBlockChangePluginEvent.class, })
|
||||||
},
|
|
||||||
eventsProduced = {
|
|
||||||
ProgramLocationPluginEvent.class, ProgramSelectionPluginEvent.class,
|
|
||||||
ByteBlockChangePluginEvent.class,
|
|
||||||
})
|
|
||||||
public class ByteViewerPlugin extends AbstractByteViewerPlugin<ProgramByteViewerComponentProvider> {
|
public class ByteViewerPlugin extends AbstractByteViewerPlugin<ProgramByteViewerComponentProvider> {
|
||||||
|
|
||||||
public ByteViewerPlugin(PluginTool tool) {
|
public ByteViewerPlugin(PluginTool tool) {
|
||||||
|
@ -73,6 +62,7 @@ public class ByteViewerPlugin extends AbstractByteViewerPlugin<ProgramByteViewer
|
||||||
|
|
||||||
if (event instanceof ProgramActivatedPluginEvent) {
|
if (event instanceof ProgramActivatedPluginEvent) {
|
||||||
currentProgram = ((ProgramActivatedPluginEvent) event).getActiveProgram();
|
currentProgram = ((ProgramActivatedPluginEvent) event).getActiveProgram();
|
||||||
|
currentLocation = null;
|
||||||
}
|
}
|
||||||
else if (event instanceof ProgramLocationPluginEvent) {
|
else if (event instanceof ProgramLocationPluginEvent) {
|
||||||
currentLocation = ((ProgramLocationPluginEvent) event).getLocation();
|
currentLocation = ((ProgramLocationPluginEvent) event).getLocation();
|
||||||
|
@ -131,8 +121,7 @@ public class ByteViewerPlugin extends AbstractByteViewerPlugin<ProgramByteViewer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void highlightChanged(ByteViewerComponentProvider provider,
|
public void highlightChanged(ByteViewerComponentProvider provider, ProgramSelection highlight) {
|
||||||
ProgramSelection highlight) {
|
|
||||||
if (provider == connectedProvider) {
|
if (provider == connectedProvider) {
|
||||||
tool.firePluginEvent(new ProgramHighlightPluginEvent(getName(), highlight,
|
tool.firePluginEvent(new ProgramHighlightPluginEvent(getName(), highlight,
|
||||||
connectedProvider.getProgram()));
|
connectedProvider.getProgram()));
|
||||||
|
|
|
@ -74,9 +74,15 @@ public class DecompilePlugin extends Plugin {
|
||||||
* or when switching program tabs.
|
* or when switching program tabs.
|
||||||
*/
|
*/
|
||||||
SwingUpdateManager delayedLocationUpdateMgr = new SwingUpdateManager(200, 200, () -> {
|
SwingUpdateManager delayedLocationUpdateMgr = new SwingUpdateManager(200, 200, () -> {
|
||||||
if (currentLocation != null) {
|
if (currentLocation == null) {
|
||||||
connectedProvider.setLocation(currentLocation, null);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Program locationProgram = currentLocation.getProgram();
|
||||||
|
if (locationProgram.isClosed()) {
|
||||||
|
return; // not sure if this can happen
|
||||||
|
}
|
||||||
|
connectedProvider.setLocation(currentLocation, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
public DecompilePlugin(PluginTool tool) {
|
public DecompilePlugin(PluginTool tool) {
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSnapshot() {
|
public boolean isSnapshot() {
|
||||||
// we are a snapshot when we are 'disconnected'
|
// we are a snapshot when we are 'disconnected'
|
||||||
return !isConnected();
|
return !isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
/**
|
/**
|
||||||
* Gives to the clipboard of this provider the given string. This will prime the clipboard
|
* Gives to the clipboard of this provider the given string. This will prime the clipboard
|
||||||
* such that a copy action will copy the given string.
|
* such that a copy action will copy the given string.
|
||||||
*
|
*
|
||||||
* @param string the string to set
|
* @param string the string to set
|
||||||
*/
|
*/
|
||||||
public void setClipboardStringContent(String string) {
|
public void setClipboardStringContent(String string) {
|
||||||
|
@ -351,7 +351,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to signal to this provider that it should update its state due to a new function
|
* Called to signal to this provider that it should update its state due to a new function
|
||||||
* being graphed. The UI is updated by the controller without this provider's knowledge.
|
* being graphed. The UI is updated by the controller without this provider's knowledge.
|
||||||
* This call here is to signal that the provider needs to update its metadata.
|
* This call here is to signal that the provider needs to update its metadata.
|
||||||
*/
|
*/
|
||||||
public void functionGraphDataChanged() {
|
public void functionGraphDataChanged() {
|
||||||
|
@ -413,15 +413,15 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
/**
|
/**
|
||||||
* Called from within the FunctionGraph when locations are changed (e.g., if a user clicks
|
* Called from within the FunctionGraph when locations are changed (e.g., if a user clicks
|
||||||
* inside of a vertex)
|
* inside of a vertex)
|
||||||
*
|
*
|
||||||
* @param newLocation the new location
|
* @param newLocation the new location
|
||||||
*/
|
*/
|
||||||
public void graphLocationChanged(ProgramLocation newLocation) {
|
public void graphLocationChanged(ProgramLocation newLocation) {
|
||||||
storeLocation(newLocation);
|
storeLocation(newLocation);
|
||||||
|
|
||||||
if (isFocusedProvider()) {
|
if (isFocusedProvider()) {
|
||||||
|
|
||||||
// Note: this is the easy way to avoid odd event bouncing--only send events out if
|
// Note: this is the easy way to avoid odd event bouncing--only send events out if
|
||||||
// we are focused, as this implies the user is driving the events. A better
|
// we are focused, as this implies the user is driving the events. A better
|
||||||
// metaphor for handling external and internal program locations is needed to
|
// metaphor for handling external and internal program locations is needed to
|
||||||
// simplify the logic of when to broadcast location changes.
|
// simplify the logic of when to broadcast location changes.
|
||||||
|
@ -434,8 +434,8 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
/**
|
/**
|
||||||
* Called from within the FunctionGraph when selections are changed (e.g., if a user clicks
|
* Called from within the FunctionGraph when selections are changed (e.g., if a user clicks
|
||||||
* inside of a vertex)
|
* inside of a vertex)
|
||||||
*
|
*
|
||||||
* @param selection the new selection
|
* @param selection the new selection
|
||||||
*/
|
*/
|
||||||
public void graphSelectionChanged(ProgramSelection selection) {
|
public void graphSelectionChanged(ProgramSelection selection) {
|
||||||
storeSelection(selection);
|
storeSelection(selection);
|
||||||
|
@ -476,10 +476,10 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when for location changes that are <b>external</b> to the function graph (e.g.,
|
* Called when for location changes that are <b>external</b> to the function graph (e.g.,
|
||||||
* when the user clicks in Ghidra's Listing window)
|
* when the user clicks in Ghidra's Listing window)
|
||||||
*
|
*
|
||||||
* @param newLocation the new location
|
* @param newLocation the new location
|
||||||
*/
|
*/
|
||||||
void setLocation(ProgramLocation newLocation) {
|
void setLocation(ProgramLocation newLocation) {
|
||||||
pendingLocation = newLocation;
|
pendingLocation = newLocation;
|
||||||
|
@ -497,6 +497,13 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Program program = newLocation.getProgram();
|
||||||
|
if (program.isClosed()) {
|
||||||
|
// this method is called from an update manager, which means that the callback may
|
||||||
|
// happen after the notification that the program was closed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setLocationNow(newLocation);
|
setLocationNow(newLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +529,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells this provider to refresh, which means to rebuild the graph and relayout the
|
* Tells this provider to refresh, which means to rebuild the graph and relayout the
|
||||||
* vertices.
|
* vertices.
|
||||||
*/
|
*/
|
||||||
private void refresh(boolean keepPerspective) {
|
private void refresh(boolean keepPerspective) {
|
||||||
|
@ -537,7 +544,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
Address address = function.getEntryPoint();
|
Address address = function.getEntryPoint();
|
||||||
Address currentAddress = currentLocation.getAddress();
|
Address currentAddress = currentLocation.getAddress();
|
||||||
if (function.getBody().contains(currentAddress)) {
|
if (function.getBody().contains(currentAddress)) {
|
||||||
// prefer the current address if it is within the current function (i.e., the
|
// prefer the current address if it is within the current function (i.e., the
|
||||||
// location hasn't changed out from under the graph due to threading issues)
|
// location hasn't changed out from under the graph due to threading issues)
|
||||||
address = currentAddress;
|
address = currentAddress;
|
||||||
}
|
}
|
||||||
|
@ -568,7 +575,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the graph that some display data may have changed, but the changes are not worth
|
* Tells the graph that some display data may have changed, but the changes are not worth
|
||||||
* performing a full rebuild
|
* performing a full rebuild
|
||||||
*/
|
*/
|
||||||
public void refreshDisplayWithoutRebuilding() {
|
public void refreshDisplayWithoutRebuilding() {
|
||||||
|
@ -597,7 +604,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
|
|
||||||
//
|
//
|
||||||
// Note: since we are not looping and we are using 'else if's, order is important!
|
// Note: since we are not looping and we are using 'else if's, order is important!
|
||||||
//
|
//
|
||||||
|
|
||||||
if (ev.containsEvent(DomainObject.DO_OBJECT_RESTORED) ||
|
if (ev.containsEvent(DomainObject.DO_OBJECT_RESTORED) ||
|
||||||
ev.containsEvent(ChangeManager.DOCR_FUNCTION_BODY_CHANGED)) {
|
ev.containsEvent(ChangeManager.DOCR_FUNCTION_BODY_CHANGED)) {
|
||||||
|
@ -716,7 +723,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReferenceRemoved(DomainObjectChangeRecord record) {
|
private void handleReferenceRemoved(DomainObjectChangeRecord record) {
|
||||||
//
|
//
|
||||||
// Get the affected vertex (if any). Determine if we have to combine the vertex with
|
// Get the affected vertex (if any). Determine if we have to combine the vertex with
|
||||||
// the vertex below it (adding a reference creates a new basic block, which creates a new
|
// the vertex below it (adding a reference creates a new basic block, which creates a new
|
||||||
// vertex--we may need to reverse that process)
|
// vertex--we may need to reverse that process)
|
||||||
|
@ -730,7 +737,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return; // this particular removal doesn't affect our graph
|
return; // this particular removal doesn't affect our graph
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// How do we know if we can combine this vertex with its parent? Well, we have some
|
// How do we know if we can combine this vertex with its parent? Well, we have some
|
||||||
// tests that must hold true:
|
// tests that must hold true:
|
||||||
// -There must be only a fallthrough edge to the affected vertex
|
// -There must be only a fallthrough edge to the affected vertex
|
||||||
|
@ -774,7 +781,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
|
|
||||||
private void handleReferenceAdded(DomainObjectChangeRecord record) {
|
private void handleReferenceAdded(DomainObjectChangeRecord record) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the affected vertex (if any). Determine if we have to split the vertex.
|
// Get the affected vertex (if any). Determine if we have to split the vertex.
|
||||||
//
|
//
|
||||||
FGData functionGraphData = controller.getFunctionGraphData();
|
FGData functionGraphData = controller.getFunctionGraphData();
|
||||||
|
@ -786,10 +793,10 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return; // this particular removal doesn't affect our graph
|
return; // this particular removal doesn't affect our graph
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// How do we know if we need to split this vertex? Well, we have some
|
// How do we know if we need to split this vertex? Well, we have some
|
||||||
// tests that must hold true:
|
// tests that must hold true:
|
||||||
// -The 'to' address for the reference must not be to the minimum address for that vertex
|
// -The 'to' address for the reference must not be to the minimum address for that vertex
|
||||||
//
|
//
|
||||||
AddressSetView addresses = destinationVertex.getAddresses();
|
AddressSetView addresses = destinationVertex.getAddresses();
|
||||||
Address minAddress = addresses.getMinAddress();
|
Address minAddress = addresses.getMinAddress();
|
||||||
|
@ -824,7 +831,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSymbolRemoved(DomainObjectChangeRecord record) {
|
private void handleSymbolRemoved(DomainObjectChangeRecord record) {
|
||||||
//
|
//
|
||||||
// Get the affected vertex (if any). Determine if we have to combine the vertex with
|
// Get the affected vertex (if any). Determine if we have to combine the vertex with
|
||||||
// the vertex below it (adding a symbol creates a new basic block, which creates a new
|
// the vertex below it (adding a symbol creates a new basic block, which creates a new
|
||||||
// vertex--we may need to reverse that process)
|
// vertex--we may need to reverse that process)
|
||||||
|
@ -837,13 +844,13 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return; // this particular removal doesn't affect our graph
|
return; // this particular removal doesn't affect our graph
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// How do we know if we can combine this vertex with its parent? Well, we have some
|
// How do we know if we can combine this vertex with its parent? Well, we have some
|
||||||
// tests that must hold true:
|
// tests that must hold true:
|
||||||
// -There must be only a fallthrough edge to the affected vertex
|
// -There must be only a fallthrough edge to the affected vertex
|
||||||
// -The parent vertex must have only one flow--FallThrough
|
// -The parent vertex must have only one flow--FallThrough
|
||||||
// -There must not be any other references to the entry of the vertex
|
// -There must not be any other references to the entry of the vertex
|
||||||
// -There must not be any non-dynamic labels on the vertex
|
// -There must not be any non-dynamic labels on the vertex
|
||||||
//
|
//
|
||||||
Graph<FGVertex, FGEdge> graph = functionGraph;
|
Graph<FGVertex, FGEdge> graph = functionGraph;
|
||||||
Collection<FGEdge> inEdgesForDestination = graph.getInEdges(destinationVertex);
|
Collection<FGEdge> inEdgesForDestination = graph.getInEdges(destinationVertex);
|
||||||
|
@ -895,7 +902,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSymbolAdded(DomainObjectChangeRecord record) {
|
private void handleSymbolAdded(DomainObjectChangeRecord record) {
|
||||||
//
|
//
|
||||||
// Get the affected vertex (if any). Determine if we have to split the vertex.
|
// Get the affected vertex (if any). Determine if we have to split the vertex.
|
||||||
//
|
//
|
||||||
FGData functionGraphData = controller.getFunctionGraphData();
|
FGData functionGraphData = controller.getFunctionGraphData();
|
||||||
|
@ -906,10 +913,10 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return; // this particular removal doesn't affect our graph
|
return; // this particular removal doesn't affect our graph
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// How do we know if we need to split this vertex? Well, we have some
|
// How do we know if we need to split this vertex? Well, we have some
|
||||||
// tests that must hold true:
|
// tests that must hold true:
|
||||||
// -The address for the symbol must not be to the minimum address for that vertex
|
// -The address for the symbol must not be to the minimum address for that vertex
|
||||||
//
|
//
|
||||||
AddressSetView addresses = destinationVertex.getAddresses();
|
AddressSetView addresses = destinationVertex.getAddresses();
|
||||||
Address minAddress = addresses.getMinAddress();
|
Address minAddress = addresses.getMinAddress();
|
||||||
|
@ -1155,7 +1162,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to limit the selections we return here to that which is inside of our
|
// we want to limit the selections we return here to that which is inside of our
|
||||||
// graph (the current selection of this provider is that for the entire program)
|
// graph (the current selection of this provider is that for the entire program)
|
||||||
Function function = currentData.getFunction();
|
Function function = currentData.getFunction();
|
||||||
AddressSetView functionBody = function.getBody();
|
AddressSetView functionBody = function.getBody();
|
||||||
|
@ -1174,7 +1181,7 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to limit the selections we return here to that which is inside of our
|
// we want to limit the selections we return here to that which is inside of our
|
||||||
// graph (the current selection of this provider is that for the entire program)
|
// graph (the current selection of this provider is that for the entire program)
|
||||||
Function function = currentData.getFunction();
|
Function function = currentData.getFunction();
|
||||||
AddressSetView functionBody = function.getBody();
|
AddressSetView functionBody = function.getBody();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue