mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-1679 - Consolidated navigation buttons and added an action to invert the search
This commit is contained in:
parent
0f3aa2b9de
commit
ae37ca2e27
24 changed files with 1804 additions and 1492 deletions
|
@ -940,6 +940,7 @@ src/main/resources/images/Program.gif||GHIDRA||||END|
|
|||
src/main/resources/images/ThunkFunction.gif||GHIDRA||||END|
|
||||
src/main/resources/images/U.gif||GHIDRA||||END|
|
||||
src/main/resources/images/Unpackage.gif||GHIDRA||||END|
|
||||
src/main/resources/images/V.png||GHIDRA||||END|
|
||||
src/main/resources/images/VCRFastForward.gif||GHIDRA||||END|
|
||||
src/main/resources/images/V_slash.png||GHIDRA||||END|
|
||||
src/main/resources/images/View.gif||GHIDRA||||END|
|
||||
|
|
|
@ -416,12 +416,27 @@
|
|||
temporarily invert the direction of the search.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Invert_Search_Logic"></A>Invert Search Logic</H3>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>The <IMG src="images/dialog-cancel.png" alt="down_arrow" border="0"> icon indicates the
|
||||
search logic will be inverted / negated. The exact meaning of this depends upon the type
|
||||
of search performed, as described below.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
<H3><A name="Next_Instruction"></A>Navigate to Instruction</H3>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>To move the cursor to the next instruction click on the Navigate by Instruction icon,
|
||||
<IMG src="images/I.gif" alt="I" border="0">. This icon is disabled when no more
|
||||
instructions exist in the current search direction.</P>
|
||||
|
||||
<P>When inverted, this task, if on an instruction, will attempt to navigate to
|
||||
the next data or undefined data. If not on an instruction, then this task
|
||||
will find the next instruction and then find the data or undefined data after that.
|
||||
</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Data"></A>Navigate to Data</H3>
|
||||
|
@ -430,6 +445,12 @@
|
|||
<P>To move the cursor to the next data code unit, click on the Navigate by Data icon, <IMG
|
||||
src="images/D.gif" alt="D" border="0">. This icon is disabled when no more data code units
|
||||
exist in the current search direction.</P>
|
||||
|
||||
<P>When inverted, this task, if on a data code unit, will attempt to navigate to
|
||||
the next instruction or undefined data. If not on a data, then this task
|
||||
will find the next defined data and then find the instruction or undefined data after that.
|
||||
</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Undefined"></A>Navigate to Undefined</H3>
|
||||
|
@ -438,14 +459,25 @@
|
|||
<P>To move the cursor to the next undefined code unit, click on the Navigate by Data icon,
|
||||
<IMG src="images/U.gif" alt="U" border="0">. This icon is disabled when no more undefined
|
||||
code units exist in the current search direction.</P>
|
||||
|
||||
<P>When inverted, this task, if on an undefined code unit, will attempt to navigate to
|
||||
the next instruction or data. If not on an undefined, then this task
|
||||
will find the next undefined and then find the instruction or data after that.
|
||||
</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Label"></A>Navigate to Label</H3>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>To move the cursor to the next Label, click on the Navigate by Label icon,
|
||||
<IMG src="images/L.gif" alt="L" border="0">. This icon is disabled when no more labels
|
||||
exist in the current search direction.</P>
|
||||
<IMG src="images/L.gif" alt="L" border="0">.</P>
|
||||
|
||||
<P>When inverted, this task, if on an address with a label, will attempt to navigate to
|
||||
the next code unit without a label. If not on an address with a label, then this task
|
||||
will find the next label and then find the next code unit after that without a label.
|
||||
</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Function"></A>Navigate to Function</H3>
|
||||
|
@ -455,37 +487,49 @@
|
|||
next function in the current direction. If inside a function and the direction is towards
|
||||
lower addresses, then this action will go to the current function's entry point.</P>
|
||||
|
||||
<P>When inverted, this task (<IMG src="images/notF.gif" alt="F">) will attempt to
|
||||
the navigate to the next instruction block not contained in a function.
|
||||
This can be useful when manually creating functions and
|
||||
stepping over them to identify potential function candidates.</P>
|
||||
</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Non_Function"></A>Navigate to Non-Function</H3>
|
||||
|
||||
<H3><A name="Next_Matching_Byte_Values"></A>Navigate to Matching Byte Values</H3>
|
||||
|
||||
<P style="margin-left: 40px;">This task (<IMG src="images/notF.gif" alt="F">) will attempt to
|
||||
the navigate to the next instruction block not contained in a function.
|
||||
This can be useful when manually creating functions and
|
||||
stepping over them to identify potential function candidates. </P>
|
||||
<BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Different_Byte_Value"></A>Navigate to Different Byte Value</H3>
|
||||
<P>This task (<IMG src="images/V.png" alt="V">) will attempt to navigate to the next matching
|
||||
byte pattern of the code unit under the cursor.
|
||||
</P>
|
||||
|
||||
|
||||
<P style="margin-left: 40px;">This task (<IMG src="images/V_slash.png" alt="V">) will attempt to
|
||||
<P>When inverted, this task will attempt to
|
||||
the navigate to the first code-unit where the byte value is different from the byte value
|
||||
of the first byte of the current code unit. This can be useful when trying to navigate
|
||||
past a series of 0s or FFs;</P>
|
||||
of the first byte of the current code unit. This can be useful when trying to navigate
|
||||
past a series of 0s or FFs</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Next_Bookmark"></A>Navigate to Bookmark</H3>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<P>To move the cursor to the next bookmark, click on the Navigate by Bookmark icon,
|
||||
<IMG src="images/B.gif" alt="B" border="0">. This icon is disabled when no more bookmarks
|
||||
exist in the current search direction. You may use the pull-down menu to choose a specific
|
||||
type of bookmark (<IMG src="images/applications-system.png" alt="B" border="0">,
|
||||
<IMG src="images/B.gif" alt="B" border="0">. You may use the pull-down menu to choose a
|
||||
specific type of bookmark (<IMG src="images/applications-system.png" alt="B" border="0">,
|
||||
<IMG src="images/edit-delete.png" alt="B" border="0">,
|
||||
<IMG src="images/information.png" alt="B" border="0">,
|
||||
<IMG src="images/notes.gif" alt="B" border="0">,
|
||||
<IMG src="images/warning.png" alt="B" border="0">,
|
||||
<IMG src="images/unknown.gif" alt="B" border="0">)
|
||||
to navigate to as opposed to all types. </P>
|
||||
|
||||
<P>When inverted, this task will attempt to navigate to then next address with a bookmark
|
||||
different than what is selected in the pull-down menu of the icon. If the 'all bookmarks'
|
||||
state is selected, then this task will simply navigate to the next address that has no
|
||||
bookmark.
|
||||
</P>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import javax.swing.KeyStroke;
|
|||
import docking.action.KeyBindingData;
|
||||
import docking.action.ToolBarData;
|
||||
import docking.tool.ToolConstants;
|
||||
import generic.util.image.ImageUtils;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.context.NavigatableContextAction;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
|
@ -36,12 +37,19 @@ import ghidra.util.HelpLocation;
|
|||
import ghidra.util.Swing;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.*;
|
||||
import resources.*;
|
||||
|
||||
public abstract class AbstractNextPreviousAction extends NavigatableContextAction {
|
||||
|
||||
private static final Icon INVERTED_OVERLAY_ICON =
|
||||
ImageUtils.makeTransparent(ResourceManager.loadImage("images/dialog-cancel.png"), .5f);
|
||||
|
||||
private boolean isForward = true;
|
||||
private PluginTool tool;
|
||||
|
||||
protected boolean isInverted;
|
||||
private Icon invertedIcon;
|
||||
|
||||
public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) {
|
||||
super(name, owner);
|
||||
this.tool = tool;
|
||||
|
@ -55,6 +63,16 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
|
|||
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name));
|
||||
setDescription(getDescriptionString());
|
||||
addToWindowWhen(NavigatableActionContext.class);
|
||||
|
||||
MultiIconBuilder builder = new MultiIconBuilder(getIcon());
|
||||
builder.addIcon(INVERTED_OVERLAY_ICON, 10, 10, QUADRANT.LR);
|
||||
invertedIcon = builder.build();
|
||||
}
|
||||
|
||||
protected void setInverted(boolean isInverted) {
|
||||
this.isInverted = isInverted;
|
||||
getToolBarData().setIcon(isInverted ? invertedIcon : getIcon());
|
||||
setDescription(getDescriptionString());
|
||||
}
|
||||
|
||||
protected abstract Icon getIcon();
|
||||
|
@ -63,13 +81,13 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
|
|||
|
||||
@Override
|
||||
public void actionPerformed(final NavigatableActionContext context) {
|
||||
Task t = new Task("Searching for " + getNavigationTypeName() + "...", true, false, true) {
|
||||
Task t = new Task("Searching for " + doGetNavigationTypeName(), true, false, true) {
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) {
|
||||
gotoNextPrevious(monitor, context);
|
||||
}
|
||||
};
|
||||
new TaskLauncher(t, tool.getToolFrame(), 500);
|
||||
new TaskLauncher(t);
|
||||
}
|
||||
|
||||
void gotoNextPrevious(TaskMonitor monitor, final NavigatableActionContext context) {
|
||||
|
@ -93,7 +111,7 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
|
|||
|
||||
private void gotoAddress(NavigatableActionContext actionContext, Address address) {
|
||||
if (address == null) {
|
||||
tool.setStatusInfo("Unable to locate another \"" + getNavigationTypeName() +
|
||||
tool.setStatusInfo("Unable to locate another \"" + doGetNavigationTypeName() +
|
||||
"\" past the current range, in the current direction.");
|
||||
return;
|
||||
}
|
||||
|
@ -119,14 +137,26 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
|
|||
|
||||
private String getDescriptionString() {
|
||||
String prefix = isForward ? "Go To Next " : "Go To Previous ";
|
||||
return prefix + getNavigationTypeName() + " (shift-click inverts direction)";
|
||||
return prefix + doGetNavigationTypeName() + " (shift-click inverts direction)";
|
||||
}
|
||||
|
||||
private String doGetNavigationTypeName() {
|
||||
if (isInverted) {
|
||||
return getInvertedNavigationTypeName();
|
||||
}
|
||||
return getNavigationTypeName();
|
||||
}
|
||||
|
||||
abstract protected String getNavigationTypeName();
|
||||
|
||||
protected String getInvertedNavigationTypeName() {
|
||||
return "Non-" + getNavigationTypeName();
|
||||
}
|
||||
|
||||
abstract protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException;
|
||||
|
||||
abstract protected Address getPreviousAddress(TaskMonitor monitor, Program program,
|
||||
Address address) throws CancelledException;
|
||||
|
||||
}
|
||||
|
|
|
@ -20,8 +20,10 @@ import java.awt.event.KeyEvent;
|
|||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import generic.util.image.ImageUtils;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.context.NavigatableContextAction;
|
||||
|
@ -58,14 +60,14 @@ import resources.ResourceManager;
|
|||
//@formatter:on
|
||||
public class NextPrevCodeUnitPlugin extends Plugin {
|
||||
private DockingAction toggleDirectionAction;
|
||||
private InvertStateAction invertStateAction;
|
||||
private AbstractNextPreviousAction instructionAction;
|
||||
private AbstractNextPreviousAction dataAction;
|
||||
private AbstractNextPreviousAction undefinedAction;
|
||||
private AbstractNextPreviousAction functionAction;
|
||||
private AbstractNextPreviousAction nonFunctionAction;
|
||||
private AbstractNextPreviousAction labelAction;
|
||||
private NextPreviousBookmarkAction bookmarkAction;
|
||||
private NextPreviousDifferentByteAction differentValueAction;
|
||||
private NextPreviousSameBytesAction sameValueAction;
|
||||
|
||||
public NextPrevCodeUnitPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
|
@ -73,60 +75,107 @@ public class NextPrevCodeUnitPlugin extends Plugin {
|
|||
}
|
||||
|
||||
private void createActions() {
|
||||
// use this index to make sure that the following actions are ordered in the way that
|
||||
// they are inserted
|
||||
int subGroupIndex = 0;
|
||||
// use this index to ensure the actions are ordered in the way that they are inserted
|
||||
char subGroupChar = 'a';
|
||||
|
||||
toggleDirectionAction = new ToggleDirectionAction("" + subGroupIndex++);
|
||||
toggleDirectionAction = new ToggleDirectionAction(String.valueOf(subGroupChar++));
|
||||
tool.addAction(toggleDirectionAction);
|
||||
|
||||
invertStateAction = new InvertStateAction(String.valueOf(subGroupChar++));
|
||||
tool.addAction(invertStateAction);
|
||||
|
||||
instructionAction =
|
||||
new NextPreviousInstructionAction(tool, getName(), "" + subGroupIndex++);
|
||||
new NextPreviousInstructionAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(instructionAction);
|
||||
|
||||
dataAction = new NextPreviousDefinedDataAction(tool, getName(), "" + subGroupIndex++);
|
||||
dataAction =
|
||||
new NextPreviousDefinedDataAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(dataAction);
|
||||
|
||||
undefinedAction = new NextPreviousUndefinedAction(tool, getName(), "" + subGroupIndex++);
|
||||
undefinedAction =
|
||||
new NextPreviousUndefinedAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(undefinedAction);
|
||||
|
||||
labelAction = new NextPreviousLabelAction(tool, getName(), "" + subGroupIndex++);
|
||||
labelAction = new NextPreviousLabelAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(labelAction);
|
||||
|
||||
functionAction = new NextPreviousFunctionAction(tool, getName(), "" + subGroupIndex++);
|
||||
functionAction =
|
||||
new NextPreviousFunctionAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(functionAction);
|
||||
|
||||
nonFunctionAction =
|
||||
new NextPreviousNonFunctionAction(tool, getName(), "" + subGroupIndex++);
|
||||
tool.addAction(nonFunctionAction);
|
||||
sameValueAction =
|
||||
new NextPreviousSameBytesAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(sameValueAction);
|
||||
|
||||
differentValueAction =
|
||||
new NextPreviousDifferentByteAction(tool, getName(), "" + subGroupIndex++);
|
||||
tool.addAction(differentValueAction);
|
||||
|
||||
bookmarkAction = new NextPreviousBookmarkAction(tool, getName(), "" + subGroupIndex++);
|
||||
bookmarkAction =
|
||||
new NextPreviousBookmarkAction(tool, getName(), String.valueOf(subGroupChar++));
|
||||
tool.addAction(bookmarkAction);
|
||||
}
|
||||
|
||||
private void updateActions(boolean searchForward) {
|
||||
private void updateActionsDirection(boolean searchForward) {
|
||||
instructionAction.setDirection(searchForward);
|
||||
dataAction.setDirection(searchForward);
|
||||
undefinedAction.setDirection(searchForward);
|
||||
functionAction.setDirection(searchForward);
|
||||
nonFunctionAction.setDirection(searchForward);
|
||||
labelAction.setDirection(searchForward);
|
||||
differentValueAction.setDirection(searchForward);
|
||||
sameValueAction.setDirection(searchForward);
|
||||
bookmarkAction.setDirection(searchForward);
|
||||
}
|
||||
|
||||
private void updatedActionsLogic(boolean isInverted) {
|
||||
instructionAction.setInverted(isInverted);
|
||||
dataAction.setInverted(isInverted);
|
||||
undefinedAction.setInverted(isInverted);
|
||||
functionAction.setInverted(isInverted);
|
||||
labelAction.setInverted(isInverted);
|
||||
sameValueAction.setInverted(isInverted);
|
||||
bookmarkAction.setInverted(isInverted);
|
||||
}
|
||||
|
||||
private class InvertStateAction extends ToggleDockingAction {
|
||||
|
||||
private final Icon INVERTED_ICON_OFF = ImageUtils.makeTransparent(
|
||||
ResourceManager.loadImage("images/dialog-cancel.png"));
|
||||
private final Icon INVERTED_ICON_ON = ImageUtils.makeTransparent(
|
||||
ResourceManager.loadImage("images/dialog-cancel.png"), .8f);
|
||||
private boolean isInverted = false;
|
||||
|
||||
public InvertStateAction(String subGroup) {
|
||||
super("Invert Search Logic", NextPrevCodeUnitPlugin.this.getName());
|
||||
|
||||
setToolBarData(new ToolBarData(INVERTED_ICON_OFF,
|
||||
ToolConstants.TOOLBAR_GROUP_FOUR, subGroup));
|
||||
|
||||
// TODO add help entry
|
||||
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName()));
|
||||
|
||||
// TODO setDescriptoin("...");
|
||||
setSelected(false);
|
||||
|
||||
addToWindowWhen(NavigatableActionContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean isSelected) {
|
||||
super.setSelected(isSelected);
|
||||
getToolBarData().setIcon(isSelected ? INVERTED_ICON_ON : INVERTED_ICON_OFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
isInverted = isSelected();
|
||||
updatedActionsLogic(isInverted);
|
||||
}
|
||||
}
|
||||
|
||||
private class ToggleDirectionAction extends NavigatableContextAction {
|
||||
Icon forwardIcon = ResourceManager.loadImage("images/down.png");
|
||||
Icon backwardIcon = ResourceManager.loadImage("images/up.png");
|
||||
private final Icon FORWARD_ICON = ResourceManager.loadImage("images/down.png");
|
||||
private final Icon BACKWARD_ICON = ResourceManager.loadImage("images/up.png");
|
||||
private boolean isForward = true;
|
||||
|
||||
ToggleDirectionAction(String subGroup) {
|
||||
super("Toggle Search Direction", NextPrevCodeUnitPlugin.this.getName());
|
||||
setToolBarData(new ToolBarData(forwardIcon,
|
||||
setToolBarData(new ToolBarData(FORWARD_ICON,
|
||||
ToolConstants.TOOLBAR_GROUP_FOUR, subGroup));
|
||||
setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK |
|
||||
InputEvent.ALT_DOWN_MASK));
|
||||
|
@ -136,14 +185,13 @@ public class NextPrevCodeUnitPlugin extends Plugin {
|
|||
new HelpLocation(HelpTopics.NAVIGATION, longName));
|
||||
setDescription(longName);
|
||||
addToWindowWhen(NavigatableActionContext.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(NavigatableActionContext context) {
|
||||
isForward = !isForward;
|
||||
getToolBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
||||
updateActions(isForward);
|
||||
getToolBarData().setIcon(isForward ? FORWARD_ICON : BACKWARD_ICON);
|
||||
updateActionsDirection(isForward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ package ghidra.app.plugin.core.navigation;
|
|||
import java.awt.event.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
|
@ -27,6 +26,7 @@ import docking.menu.ActionState;
|
|||
import docking.menu.MultiStateDockingAction;
|
||||
import docking.tool.ToolConstants;
|
||||
import docking.widgets.EventTrigger;
|
||||
import generic.util.image.ImageUtils;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
|
@ -38,29 +38,42 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Swing;
|
||||
import resources.ResourceManager;
|
||||
import resources.*;
|
||||
|
||||
public class NextPreviousBookmarkAction extends MultiStateDockingAction<String> {
|
||||
private boolean isForward = true;
|
||||
private PluginTool tool;
|
||||
|
||||
private static ImageIcon bookmarkIcon = ResourceManager.loadImage("images/B.gif");
|
||||
private static ImageIcon bookmarkAnalysisIcon =
|
||||
public static final String ALL_BOOKMARK_TYPES = "All Bookmark Types";
|
||||
|
||||
private static final Icon INVERTED_OVERLAY_ICON =
|
||||
ImageUtils.makeTransparent(ResourceManager.loadImage("images/dialog-cancel.png"), .5f);
|
||||
|
||||
private PluginTool tool;
|
||||
private boolean isForward = true;
|
||||
private boolean isInverted;
|
||||
|
||||
private static final ImageIcon BOOKMARK_ICON = ResourceManager.getScaledIcon(
|
||||
ResourceManager.loadImage("images/B.gif"), 16, 16);
|
||||
private static final ImageIcon BOOKMARK_ANALYSIS_ICON =
|
||||
ResourceManager.loadImage("images/applications-system.png");
|
||||
private static ImageIcon bookmarkErrorIcon =
|
||||
private static final ImageIcon BOOKMARK_ERROR_ICON =
|
||||
ResourceManager.loadImage("images/edit-delete.png");
|
||||
private static ImageIcon bookmarkInfoIcon = ResourceManager.loadImage("images/information.png");
|
||||
private static ImageIcon bookmarkNoteIcon = ResourceManager.loadImage("images/notes.gif");
|
||||
private static ImageIcon bookmarkWarningIcon = ResourceManager.loadImage("images/warning.png");
|
||||
private static ImageIcon bookmarkUnknownIcon = ResourceManager.loadImage("images/unknown.gif");
|
||||
private static final ImageIcon BOOKMARK_INFO_ICON =
|
||||
ResourceManager.loadImage("images/information.png");
|
||||
private static final ImageIcon BOOKMARK_NOTE_ICON =
|
||||
ResourceManager.loadImage("images/notes.gif");
|
||||
private static final ImageIcon BOOKMARK_WARNING_ICON =
|
||||
ResourceManager.loadImage("images/warning.png");
|
||||
private static final ImageIcon BOOKMARK_UNKNOWN_ICON =
|
||||
ResourceManager.loadImage("images/unknown.gif");
|
||||
|
||||
public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {
|
||||
super("Next Bookmark", owner);
|
||||
this.tool = tool;
|
||||
|
||||
setSupportsDefaultToolContext(true);
|
||||
|
||||
ToolBarData toolBarData =
|
||||
new ToolBarData(bookmarkIcon, ToolConstants.TOOLBAR_GROUP_FOUR);
|
||||
new ToolBarData(BOOKMARK_ICON, ToolConstants.TOOLBAR_GROUP_FOUR);
|
||||
toolBarData.setToolBarSubGroup(subGroup);
|
||||
setToolBarData(toolBarData);
|
||||
|
||||
|
@ -71,16 +84,16 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
setDescription("Set bookmark options");
|
||||
|
||||
ActionState<String> allBookmarks =
|
||||
new ActionState<>("All Types", bookmarkIcon, BookmarkType.ALL_TYPES);
|
||||
new ActionState<>("All Types", BOOKMARK_ICON, ALL_BOOKMARK_TYPES);
|
||||
ActionState<String> analysis =
|
||||
new ActionState<>("Analysis", bookmarkAnalysisIcon, BookmarkType.ANALYSIS);
|
||||
new ActionState<>("Analysis", BOOKMARK_ANALYSIS_ICON, BookmarkType.ANALYSIS);
|
||||
ActionState<String> error =
|
||||
new ActionState<>("Error", bookmarkErrorIcon, BookmarkType.ERROR);
|
||||
ActionState<String> info = new ActionState<>("Info", bookmarkInfoIcon, BookmarkType.INFO);
|
||||
ActionState<String> note = new ActionState<>("Note", bookmarkNoteIcon, BookmarkType.NOTE);
|
||||
new ActionState<>("Error", BOOKMARK_ERROR_ICON, BookmarkType.ERROR);
|
||||
ActionState<String> info = new ActionState<>("Info", BOOKMARK_INFO_ICON, BookmarkType.INFO);
|
||||
ActionState<String> note = new ActionState<>("Note", BOOKMARK_NOTE_ICON, BookmarkType.NOTE);
|
||||
ActionState<String> warning =
|
||||
new ActionState<>("Warning", bookmarkWarningIcon, BookmarkType.WARNING);
|
||||
ActionState<String> custom = new ActionState<>("Custom", bookmarkUnknownIcon, "Custom");
|
||||
new ActionState<>("Warning", BOOKMARK_WARNING_ICON, BookmarkType.WARNING);
|
||||
ActionState<String> custom = new ActionState<>("Custom", BOOKMARK_UNKNOWN_ICON, "Custom");
|
||||
|
||||
addActionState(allBookmarks);
|
||||
addActionState(analysis);
|
||||
|
@ -110,19 +123,122 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
|
||||
@Override
|
||||
public void actionStateChanged(ActionState<String> newActionState, EventTrigger trigger) {
|
||||
// nothing
|
||||
|
||||
Icon icon = newActionState.getIcon();
|
||||
ToolBarData tbData = getToolBarData();
|
||||
tbData.setIcon(isInverted ? invertIcon(icon) : icon);
|
||||
}
|
||||
|
||||
// Find the beginning of the next instruction range
|
||||
private Address getNextAddress(Program program, Address address, String bookmarkType) {
|
||||
Address start = getNextAddressToBeginSearchingForward(program, address);
|
||||
Bookmark nextBookmark = getNextBookmark(program, start, true, bookmarkType);
|
||||
return nextBookmark == null ? null : nextBookmark.getAddress();
|
||||
|
||||
if (isInverted) {
|
||||
return getNextAddressOfNonBookmark(program, address, bookmarkType);
|
||||
}
|
||||
|
||||
return getAddressOfNextBookmarkAfter(program, address, bookmarkType);
|
||||
}
|
||||
|
||||
private Address getPreviousAddress(Program program, Address address, String bookmarkType) {
|
||||
|
||||
if (isInverted) {
|
||||
return getPreviousAddressOfNonBookmark(program, address, bookmarkType);
|
||||
}
|
||||
|
||||
return getAddressOfPreviousBookmarkBefore(program, address, bookmarkType);
|
||||
}
|
||||
|
||||
private Address getNextAddressOfNonBookmark(Program program, Address address,
|
||||
String bookmarkType) {
|
||||
|
||||
if (ALL_BOOKMARK_TYPES.equals(bookmarkType)) {
|
||||
// special case: when 'all types' is negated, then we skip runs of non-bookmarks to
|
||||
// allow users to quickly jump to areas with any bookmarks
|
||||
address = getAddressOfNextBookmarkAfter(program, address, bookmarkType);
|
||||
}
|
||||
|
||||
return getAdddressOfNextPreviousNonBookmark(program, address, bookmarkType, true);
|
||||
}
|
||||
|
||||
private Address getPreviousAddressOfNonBookmark(Program program, Address address,
|
||||
String bookmarkType) {
|
||||
|
||||
if (ALL_BOOKMARK_TYPES.equals(bookmarkType)) {
|
||||
// special case: when 'all types' is negated, then we skip runs of non-bookmarks to
|
||||
// allow users to quickly jump to areas with any bookmarks
|
||||
address = getAddressOfPreviousBookmarkBefore(program, address, bookmarkType);
|
||||
}
|
||||
|
||||
return getAdddressOfNextPreviousNonBookmark(program, address, bookmarkType, false);
|
||||
}
|
||||
|
||||
private Address getAdddressOfNextPreviousNonBookmark(Program program, Address address,
|
||||
String bookmarkType, boolean forward) {
|
||||
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
address = forward ? address.next() : address.previous();
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// By default, if we are given a specific bookmark type, then we need only to find the
|
||||
// next bookmark of a different type. However, if the given type is 'all bookmarks', then
|
||||
// do something reasonable, which is to find the next code unit without a bookmark. Users
|
||||
// are not likely to use this option.
|
||||
//
|
||||
if (bookmarkType.equals(ALL_BOOKMARK_TYPES)) {
|
||||
return getNextPreviousCuWithoutBookmarkAddress(program, address, forward);
|
||||
}
|
||||
|
||||
BookmarkManager bm = program.getBookmarkManager();
|
||||
Iterator<Bookmark> it = bm.getBookmarksIterator(address, forward);
|
||||
while (it.hasNext()) {
|
||||
Bookmark nextBookmark = it.next();
|
||||
Address nextAddress = nextBookmark.getAddress();
|
||||
if (nextAddress.isExternalAddress()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!nextBookmark.getTypeString().equals(bookmarkType)) {
|
||||
return nextBookmark.getAddress();
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Address getNextPreviousCuWithoutBookmarkAddress(Program program, Address address,
|
||||
boolean forward) {
|
||||
|
||||
CodeUnitIterator it = program.getListing().getCodeUnits(address, forward);
|
||||
while (it.hasNext()) {
|
||||
CodeUnit cu = it.next();
|
||||
Address minAddress = cu.getMinAddress();
|
||||
BookmarkManager bm = program.getBookmarkManager();
|
||||
Bookmark[] bookmarks = bm.getBookmarks(minAddress);
|
||||
if (bookmarks.length == 0) {
|
||||
return minAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Address getAddressOfNextBookmarkAfter(Program program, Address address,
|
||||
String bookmarkType) {
|
||||
Address start = getNextAddressToBeginSearchingForward(program, address);
|
||||
Bookmark nextBookmark = getNextPreviousBookmark(program, start, true, bookmarkType);
|
||||
return nextBookmark == null ? null : nextBookmark.getAddress();
|
||||
|
||||
}
|
||||
|
||||
private Address getAddressOfPreviousBookmarkBefore(Program program, Address address,
|
||||
String bookmarkType) {
|
||||
Address start = getNextAddressToBeginSearchingBackward(program, address);
|
||||
Bookmark nextBookmark = getNextBookmark(program, start, false, bookmarkType);
|
||||
Bookmark nextBookmark = getNextPreviousBookmark(program, start, false, bookmarkType);
|
||||
return nextBookmark == null ? null : nextBookmark.getAddress();
|
||||
}
|
||||
|
||||
|
@ -150,19 +266,19 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
return cu;
|
||||
}
|
||||
|
||||
private Bookmark getNextBookmark(Program program, Address address, boolean forward,
|
||||
private Bookmark getNextPreviousBookmark(Program program, Address address, boolean forward,
|
||||
String bookmarkType) {
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
Iterator<Bookmark> bookmarkIterator =
|
||||
bookmarkManager.getBookmarksIterator(address, forward);
|
||||
while (bookmarkIterator.hasNext()) {
|
||||
Bookmark nextBookmark = bookmarkIterator.next();
|
||||
|
||||
BookmarkManager bm = program.getBookmarkManager();
|
||||
Iterator<Bookmark> it = bm.getBookmarksIterator(address, forward);
|
||||
while (it.hasNext()) {
|
||||
Bookmark nextBookmark = it.next();
|
||||
Address nextAddress = nextBookmark.getAddress();
|
||||
if (nextAddress.isExternalAddress()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bookmarkType.equals(BookmarkType.ALL_TYPES)) {
|
||||
if (bookmarkType.equals(ALL_BOOKMARK_TYPES)) {
|
||||
return nextBookmark;
|
||||
}
|
||||
else if (bookmarkType.equals("Custom") &&
|
||||
|
@ -172,13 +288,11 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
else if (nextBookmark.getTypeString().equals(bookmarkType)) {
|
||||
return nextBookmark;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!bookmarkIterator.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return bookmarkIterator.next();
|
||||
}
|
||||
|
||||
private boolean isNotBuiltInType(Address address, Bookmark nextBookmark, Address nextAddress) {
|
||||
return !nextBookmark.getTypeString().equals(BookmarkType.ANALYSIS) &&
|
||||
|
@ -231,10 +345,31 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
setDescription(getToolTipText());
|
||||
}
|
||||
|
||||
public void setInverted(boolean isInverted) {
|
||||
this.isInverted = isInverted;
|
||||
|
||||
ActionState<String> state = getCurrentState();
|
||||
Icon icon = state.getIcon();
|
||||
getToolBarData().setIcon(isInverted ? invertIcon(icon) : icon);
|
||||
setDescription(getToolTipText());
|
||||
}
|
||||
|
||||
private Icon invertIcon(Icon icon) {
|
||||
MultiIconBuilder builder = new MultiIconBuilder(icon);
|
||||
builder.addIcon(INVERTED_OVERLAY_ICON, 10, 10, QUADRANT.LR);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText() {
|
||||
String description = "Go To " + (isForward ? "Next" : "Previous");
|
||||
description += " Bookmark: " + getCurrentState().getName();
|
||||
if (isInverted) {
|
||||
description += " Non-Bookmark: ";
|
||||
}
|
||||
else {
|
||||
description += " Bookmark: ";
|
||||
}
|
||||
description += getCurrentState().getName();
|
||||
description += " (shift-click inverts direction)";
|
||||
return description;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -16,18 +15,17 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.navigation;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
|
||||
|
@ -52,28 +50,49 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
|
|||
InputEvent.ALT_DOWN_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the beginning of the next instruction range
|
||||
*/
|
||||
@Override
|
||||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getNextNonDataAddress(monitor, program, address);
|
||||
}
|
||||
|
||||
if (isDefinedDataAt(program, address)) {
|
||||
// on an instruction, we have to find a non-instruction before finding the next instruction
|
||||
// on a data, find a non-data before finding the next data
|
||||
address = getAddressOfNextPreviousNonDefinedData(monitor, program, address, true);
|
||||
}
|
||||
|
||||
// we know address is not an instruction at this point
|
||||
|
||||
return getAddressOfNextDataAfter(program, address);
|
||||
}
|
||||
|
||||
private Address getNextNonDataAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on a data, find the next instruction or undefined
|
||||
// -if not on a data, find the next data, then find the next instruction or undefined after
|
||||
// that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!isDefinedDataAt(program, address)) {
|
||||
address = getAddressOfNextDataAfter(program, address);
|
||||
}
|
||||
|
||||
return getAddressOfNextPreviousNonDefinedData(monitor, program, address, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getPreviousNonDataAddress(monitor, program, address);
|
||||
}
|
||||
|
||||
if (isDefinedDataAt(program, address)) {
|
||||
// on an instruction, we have to find a non-instruction before finding the previous instruction
|
||||
// on an data, find a non-data before finding the previous data
|
||||
address = getAddressOfNextPreviousNonDefinedData(monitor, program, address, false);
|
||||
}
|
||||
|
||||
|
@ -82,6 +101,22 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
|
|||
return getAddressOfPreviousDataBefore(program, address);
|
||||
}
|
||||
|
||||
private Address getPreviousNonDataAddress(TaskMonitor monitor, Program program,
|
||||
Address address) throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on an data, find the previous instruction or undefined
|
||||
// -if not on a data, find the previous data, then find the previous instruction or
|
||||
// undefined before that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!isDefinedDataAt(program, address)) {
|
||||
address = getAddressOfPreviousDataBefore(program, address);
|
||||
}
|
||||
|
||||
return getAddressOfNextPreviousNonDefinedData(monitor, program, address, false);
|
||||
}
|
||||
|
||||
private boolean isDefinedDataAt(Program program, Address address) {
|
||||
if (address == null) {
|
||||
return false;
|
||||
|
|
|
@ -25,6 +25,7 @@ import ghidra.app.nav.Navigatable;
|
|||
import ghidra.app.services.GoToService;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.util.FunctionSignatureFieldLocation;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
|
@ -53,15 +54,19 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
|
|||
return "Function";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the beginning of the next instruction range
|
||||
* @throws CancelledException
|
||||
*/
|
||||
@Override
|
||||
protected String getInvertedNavigationTypeName() {
|
||||
return "Instruction Not In a Function";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
Function nextFunction = getNextFunction(program, address, true);
|
||||
if (isInverted) {
|
||||
return getNextNonFunctionAddress(monitor, program, address);
|
||||
}
|
||||
Function nextFunction = getNextFunctionNotAtAddress(program, address, true);
|
||||
return nextFunction == null ? null : nextFunction.getEntryPoint();
|
||||
}
|
||||
|
||||
|
@ -69,15 +74,68 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
|
|||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getPreviousNonFunctionAddress(monitor, program, address);
|
||||
}
|
||||
|
||||
Function function = program.getListing().getFunctionContaining(address);
|
||||
if (isInsideFunctionNotAtEntry(function, address)) {
|
||||
return function.getEntryPoint();
|
||||
}
|
||||
|
||||
Function nextFunction = getNextFunction(program, address, false);
|
||||
Function nextFunction = getNextFunctionNotAtAddress(program, address, false);
|
||||
return nextFunction == null ? null : nextFunction.getEntryPoint();
|
||||
}
|
||||
|
||||
private Address getNextNonFunctionAddress(TaskMonitor monitor, Program program,
|
||||
Address address) throws CancelledException {
|
||||
|
||||
Function function = program.getListing().getFunctionContaining(address);
|
||||
if (function == null) {
|
||||
function = getNextFunction(program, address, true);
|
||||
}
|
||||
if (function == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return findNextInstructionAddressNotInFunction(monitor, program, function, true);
|
||||
}
|
||||
|
||||
private Address findNextInstructionAddressNotInFunction(TaskMonitor monitor, Program program,
|
||||
Function startFunction, boolean isForward) throws CancelledException {
|
||||
Function function = startFunction;
|
||||
AddressSetView body = function.getBody();
|
||||
Address address = startFunction.getEntryPoint();
|
||||
InstructionIterator it = program.getListing().getInstructions(address, isForward);
|
||||
while (it.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
Instruction instruction = it.next();
|
||||
Address instructionAddress = instruction.getMinAddress();
|
||||
if (!body.contains(instructionAddress)) {
|
||||
function = program.getListing().getFunctionContaining(instructionAddress);
|
||||
if (function == null) {
|
||||
return instructionAddress;
|
||||
}
|
||||
body = function.getBody();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Address getPreviousNonFunctionAddress(TaskMonitor monitor, Program program,
|
||||
Address address) throws CancelledException {
|
||||
|
||||
Function function = program.getListing().getFunctionContaining(address);
|
||||
if (function == null) {
|
||||
function = getNextFunction(program, address, false);
|
||||
}
|
||||
if (function == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return findNextInstructionAddressNotInFunction(monitor, program, function, false);
|
||||
}
|
||||
|
||||
private boolean isInsideFunctionNotAtEntry(Function function, Address address) {
|
||||
if (function == null) {
|
||||
return false;
|
||||
|
@ -90,6 +148,15 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
|
|||
if (!functionIterator.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return functionIterator.next();
|
||||
}
|
||||
|
||||
private Function getNextFunctionNotAtAddress(Program program, Address address,
|
||||
boolean forward) {
|
||||
FunctionIterator functionIterator = program.getListing().getFunctions(address, forward);
|
||||
if (!functionIterator.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
Function nextFunction = functionIterator.next();
|
||||
if (!nextFunction.getEntryPoint().equals(address)) {
|
||||
return nextFunction;
|
||||
|
@ -102,6 +169,11 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
|
|||
|
||||
@Override
|
||||
protected void gotoAddress(GoToService service, Navigatable navigatable, Address address) {
|
||||
if (isInverted) {
|
||||
service.goTo(navigatable, address);
|
||||
return;
|
||||
}
|
||||
|
||||
Program program = navigatable.getProgram();
|
||||
Function function = program.getListing().getFunctionAt(address);
|
||||
FunctionSignatureFieldLocation location = new FunctionSignatureFieldLocation(program,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -16,18 +15,17 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.navigation;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
|
||||
|
@ -52,21 +50,20 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
|
|||
return "Instruction";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the beginning of the next instruction range
|
||||
* @throws CancelledException
|
||||
*/
|
||||
@Override
|
||||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getNextNonInstructionAddress(monitor, program, address);
|
||||
}
|
||||
|
||||
if (isInstructionAt(program, address)) {
|
||||
// on an instruction, we have to find a non-instruction before finding the next instruction
|
||||
// on an instruction, find a non-instruction before finding the next instruction
|
||||
address = getAddressOfNextPreviousNonInstruction(monitor, program, address, true);
|
||||
}
|
||||
|
||||
// we know address is not an instruction at this point
|
||||
|
||||
return getAddressOfNextInstructionAfter(program, address);
|
||||
}
|
||||
|
||||
|
@ -74,16 +71,51 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
|
|||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getPreviousNonInstructionAddress(monitor, program, address);
|
||||
}
|
||||
|
||||
if (isInstructionAt(program, address)) {
|
||||
// on an instruction, we have to find a non-instruction before finding the previous instruction
|
||||
// on an instruction, find a non-instruction before finding the previous instruction
|
||||
address = getAddressOfNextPreviousNonInstruction(monitor, program, address, false);
|
||||
}
|
||||
|
||||
// we know address is not at an instruction at this point
|
||||
|
||||
return getAddressOfPreviousInstructionBefore(program, address);
|
||||
}
|
||||
|
||||
private Address getNextNonInstructionAddress(TaskMonitor monitor, Program program,
|
||||
Address address) throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on an instruction, find the next data or undefined
|
||||
// -if not on an instruction, find the next instruction, then find the next data or
|
||||
// undefined after that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!isInstructionAt(program, address)) {
|
||||
address = getAddressOfNextInstructionAfter(program, address);
|
||||
}
|
||||
|
||||
return getAddressOfNextPreviousNonInstruction(monitor, program, address, true);
|
||||
}
|
||||
|
||||
private Address getPreviousNonInstructionAddress(TaskMonitor monitor, Program program,
|
||||
Address address) throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on an instruction, find the previous data or undefined
|
||||
// -if not on an instruction, find the previous instruction, then find the previous data or
|
||||
// undefined before that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!isInstructionAt(program, address)) {
|
||||
address = getAddressOfPreviousInstructionBefore(program, address);
|
||||
}
|
||||
|
||||
return getAddressOfNextPreviousNonInstruction(monitor, program, address, false);
|
||||
}
|
||||
|
||||
private boolean isInstructionAt(Program program, Address address) {
|
||||
if (address == null) {
|
||||
return false;
|
||||
|
@ -116,6 +148,10 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
|
|||
private Address getAddressOfNextPreviousNonInstruction(TaskMonitor monitor, Program program,
|
||||
Address address, boolean forward) throws CancelledException {
|
||||
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CodeUnitIterator codeUnits = program.getListing().getCodeUnits(address, forward);
|
||||
while (codeUnits.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -16,21 +15,19 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.navigation;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressIterator;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressIterator;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class NextPreviousLabelAction extends AbstractNextPreviousAction {
|
||||
|
@ -59,6 +56,10 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
|
|||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getNextNonLabel(monitor, program, address);
|
||||
}
|
||||
|
||||
address = getAddressOfNextCodeUnit(program, address);
|
||||
return getAddressOfNextPreviousLabel(program, address, true);
|
||||
}
|
||||
|
@ -67,10 +68,71 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
|
|||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getPreviousNonLabel(monitor, program, address);
|
||||
}
|
||||
|
||||
address = getAddressOfPreviousCodeUnit(program, address);
|
||||
return getAddressOfNextPreviousLabel(program, address, false);
|
||||
}
|
||||
|
||||
private Address getNextNonLabel(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on a label, find the next non-label code unit
|
||||
// -if not on a label, find the next label, then find the next non-label code unit after
|
||||
// that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!hasLabelAt(program, address)) {
|
||||
address = getAddressOfNextPreviousLabel(program, address, true);
|
||||
}
|
||||
|
||||
return getAddressOfNextPreviousNonLabel(monitor, program, address, true);
|
||||
}
|
||||
|
||||
private Address getPreviousNonLabel(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on a label, find the previous non-label code unit
|
||||
// -if not on a label, find the previous label, then find the previous non-label code unit
|
||||
// before that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!hasLabelAt(program, address)) {
|
||||
address = getAddressOfNextPreviousLabel(program, address, false);
|
||||
}
|
||||
|
||||
return getAddressOfNextPreviousNonLabel(monitor, program, address, false);
|
||||
}
|
||||
|
||||
private Address getAddressOfNextPreviousNonLabel(TaskMonitor monitor, Program program,
|
||||
Address address, boolean forward) throws CancelledException {
|
||||
|
||||
if (address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
CodeUnitIterator codeUnits = program.getListing().getCodeUnits(address, forward);
|
||||
while (codeUnits.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
CodeUnit codeUnit = codeUnits.next();
|
||||
Address minAddress = codeUnit.getMinAddress();
|
||||
if (symbolTable.getPrimarySymbol(minAddress) == null) {
|
||||
return minAddress;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasLabelAt(Program program, Address address) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
return symbolTable.getPrimarySymbol(address) != null;
|
||||
}
|
||||
|
||||
private Address getAddressOfNextCodeUnit(Program program, Address address) {
|
||||
CodeUnit cu = program.getListing().getCodeUnitAfter(address);
|
||||
if (cu == null) {
|
||||
|
@ -87,7 +149,8 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
|
|||
return cu.getAddress();
|
||||
}
|
||||
|
||||
private Address getAddressOfNextPreviousLabel(Program program, Address address, boolean forward) {
|
||||
private Address getAddressOfNextPreviousLabel(Program program, Address address,
|
||||
boolean forward) {
|
||||
|
||||
if (address == null) {
|
||||
return null;
|
||||
|
@ -95,7 +158,6 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
|
|||
|
||||
Address nextDefinedLableAddress = getNextDefinedLableAddress(program, address, forward);
|
||||
Address nextReferenceToAddress = getNextReferenceToAddress(program, address, forward);
|
||||
|
||||
if (nextDefinedLableAddress == null) {
|
||||
return nextReferenceToAddress;
|
||||
}
|
||||
|
@ -104,11 +166,9 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
|
|||
}
|
||||
|
||||
int compare = nextDefinedLableAddress.compareTo(nextReferenceToAddress);
|
||||
|
||||
if (forward) {
|
||||
return compare <= 0 ? nextDefinedLableAddress : nextReferenceToAddress;
|
||||
}
|
||||
|
||||
return compare >= 0 ? nextDefinedLableAddress : nextReferenceToAddress;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,122 +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.navigation;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.services.GoToService;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class NextPreviousNonFunctionAction extends AbstractNextPreviousAction {
|
||||
|
||||
public NextPreviousNonFunctionAction(PluginTool tool, String owner, String subGroup) {
|
||||
super(tool, "Next Non-Function", owner, subGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Icon getIcon() {
|
||||
return ResourceManager.loadImage("images/notF.gif");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeyStroke getKeyStroke() {
|
||||
return KeyStroke.getKeyStroke(KeyEvent.VK_N,
|
||||
InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNavigationTypeName() {
|
||||
return "Instruction Not In a Function";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the beginning of the next instruction range
|
||||
* @throws CancelledException
|
||||
*/
|
||||
@Override
|
||||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
Function function = program.getListing().getFunctionContaining(address);
|
||||
if (function == null) {
|
||||
function = getNextFunction(program, address, true);
|
||||
}
|
||||
if (function == null) {
|
||||
return null;
|
||||
}
|
||||
return findNextInstructionAddressNotInFunction(monitor, program, function.getEntryPoint(),
|
||||
true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
Function function = program.getListing().getFunctionContaining(address);
|
||||
if (function == null) {
|
||||
function = getNextFunction(program, address, false);
|
||||
}
|
||||
if (function == null) {
|
||||
return null;
|
||||
}
|
||||
return findNextInstructionAddressNotInFunction(monitor, program, function.getEntryPoint(),
|
||||
false);
|
||||
}
|
||||
|
||||
private Address findNextInstructionAddressNotInFunction(TaskMonitor monitor, Program program,
|
||||
Address address, boolean isForward) throws CancelledException {
|
||||
Function function = program.getListing().getFunctionContaining(address);
|
||||
AddressSetView body = function.getBody();
|
||||
InstructionIterator it = program.getListing().getInstructions(address, isForward);
|
||||
while (it.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
Instruction instruction = it.next();
|
||||
Address instructionAddress = instruction.getMinAddress();
|
||||
if (!body.contains(instructionAddress)) {
|
||||
function = program.getListing().getFunctionContaining(instructionAddress);
|
||||
if (function == null) {
|
||||
return instructionAddress;
|
||||
}
|
||||
body = function.getBody();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Function getNextFunction(Program program, Address address, boolean forward) {
|
||||
FunctionIterator functionIterator = program.getListing().getFunctions(address, forward);
|
||||
if (!functionIterator.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return functionIterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void gotoAddress(GoToService service, Navigatable navigatable, Address address) {
|
||||
service.goTo(navigatable, address);
|
||||
}
|
||||
}
|
|
@ -15,17 +15,6 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.navigation;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Iterator;
|
||||
|
@ -33,22 +22,35 @@ import java.util.Iterator;
|
|||
import javax.swing.Icon;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction {
|
||||
/**
|
||||
* Navigates to the same byte pattern value under the current code unit. When negated, the search
|
||||
* will only consider a single byte, as it seems more useful to be able to skip runs of a
|
||||
* particular byte.
|
||||
*/
|
||||
public class NextPreviousSameBytesAction extends AbstractNextPreviousAction {
|
||||
|
||||
public NextPreviousDifferentByteAction(PluginTool tool, String owner, String subGroup) {
|
||||
super(tool, "Next Different Byte Value", owner, subGroup);
|
||||
}
|
||||
private static final Icon ICON = ResourceManager.loadImage("images/V.png");
|
||||
|
||||
@Override
|
||||
protected String getNavigationTypeName() {
|
||||
return "Different Byte Value";
|
||||
NextPreviousSameBytesAction(PluginTool tool, String owner, String subGroup) {
|
||||
super(tool, "Next Matching Byte Values", owner, subGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Icon getIcon() {
|
||||
return ResourceManager.loadImage("images/V_slash.png");
|
||||
return ICON;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,13 +59,24 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
|
|||
InputEvent.ALT_DOWN_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the beginning of the next instruction range
|
||||
*/
|
||||
@Override
|
||||
protected String getNavigationTypeName() {
|
||||
return "Same Bytes Value";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInvertedNavigationTypeName() {
|
||||
return "Different Bytes Value";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getNextPreviousDifferentByteValueAddress(monitor, program, address, true);
|
||||
}
|
||||
|
||||
return getNextPreviousAddress(monitor, program, address, true);
|
||||
}
|
||||
|
||||
|
@ -71,12 +84,15 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
|
|||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getNextPreviousDifferentByteValueAddress(monitor, program, address, false);
|
||||
}
|
||||
|
||||
return getNextPreviousAddress(monitor, program, address, false);
|
||||
}
|
||||
|
||||
protected Address getNextPreviousAddress(TaskMonitor monitor, Program program, Address address,
|
||||
boolean forward) throws CancelledException {
|
||||
|
||||
private Address getNextPreviousDifferentByteValueAddress(TaskMonitor monitor, Program program,
|
||||
Address address, boolean forward) throws CancelledException {
|
||||
byte value = 0;
|
||||
try {
|
||||
value = program.getMemory().getByte(address);
|
||||
|
@ -114,6 +130,55 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
|
|||
return null;
|
||||
}
|
||||
|
||||
private Address getNextPreviousAddress(TaskMonitor monitor, Program program,
|
||||
Address address, boolean forward) {
|
||||
|
||||
Address startAddress;
|
||||
byte[] bytes;
|
||||
CodeUnit cu = program.getListing().getCodeUnitContaining(address);
|
||||
if (cu != null) {
|
||||
try {
|
||||
bytes = cu.getBytes();
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
Msg.debug(this, "Exception getting code unit bytes at " + cu.getAddress(), e);
|
||||
return null; // not sure if this can happen
|
||||
}
|
||||
|
||||
startAddress = forward ? cu.getMaxAddress().next() : cu.getMinAddress().previous();
|
||||
}
|
||||
else {
|
||||
try {
|
||||
Memory memory = program.getMemory();
|
||||
bytes = new byte[] { memory.getByte(address) };
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
Msg.debug(this, "Exception getting code unit bytes at " + address, e);
|
||||
return null; // not sure if this can happen
|
||||
}
|
||||
|
||||
startAddress = forward ? address.next() : address.previous();
|
||||
}
|
||||
|
||||
return getNextPreviousSameBytes(monitor, program, startAddress, bytes, forward);
|
||||
}
|
||||
|
||||
private Address getNextPreviousSameBytes(TaskMonitor monitor, Program program,
|
||||
Address startAddress, byte[] bytes, boolean forward) {
|
||||
Memory memory = program.getMemory();
|
||||
byte[] mask = null; // null signals to use a full mask
|
||||
AddressSetView addresses = memory.getAllInitializedAddressSet();
|
||||
if (startAddress == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Address endAddress =
|
||||
forward ? addresses.getMaxAddress() : addresses.getMinAddress().previous();
|
||||
Address matchAddress = memory.findBytes(startAddress, endAddress, bytes,
|
||||
mask, forward, monitor);
|
||||
return matchAddress;
|
||||
}
|
||||
|
||||
private CodeUnit getNextPreviousCodeUnit(Program program, Address address, boolean forward) {
|
||||
if (forward) {
|
||||
return program.getListing().getDefinedCodeUnitAfter(address);
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -16,18 +15,17 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.navigation;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
|
||||
public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
|
||||
|
@ -52,21 +50,20 @@ public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
|
|||
return "Undefined";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the beginning of the next instruction range
|
||||
* @throws CancelledException
|
||||
*/
|
||||
@Override
|
||||
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getNextNonUndefined(monitor, program, address);
|
||||
}
|
||||
|
||||
if (isUndefinedAt(program, address)) {
|
||||
// on an undefined, we have to find a defined before finding the next undefined
|
||||
// on an undefined, find a defined before finding the next undefined
|
||||
address = getAddressOfNextDefined(program, address);
|
||||
}
|
||||
|
||||
// we know address is not an instruction at this point
|
||||
|
||||
// we know address is not an undefined at this point
|
||||
return getAddressOfNextPreviousUndefined(monitor, program, address, true);
|
||||
}
|
||||
|
||||
|
@ -74,16 +71,51 @@ public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
|
|||
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
if (isInverted) {
|
||||
return getPreviousNonUndefined(monitor, program, address);
|
||||
}
|
||||
|
||||
if (isUndefinedAt(program, address)) {
|
||||
// on an instruction, we have to find a non-instruction before finding the previous instruction
|
||||
// on an undefined, find a defined before finding the previous undefined
|
||||
address = getAddressOfPreviousDefined(program, address);
|
||||
}
|
||||
|
||||
// we know address is not at an instruction at this point
|
||||
|
||||
// we know address is not at an undefined at this point
|
||||
return getAddressOfNextPreviousUndefined(monitor, program, address, false);
|
||||
}
|
||||
|
||||
private Address getNextNonUndefined(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on an undefined, find the next instruction or data
|
||||
// -if not on an undefined, find the next undefined, then find the next instruction or
|
||||
// undefined after that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!isUndefinedAt(program, address)) {
|
||||
address = getAddressOfNextPreviousUndefined(monitor, program, address, true);
|
||||
}
|
||||
|
||||
return getAddressOfNextDefined(program, address);
|
||||
}
|
||||
|
||||
private Address getPreviousNonUndefined(TaskMonitor monitor, Program program, Address address)
|
||||
throws CancelledException {
|
||||
|
||||
//
|
||||
// Assumptions:
|
||||
// -if on an undefined, find the previous data or instruction
|
||||
// -if not on an undefined, find the previous undefined, then find the previous data or
|
||||
// instruction before that (this mimics the non-inverted case)
|
||||
//
|
||||
if (!isUndefinedAt(program, address)) {
|
||||
address = getAddressOfNextPreviousUndefined(monitor, program, address, false);
|
||||
}
|
||||
|
||||
return getAddressOfPreviousDefined(program, address);
|
||||
}
|
||||
|
||||
private boolean isUndefinedAt(Program program, Address address) {
|
||||
if (address == null) {
|
||||
return false;
|
||||
|
|
BIN
Ghidra/Features/Base/src/main/resources/images/V.png
Normal file
BIN
Ghidra/Features/Base/src/main/resources/images/V.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 483 B |
Binary file not shown.
Before Width: | Height: | Size: 281 B |
|
@ -659,7 +659,9 @@ public class BookmarkPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
|
||||
BookmarkManager bm = program.getBookmarkManager();
|
||||
tx(program, () -> {
|
||||
bm.removeBookmarks(BookmarkType.ALL_TYPES);
|
||||
bm.removeBookmarks("Type1");
|
||||
bm.removeBookmarks("Type2");
|
||||
bm.removeBookmarks("Type3");
|
||||
});
|
||||
|
||||
list = getBookmarks(program.getBookmarkManager());
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -28,24 +27,29 @@ public class TranslateIcon implements Icon {
|
|||
int translateX;
|
||||
int translateY;
|
||||
|
||||
/** Where the translate values are offset from the icon's upper corner */
|
||||
/**
|
||||
* Where the translate values are offset from the icon's upper corner
|
||||
* @param icon the icon
|
||||
* @param translateX the x translation
|
||||
* @param translateY the y translation
|
||||
*/
|
||||
public TranslateIcon(Icon icon, int translateX, int translateY) {
|
||||
this.icon = icon;
|
||||
this.translateX = translateX;
|
||||
this.translateY = translateY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics, int, int)
|
||||
*/
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
icon.paintIcon(c, g, x + translateX, y + translateY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return icon.getIconHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return icon.getIconWidth();
|
||||
}
|
||||
|
|
|
@ -31,12 +31,9 @@ import ghidra.program.model.util.CodeUnitInsertionException;
|
|||
import ghidra.program.model.util.PropertyMap;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
/**
|
||||
* Database implementation of Listing.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ListingDB implements Listing {
|
||||
|
||||
|
@ -45,9 +42,6 @@ class ListingDB implements Listing {
|
|||
private TreeManager treeMgr;
|
||||
private FunctionManager functionMgr;
|
||||
|
||||
/**
|
||||
* Set the program.
|
||||
*/
|
||||
public void setProgram(ProgramDB program) {
|
||||
this.program = program;
|
||||
codeMgr = program.getCodeManager();
|
||||
|
@ -55,261 +49,165 @@ class ListingDB implements Listing {
|
|||
functionMgr = program.getFunctionManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitAt(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit getCodeUnitAt(Address addr) {
|
||||
return codeMgr.getCodeUnitAt(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitContaining(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit getCodeUnitContaining(Address addr) {
|
||||
return codeMgr.getCodeUnitContaining(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitAfter(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit getCodeUnitAfter(Address addr) {
|
||||
return codeMgr.getCodeUnitAfter(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitBefore(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit getCodeUnitBefore(Address addr) {
|
||||
return codeMgr.getCodeUnitBefore(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitIterator(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCodeUnitIterator(String property, boolean forward) {
|
||||
return codeMgr.getCodeUnitIterator(property, program.getMinAddress(), forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitIterator(java.lang.String, ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCodeUnitIterator(String property, Address addr, boolean forward) {
|
||||
return codeMgr.getCodeUnitIterator(property, addr, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnitIterator(java.lang.String, ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCodeUnitIterator(String property, AddressSetView addrSet,
|
||||
boolean forward) {
|
||||
return codeMgr.getCodeUnitIterator(property, addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnits()
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCodeUnits(boolean forward) {
|
||||
return codeMgr.getCodeUnits(program.getMemory(), forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnits(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCodeUnits(Address addr, boolean forward) {
|
||||
return codeMgr.getCodeUnits(addr, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCodeUnits(ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCodeUnits(AddressSetView addrSet, boolean forward) {
|
||||
return codeMgr.getCodeUnits(addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructionAt(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Instruction getInstructionAt(Address addr) {
|
||||
return codeMgr.getInstructionAt(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructionContaining(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Instruction getInstructionContaining(Address addr) {
|
||||
return codeMgr.getInstructionContaining(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructionAfter(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Instruction getInstructionAfter(Address addr) {
|
||||
return codeMgr.getInstructionAfter(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructionBefore(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Instruction getInstructionBefore(Address addr) {
|
||||
return codeMgr.getInstructionBefore(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructions()
|
||||
*/
|
||||
@Override
|
||||
public InstructionIterator getInstructions(boolean forward) {
|
||||
return codeMgr.getInstructions(forward ? program.getMinAddress() : program.getMaxAddress(),
|
||||
forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructions(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public InstructionIterator getInstructions(Address addr, boolean forward) {
|
||||
return codeMgr.getInstructions(addr, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getInstructions(ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public InstructionIterator getInstructions(AddressSetView addrSet, boolean forward) {
|
||||
return codeMgr.getInstructions(addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDataAt(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDataAt(Address addr) {
|
||||
return codeMgr.getDataAt(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDataContaining(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDataContaining(Address addr) {
|
||||
return codeMgr.getDataContaining(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDataAfter(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDataAfter(Address addr) {
|
||||
return codeMgr.getDataAfter(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDataBefore(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDataBefore(Address addr) {
|
||||
return codeMgr.getDataBefore(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getData()
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getData(boolean forward) {
|
||||
return codeMgr.getData(forward ? program.getMinAddress() : program.getMaxAddress(),
|
||||
forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getData(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getData(Address addr, boolean forward) {
|
||||
return codeMgr.getData(addr, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getData(ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getData(AddressSetView addrSet, boolean forward) {
|
||||
return codeMgr.getData(addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedDataAt(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDefinedDataAt(Address addr) {
|
||||
return codeMgr.getDefinedDataAt(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedDataContaining(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDefinedDataContaining(Address addr) {
|
||||
return codeMgr.getDefinedDataContaining(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedDataAfter(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDefinedDataAfter(Address addr) {
|
||||
return codeMgr.getDefinedDataAfter(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedDataBefore(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getDefinedDataBefore(Address addr) {
|
||||
return codeMgr.getDefinedDataBefore(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedData()
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getDefinedData(boolean forward) {
|
||||
return codeMgr.getDefinedData(forward ? program.getMinAddress() : program.getMaxAddress(),
|
||||
forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedData(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getDefinedData(Address addr, boolean forward) {
|
||||
return codeMgr.getDefinedData(addr, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedData(ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getDefinedData(AddressSetView addrSet, boolean forward) {
|
||||
return codeMgr.getDefinedData(addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getUndefinedDataAt(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getUndefinedDataAt(Address addr) {
|
||||
return codeMgr.getUndefinedAt(addr);
|
||||
|
@ -321,295 +219,190 @@ class ListingDB implements Listing {
|
|||
return codeMgr.getUndefinedRanges(set, initializedMemoryOnly, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getUndefinedDataAfter(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getUndefinedDataAfter(Address addr, TaskMonitor monitor) {
|
||||
return codeMgr.getFirstUndefinedDataAfter(addr, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFirstUndefinedData(ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public Data getFirstUndefinedData(AddressSetView set, TaskMonitor monitor) {
|
||||
return codeMgr.getFirstUndefinedData(set, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getUndefinedDataBefore(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Data getUndefinedDataBefore(Address addr, TaskMonitor monitor) {
|
||||
return codeMgr.getFirstUndefinedDataBefore(addr, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCompositeData()
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getCompositeData(boolean forward) {
|
||||
return codeMgr.getCompositeData(forward ? program.getMinAddress() : program.getMaxAddress(),
|
||||
forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCompositeData(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getCompositeData(Address start, boolean forward) {
|
||||
return codeMgr.getCompositeData(start, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCompositeData(ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) {
|
||||
return codeMgr.getCompositeData(addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getUserDefinedProperties()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<String> getUserDefinedProperties() {
|
||||
return codeMgr.getUserDefinedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#removeUserDefinedProperty(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void removeUserDefinedProperty(String propertyName) {
|
||||
codeMgr.removeUserDefinedProperty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getPropertyMap(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public PropertyMap getPropertyMap(String propertyName) {
|
||||
return codeMgr.getPropertyMap(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#createInstruction(ghidra.program.model.address.Address, ghidra.program.model.lang.InstructionPrototype, ghidra.program.model.mem.MemBuffer, ghidra.program.model.lang.ProcessorContext)
|
||||
*/
|
||||
@Override
|
||||
public Instruction createInstruction(Address addr, InstructionPrototype prototype,
|
||||
MemBuffer memBuf, ProcessorContextView context) throws CodeUnitInsertionException {
|
||||
return codeMgr.createCodeUnit(addr, prototype, memBuf, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#addInstructions(ghidra.program.model.lang.InstructionSet, boolean)
|
||||
*/
|
||||
@Override
|
||||
public AddressSetView addInstructions(InstructionSet instructionSet, boolean overwrite)
|
||||
throws CodeUnitInsertionException {
|
||||
return codeMgr.addInstructions(instructionSet, overwrite);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ghidra.program.model.listing.Listing#createData(ghidra.program.model.address.Address, ghidra.program.model.data.DataType)
|
||||
*/
|
||||
@Override
|
||||
public Data createData(Address addr, DataType dataType)
|
||||
throws CodeUnitInsertionException, DataTypeConflictException {
|
||||
return codeMgr.createCodeUnit(addr, dataType, dataType.getLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#createData(ghidra.program.model.address.Address, ghidra.program.model.data.DataType)
|
||||
*/
|
||||
@Override
|
||||
public Data createData(Address addr, DataType dataType, int length)
|
||||
throws CodeUnitInsertionException, DataTypeConflictException {
|
||||
return codeMgr.createCodeUnit(addr, dataType, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#clearCodeUnits(ghidra.program.model.address.Address, ghidra.program.model.address.Address, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext) {
|
||||
try {
|
||||
codeMgr.clearCodeUnits(startAddr, endAddr, clearContext,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
TaskMonitor.DUMMY);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// can't happen with dummy monitor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#clearCodeUnits(ghidra.program.model.address.Address, ghidra.program.model.address.Address, boolean, ghidra.util.task.TaskMonitor)
|
||||
*/
|
||||
@Override
|
||||
public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
codeMgr.clearCodeUnits(startAddr, endAddr, clearContext, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#isUndefined(ghidra.program.model.address.Address, ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public boolean isUndefined(Address start, Address end) {
|
||||
return codeMgr.isUndefined(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#clearComments(ghidra.program.model.address.Address, ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public void clearComments(Address startAddr, Address endAddr) {
|
||||
codeMgr.clearComments(startAddr, endAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#clearProperties(ghidra.program.model.address.Address, ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public void clearProperties(Address startAddr, Address endAddr, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
codeMgr.clearProperties(startAddr, endAddr, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#clearAll(boolean, TaskMonitor)
|
||||
*/
|
||||
@Override
|
||||
public void clearAll(boolean clearContext, TaskMonitor monitor) {
|
||||
codeMgr.clearAll(false, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
codeMgr.clearAll(false, TaskMonitor.DUMMY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getNumCodeUnits()
|
||||
*/
|
||||
@Override
|
||||
public long getNumCodeUnits() {
|
||||
return getNumDefinedData() + getNumInstructions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getNumDefinedData()
|
||||
*/
|
||||
@Override
|
||||
public long getNumDefinedData() {
|
||||
return codeMgr.getNumDefinedData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getNumInstructions()
|
||||
*/
|
||||
@Override
|
||||
public long getNumInstructions() {
|
||||
return codeMgr.getNumInstructions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFragment(java.lang.String, ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public ProgramFragment getFragment(String treeName, Address addr) {
|
||||
return treeMgr.getFragment(treeName, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getModule(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ProgramModule getModule(String treeName, String name) {
|
||||
return treeMgr.getModule(treeName, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFragment(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ProgramFragment getFragment(String treeName, String name) {
|
||||
return treeMgr.getFragment(treeName, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#createRootModule(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ProgramModule createRootModule(String treeName) throws DuplicateNameException {
|
||||
return treeMgr.createRootModule(treeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getRootModule(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ProgramModule getRootModule(String treeName) {
|
||||
return treeMgr.getRootModule(treeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getRootModule(long)
|
||||
*/
|
||||
@Override
|
||||
public ProgramModule getRootModule(long treeID) {
|
||||
return treeMgr.getRootModule(treeID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getRootModule(long)
|
||||
*/
|
||||
@Override
|
||||
public ProgramModule getDefaultRootModule() {
|
||||
return treeMgr.getDefaultRootModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getTreeNames()
|
||||
*/
|
||||
@Override
|
||||
public String[] getTreeNames() {
|
||||
return treeMgr.getTreeNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#removeTree(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean removeTree(String treeName) {
|
||||
return treeMgr.removeTree(treeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#renameTree(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void renameTree(String oldName, String newName) throws DuplicateNameException {
|
||||
treeMgr.renameTree(oldName, newName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDataTypeManager()
|
||||
*/
|
||||
@Override
|
||||
public DataTypeManager getDataTypeManager() {
|
||||
return program.getDataTypeManager();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.program.model.listing.Listing#createFunction(java.lang.String, ghidra.program.model.address.Address, ghidra.program.model.address.AddressSetView, int)
|
||||
*/
|
||||
@Override
|
||||
public Function createFunction(String name, Address entryPoint, AddressSetView body,
|
||||
SourceType source) throws InvalidInputException, OverlappingFunctionException {
|
||||
return functionMgr.createFunction(name, entryPoint, body, source);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.program.model.listing.Listing#createFunction(java.lang.String, ghidra.program.model.symbol.Namespace, ghidra.program.model.address.Address, ghidra.program.model.address.AddressSetView, int)
|
||||
*/
|
||||
@Override
|
||||
public Function createFunction(String name, Namespace nameSpace, Address entryPoint,
|
||||
AddressSetView body, SourceType source)
|
||||
|
@ -617,17 +410,11 @@ class ListingDB implements Listing {
|
|||
return functionMgr.createFunction(name, nameSpace, entryPoint, body, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#removeFunction(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public void removeFunction(Address entryPoint) {
|
||||
functionMgr.removeFunction(entryPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFunctionAt(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Function getFunctionAt(Address entryPoint) {
|
||||
return functionMgr.getFunctionAt(entryPoint);
|
||||
|
@ -662,9 +449,6 @@ class ListingDB implements Listing {
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFirstFunctionContaining(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public Function getFunctionContaining(Address addr) {
|
||||
return functionMgr.getFunctionContaining(addr);
|
||||
|
@ -675,90 +459,57 @@ class ListingDB implements Listing {
|
|||
return functionMgr.getExternalFunctions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFunctions(boolean)
|
||||
*/
|
||||
@Override
|
||||
public FunctionIterator getFunctions(boolean forward) {
|
||||
return functionMgr.getFunctions(forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFunctions(ghidra.program.model.address.Address, boolean)
|
||||
*/
|
||||
@Override
|
||||
public FunctionIterator getFunctions(Address start, boolean forward) {
|
||||
return functionMgr.getFunctions(start, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getFunctions(ghidra.program.model.address.AddressSetView, boolean)
|
||||
*/
|
||||
@Override
|
||||
public FunctionIterator getFunctions(AddressSetView asv, boolean forward) {
|
||||
return functionMgr.getFunctions(asv, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#isInFunction(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public boolean isInFunction(Address addr) {
|
||||
return functionMgr.isInFunction(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCommentHistory(ghidra.program.model.address.Address, int)
|
||||
*/
|
||||
@Override
|
||||
public CommentHistory[] getCommentHistory(Address addr, int commentType) {
|
||||
return codeMgr.getCommentHistory(addr, commentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCommentCodeUnitIterator(int, ghidra.program.model.address.AddressSetView)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnitIterator getCommentCodeUnitIterator(int commentType, AddressSetView addrSet) {
|
||||
return codeMgr.getCommentCodeUnitIterator(commentType, addrSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCommentAddressIterator(int, ghidra.program.model.address.AddressSetView, boolean)
|
||||
*/
|
||||
@Override
|
||||
public AddressIterator getCommentAddressIterator(int commentType, AddressSetView addrSet,
|
||||
boolean forward) {
|
||||
return codeMgr.getCommentAddressIterator(commentType, addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getCommentAddressIterator(ghidra.program.model.address.AddressSetView, boolean)
|
||||
*/
|
||||
@Override
|
||||
public AddressIterator getCommentAddressIterator(AddressSetView addrSet, boolean forward) {
|
||||
return codeMgr.getCommentAddressIterator(addrSet, forward);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getComment(int, ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public String getComment(int commentType, Address address) {
|
||||
return codeMgr.getComment(commentType, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#setComment(ghidra.program.model.address.Address, int, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setComment(Address address, int commentType, String comment) {
|
||||
codeMgr.setComment(address, commentType, comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedCodeUnitAfter(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit getDefinedCodeUnitAfter(Address addr) {
|
||||
CodeUnit data = codeMgr.getDefinedDataAfter(addr);
|
||||
|
@ -777,9 +528,6 @@ class ListingDB implements Listing {
|
|||
return inst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.Listing#getDefinedCodeUnitBefore(ghidra.program.model.address.Address)
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit getDefinedCodeUnitBefore(Address addr) {
|
||||
CodeUnit data = codeMgr.getDefinedDataBefore(addr);
|
||||
|
|
|
@ -50,7 +50,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
|
||||
private boolean upgrade = false;
|
||||
|
||||
private Map<String, BookmarkType> typesByName = new TreeMap<String, BookmarkType>();
|
||||
private Map<String, BookmarkType> typesByName = new TreeMap<>();
|
||||
private ObjectArray typesArray = new ObjectArray();
|
||||
private Lock lock;
|
||||
|
||||
|
@ -73,7 +73,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
bookmarkTypeAdapter = BookmarkTypeDBAdapter.getAdapter(handle, openMode);
|
||||
int[] types = bookmarkTypeAdapter.getTypeIds();
|
||||
bookmarkAdapter = BookmarkDBAdapter.getAdapter(handle, openMode, types, addrMap, monitor);
|
||||
cache = new DBObjectCache<BookmarkDB>(100);
|
||||
cache = new DBObjectCache<>(100);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -388,16 +388,6 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
lock.acquire();
|
||||
try {
|
||||
|
||||
boolean isSpecificType = type != null && type != BookmarkType.ALL_TYPES;
|
||||
if (!isSpecificType) {
|
||||
// no type specified; remove all
|
||||
Iterator<String> iter = typesByName.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
removeBookmarks(iter.next());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
BookmarkTypeDB bmt = (BookmarkTypeDB) typesByName.get(type);
|
||||
if (bmt.hasBookmarks()) {
|
||||
|
@ -474,7 +464,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
lock.acquire();
|
||||
try {
|
||||
int n = typesArray.getLastNonEmptyIndex();
|
||||
List<Bookmark> list = new ArrayList<Bookmark>();
|
||||
List<Bookmark> list = new ArrayList<>();
|
||||
for (int i = 0; i <= n; i++) {
|
||||
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
|
||||
if (bmt != null && bmt.hasBookmarks()) {
|
||||
|
@ -512,7 +502,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
lock.acquire();
|
||||
try {
|
||||
Bookmark[] bookmarks = null;
|
||||
List<Bookmark> list = new ArrayList<Bookmark>();
|
||||
List<Bookmark> list = new ArrayList<>();
|
||||
BookmarkType bmt = getBookmarkType(type);
|
||||
if (bmt != null && bmt.hasBookmarks()) {
|
||||
getBookmarks(address, bmt.getTypeId(), list);
|
||||
|
@ -681,18 +671,18 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
@Override
|
||||
public Iterator<Bookmark> getBookmarksIterator(Address startAddress, boolean forward) {
|
||||
|
||||
List<PeekableIterator<Bookmark>> list = new ArrayList<PeekableIterator<Bookmark>>();
|
||||
List<PeekableIterator<Bookmark>> list = new ArrayList<>();
|
||||
int n = typesArray.getLastNonEmptyIndex();
|
||||
for (int i = 0; i <= n; i++) {
|
||||
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
|
||||
if (bmt != null && bmt.hasBookmarks()) {
|
||||
Iterator<Bookmark> bookmarksIterator =
|
||||
getBookmarksIterator(startAddress, bmt, forward);
|
||||
list.add(new WrappingPeekableIterator<Bookmark>(bookmarksIterator));
|
||||
list.add(new WrappingPeekableIterator<>(bookmarksIterator));
|
||||
}
|
||||
}
|
||||
|
||||
return new MultiIterator<Bookmark>(list, forward);
|
||||
return new MultiIterator<>(list, forward);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -880,7 +870,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
|
|||
Iterator<Bookmark> bookmarkIt;
|
||||
|
||||
TotalIterator() {
|
||||
List<BookmarkTypeDB> list = new ArrayList<BookmarkTypeDB>();
|
||||
List<BookmarkTypeDB> list = new ArrayList<>();
|
||||
int n = typesArray.getLastNonEmptyIndex();
|
||||
for (int i = 0; i <= n; i++) {
|
||||
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,7 +38,7 @@ class CodeUnitRecordIterator implements CodeUnitIterator {
|
|||
|
||||
/**
|
||||
* Constructs a new CodeUnitRecordIterator
|
||||
* @param codeMgr the code managaer
|
||||
* @param codeMgr the code manager
|
||||
* @param instIt the instruction iterator
|
||||
* @param dataIt the data iterator
|
||||
* @param set the address set (required)
|
||||
|
@ -57,17 +57,11 @@ class CodeUnitRecordIterator implements CodeUnitIterator {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.CodeUnitIterator#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (nextCu == null) {
|
||||
|
@ -76,9 +70,6 @@ class CodeUnitRecordIterator implements CodeUnitIterator {
|
|||
return nextCu != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.listing.CodeUnitIterator#next()
|
||||
*/
|
||||
@Override
|
||||
public CodeUnit next() {
|
||||
if (hasNext()) {
|
||||
|
|
|
@ -62,7 +62,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
|||
private LiveMemoryHandler liveMemory;
|
||||
|
||||
// lazy hashmap of block names to blocks, must be reloaded if blocks are removed or added
|
||||
private HashMap<String, MemoryBlock> nameBlockMap = new HashMap<String, MemoryBlock>();
|
||||
private HashMap<String, MemoryBlock> nameBlockMap = new HashMap<>();
|
||||
private final static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out
|
||||
|
||||
Lock lock;
|
||||
|
@ -1257,8 +1257,13 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
|||
* Tests if the memory contains a sequence of contiguous bytes that match the given byte array
|
||||
* at all bit positions where the mask contains an "on" bit. The test will be something like
|
||||
*
|
||||
* for(int i=0;i<bytes.length;i++) { if (bytes[i] != memory.getByte(addr+i) & masks[i]) {
|
||||
* return false; } } return false;
|
||||
* <PRE>
|
||||
* for(int i = 0; i < bytes.length; i++) {
|
||||
* if (bytes[i] != memory.getByte(addr+i) & masks[i]) {
|
||||
* return false;
|
||||
* }
|
||||
* }
|
||||
* </PRE>
|
||||
*
|
||||
* @param addr The beginning address in memory to test against.
|
||||
* @param bytes the array of bytes to test for.
|
||||
|
|
|
@ -18,23 +18,22 @@ package ghidra.program.model.address;
|
|||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.program.model.data.DataOrganization;
|
||||
import ghidra.program.model.lang.Register;
|
||||
|
||||
/**
|
||||
* An address represents a location in a program. Conceptually, addresses consist
|
||||
* of an "address space" and an offset within that space. Many processors have only
|
||||
* one "real" address space, but some have several spaces. Also, there are
|
||||
* "artificial" address spaces used for analysis and representing other non-memory locations
|
||||
* such as a register or an offset on the stack relative to a functions frame pointer.
|
||||
*
|
||||
* An address represents a location in a program. Conceptually, addresses consist of an
|
||||
* "address space" and an offset within that space. Many processors have only one "real" address
|
||||
* space, but some have several spaces. Also, there are "artificial" address spaces used for
|
||||
* analysis and representing other non-memory locations such as a register or an offset on the
|
||||
* stack relative to a functions frame pointer.
|
||||
*/
|
||||
|
||||
public interface Address extends Comparable<Address> {
|
||||
/**
|
||||
* Address object representing an invalid address.
|
||||
*/
|
||||
public static final Address NO_ADDRESS = new SpecialAddress("NO ADDRESS");
|
||||
/**
|
||||
* Address object representing an extenal entry address.
|
||||
* Address object representing an external entry address.
|
||||
*/
|
||||
public static final Address EXT_FROM_ADDRESS = new SpecialAddress("Entry Point");
|
||||
/**
|
||||
|
@ -43,14 +42,14 @@ public interface Address extends Comparable<Address> {
|
|||
public final char SEPARATOR_CHAR = ':';
|
||||
|
||||
/**
|
||||
* Creates a new Address by parsing a String representation of an address. The
|
||||
* string may be either a simple number (just the offset part of an address) or take
|
||||
* the form "addressSpaceName:offset". If the latter form is used, the
|
||||
* "addressSpaceName" must match the name of the space for this address.
|
||||
* Creates a new Address by parsing a String representation of an address. The string may be
|
||||
* either a simple number (just the offset part of an address) or take the form
|
||||
* "addressSpaceName:offset". If the latter form is used, the "addressSpaceName" must match
|
||||
* the name of the space for this address.
|
||||
*
|
||||
* @param addrString the String to parse.
|
||||
* @return the new Address if the string is a legally formed address or null
|
||||
* if the string contains an address space name that does not match this address's space.
|
||||
* @return the new Address if the string is a legally formed address or null if the string
|
||||
* contains an address space name that does not match this address's space.
|
||||
* @throws AddressFormatException if the string cannot be parsed or the
|
||||
* parsed offset is larger than the size for this address' space.
|
||||
*/
|
||||
|
@ -68,30 +67,31 @@ public interface Address extends Comparable<Address> {
|
|||
|
||||
/**
|
||||
* Returns a new address in this address's space with the given offset.
|
||||
* NOTE: for those spaces with an addressable unit size other than 1, the address
|
||||
* returned may not correspond to an addressable unit/word boundary if a byte-offset
|
||||
* is specified.
|
||||
* <P>NOTE: for those spaces with an addressable unit size other than 1, the address returned
|
||||
* may not correspond to an addressable unit/word boundary if a byte-offset is specified.
|
||||
*
|
||||
* @param offset the offset for the new address.
|
||||
* @param isAddressableWordOffset if true the specified offset is an addressable unit/word offset,
|
||||
* otherwise offset is a byte offset. See {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize()
|
||||
* @param isAddressableWordOffset if true the specified offset is an addressable unit/word
|
||||
* offset, otherwise offset is a byte offset. See
|
||||
* {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize()
|
||||
* AddressSpace#getAddressableUnitSize()} to understand the distinction
|
||||
* (i.e., wordOffset = byteOffset * addressableUnitSize).
|
||||
* @return address with given offset
|
||||
* @throws AddressOutOfBoundsException if the offset is less than 0 or greater
|
||||
* than the max offset allowed for this space.
|
||||
* @throws AddressOutOfBoundsException if the offset is less than 0 or greater than the max
|
||||
* offset allowed for this space.
|
||||
*/
|
||||
Address getNewAddress(long offset, boolean isAddressableWordOffset)
|
||||
throws AddressOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Returns a new address in this address's space with the given offset. The specified
|
||||
* offset will be truncated within the space and will not throw an exception.
|
||||
* NOTE: for those spaces with an addressable unit size other than 1, the address
|
||||
* returned may not correspond to a word boundary (addressable unit) if a byte-offset
|
||||
* is specified.
|
||||
* Returns a new address in this address's space with the given offset. The specified offset
|
||||
* will be truncated within the space and will not throw an exception.
|
||||
* <p>NOTE: for those spaces with an addressable unit size other than 1, the address returned
|
||||
* may not correspond to a word boundary (addressable unit) if a byte-offset is specified.
|
||||
* @param offset the offset for the new address.
|
||||
* @param isAddressableWordOffset if true the specified offset is an addressable unit/word offset,
|
||||
* otherwise offset is a byte offset. See {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize()
|
||||
* @param isAddressableWordOffset if true the specified offset is an addressable unit/word
|
||||
* offset, otherwise offset is a byte offset. See
|
||||
* {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize()
|
||||
* AddressSpace#getAddressableUnitSize()} to understand the distinction
|
||||
* (i.e., wordOffset = byteOffset * addressableUnitSize).
|
||||
* @return address with given byte offset truncated to the physical space size
|
||||
|
@ -99,40 +99,38 @@ public interface Address extends Comparable<Address> {
|
|||
Address getNewTruncatedAddress(long offset, boolean isAddressableWordOffset);
|
||||
|
||||
/**
|
||||
* Returns the number of bytes needed to form a pointer to this address. The
|
||||
* result will be one of {1,2,4,8}.
|
||||
* @see DataOrganization#getPointerSize() for compiler-specific size of pointers stored in memory.
|
||||
* Returns the number of bytes needed to form a pointer to this address. The result will be
|
||||
* one of {1,2,4,8}.
|
||||
* @return the pointer size
|
||||
* @see DataOrganization#getPointerSize() for compiler-specific size of pointers stored in
|
||||
* memory.
|
||||
*/
|
||||
public int getPointerSize();
|
||||
|
||||
/**
|
||||
* Returns the address's successor. In most cases, this is equivalent
|
||||
* to addr.add(1), but segmented addresses could span segments. The result
|
||||
* of calling this on the highest address will result in a null return value.
|
||||
* @return the next higher address, or null if already at the
|
||||
* highest address.
|
||||
* Returns the address's successor. In most cases, this is equivalent to addr.add(1), but
|
||||
* segmented addresses could span segments. The result of calling this on the highest address
|
||||
* will result in a null return value.
|
||||
* @return the next higher address, or null if already at the highest address.
|
||||
*/
|
||||
public Address next();
|
||||
|
||||
/**
|
||||
* Returns the address's predecessor. In most cases, this is equivalent to
|
||||
* addr.subtract(1), but segmented addresses could span segments. The
|
||||
* result of calling this on the lowest address will result in a null return value.
|
||||
* @return the next lower address, or null if already at the
|
||||
* lowest address.
|
||||
* Returns the address's predecessor. In most cases, this is equivalent to addr.subtract(1),
|
||||
* but segmented addresses could span segments. The result of calling this on the lowest
|
||||
* address will result in a null return value.
|
||||
* @return the next lower address, or null if already at the lowest address.
|
||||
*/
|
||||
public Address previous();
|
||||
|
||||
/**
|
||||
* Get the offset of this Address.
|
||||
*
|
||||
* @return the offset of this Address.
|
||||
*/
|
||||
public long getOffset();
|
||||
|
||||
/**
|
||||
* Get the offset of this Address as a BigInteger
|
||||
*
|
||||
* Get the offset of this Address as a BigInteger.
|
||||
* @return the offset of this Address.
|
||||
*/
|
||||
public BigInteger getOffsetAsBigInteger();
|
||||
|
@ -152,17 +150,21 @@ public interface Address extends Comparable<Address> {
|
|||
|
||||
/**
|
||||
* Returns the address space associated with this address.
|
||||
* @return the address space
|
||||
*/
|
||||
public AddressSpace getAddressSpace();
|
||||
|
||||
/**
|
||||
* Return true if this address' address space is equal to the
|
||||
* address space for addr.
|
||||
* Return true if this address' address space is equal to the address space for addr.
|
||||
* @param addr the address to check
|
||||
* @return true if the same space
|
||||
*/
|
||||
public boolean hasSameAddressSpace(Address addr);
|
||||
|
||||
/** Returns the number of bits that are used to form the address. Thus
|
||||
* the maximum offset for this address space will be 2^size-1.
|
||||
/**
|
||||
* Returns the number of bits that are used to form the address. Thus the maximum offset for
|
||||
* this address space will be 2^size-1.
|
||||
* @return the size
|
||||
*/
|
||||
public int getSize();
|
||||
|
||||
|
@ -176,10 +178,9 @@ public interface Address extends Comparable<Address> {
|
|||
public long subtract(Address addr);
|
||||
|
||||
/**
|
||||
* Creates a new address by subtracting the displacement from the current
|
||||
* address. The new address will wrap in a manner that depends on the
|
||||
* address space. For a generic address space this will wrap at the
|
||||
* extents of the address space. For a segmented address space it will
|
||||
* Creates a new address by subtracting the displacement from the current address. The new
|
||||
* address will wrap in a manner that depends on the address space. For a generic address space
|
||||
* this will wrap at the extents of the address space. For a segmented address space it will
|
||||
* wrap at the extents of the segment.
|
||||
*
|
||||
* @param displacement the displacement to subtract.
|
||||
|
@ -188,43 +189,41 @@ public interface Address extends Comparable<Address> {
|
|||
public Address subtractWrap(long displacement);
|
||||
|
||||
/**
|
||||
* Creates a new address by subtracting the displacement from the current
|
||||
* address. If the offset is greater than the max offset of the address space, the high
|
||||
* order bits are masked off, making the address wrap. For non-segmented addresses this
|
||||
* will be the same as subtractWrap(). For segmented addresses, the address will wrap when
|
||||
* the 20 bit (oxfffff) offset is exceeded, as opposed to when the segment offset is exceeded.
|
||||
* Creates a new address by subtracting the displacement from the current address. If the
|
||||
* offset is greater than the max offset of the address space, the high order bits are masked
|
||||
* off, making the address wrap. For non-segmented addresses this will be the same as
|
||||
* subtractWrap(). For segmented addresses, the address will wrap when the 20 bit (oxfffff)
|
||||
* offset is exceeded, as opposed to when the segment offset is exceeded.
|
||||
* @param displacement the displacement to add.
|
||||
* @return The new Address formed by subtracting the displacement from this address's offset.
|
||||
*/
|
||||
public Address subtractWrapSpace(long displacement);
|
||||
|
||||
/**
|
||||
* Creates a new Address by subtracting displacement from the
|
||||
* Address. The Address will not wrap within the space and in fact will throw
|
||||
* an exception if the result is less than the min address in this space or
|
||||
* greater than the max address in this space.
|
||||
* Creates a new Address by subtracting displacement from the Address. The Address will not
|
||||
* wrap within the space and in fact will throw an exception if the result is less than the min
|
||||
* address in this space or greater than the max address in this space.
|
||||
*
|
||||
* @param displacement the displacement to subtract.
|
||||
* @return The new Address
|
||||
* @throws AddressOverflowException if the offset in this Address would
|
||||
* overflow due to this operation.
|
||||
* @throws AddressOverflowException if the offset in this Address would overflow due to this
|
||||
* operation.
|
||||
*/
|
||||
public Address subtractNoWrap(long displacement) throws AddressOverflowException;
|
||||
|
||||
/**
|
||||
* Creates a new address (possibly in a new space) by subtracting the displacement to
|
||||
* this address.
|
||||
* Creates a new address (possibly in a new space) by subtracting the displacement to this
|
||||
* address.
|
||||
* @param displacement the amount to subtract from this offset.
|
||||
* @return The address using the subtracted offset.
|
||||
*/
|
||||
public Address subtract(long displacement);
|
||||
|
||||
/**
|
||||
* Creates a new address by adding the displacement to the current
|
||||
* address. The new address will wrap in a manner that depends on the
|
||||
* address space. For a generic address space this will wrap at the
|
||||
* extents of the address space. For a segmented address space it will
|
||||
* wrap at the extents of the segment.
|
||||
* Creates a new address by adding the displacement to the current address. The new address
|
||||
* will wrap in a manner that depends on the address space. For a generic address space this
|
||||
* will wrap at the extents of the address space. For a segmented address space it will wrap at
|
||||
* the extents of the segment.
|
||||
*
|
||||
* @param displacement the displacement to add.
|
||||
* @return The new Address formed by adding the displacement to this address's offset.
|
||||
|
@ -232,38 +231,35 @@ public interface Address extends Comparable<Address> {
|
|||
public Address addWrap(long displacement);
|
||||
|
||||
/**
|
||||
* Creates a new address by adding the displacement to the current
|
||||
* address. If the offset is greater than the max offset of the address space, the high
|
||||
* order bits are masked off, making the address wrap. For non-segmented addresses this
|
||||
* will be the same as addWrap(). For segmented addresses, the address will wrap when
|
||||
* the 20 bit (oxfffff) offset is exceeded, as opposed to when the segment offset is exceeded.
|
||||
* Creates a new address by adding the displacement to the current address. If the offset is
|
||||
* greater than the max offset of the address space, the high order bits are masked off, making
|
||||
* the address wrap. For non-segmented addresses this will be the same as addWrap(). For
|
||||
* segmented addresses, the address will wrap when the 20 bit (oxfffff) offset is exceeded, as
|
||||
* opposed to when the segment offset is exceeded.
|
||||
* @param displacement the displacement to add.
|
||||
* @return The new Address formed by adding the displacement to this address's offset.
|
||||
*/
|
||||
public Address addWrapSpace(long displacement);
|
||||
|
||||
/**
|
||||
* Creates a new Address with a displacement relative to this
|
||||
* Address. The Address will not wrap around! An exception will be
|
||||
* throw if the result is not within this address space.
|
||||
* Creates a new Address with a displacement relative to this Address. The Address will not
|
||||
* wrap around! An exception will be throw if the result is not within this address space.
|
||||
*
|
||||
* @param displacement the displacement to add.
|
||||
* @return The new Address
|
||||
* @throws AddressOverflowException if the offset in this Address would
|
||||
* overflow (wrap around) due to this operation.
|
||||
* @return the new address.
|
||||
* @throws AddressOverflowException if the offset in this Address would overflow (wrap around)
|
||||
* due to this operation.
|
||||
*/
|
||||
public Address addNoWrap(long displacement) throws AddressOverflowException;
|
||||
|
||||
public Address addNoWrap(BigInteger displacement) throws AddressOverflowException;
|
||||
|
||||
/**
|
||||
* Creates a new address (possibly in a new space) by adding the displacement to
|
||||
* this address.
|
||||
* Creates a new address (possibly in a new space) by adding the displacement to this address.
|
||||
* @param displacement the amount to add to this offset.
|
||||
* @return The new address.
|
||||
* @throws AddressOutOfBoundsException if wrapping is not supported by the
|
||||
* corresponding address space and the addition causes an out-of-bounds
|
||||
* error
|
||||
* @throws AddressOutOfBoundsException if wrapping is not supported by the corresponding
|
||||
* address space and the addition causes an out-of-bounds error
|
||||
*/
|
||||
public Address add(long displacement) throws AddressOutOfBoundsException;
|
||||
|
||||
|
@ -271,73 +267,74 @@ public interface Address extends Comparable<Address> {
|
|||
* Tests whether the given address immediately follows this address.
|
||||
*
|
||||
* @param addr the address to test.
|
||||
* @return true if the address follows this address.
|
||||
*/
|
||||
public boolean isSuccessor(Address addr);
|
||||
|
||||
/**
|
||||
* Returns a String representation of the address in hex and padded
|
||||
* to the appropriate size.
|
||||
* Returns a String representation of the address in hex and padded to the appropriate size.
|
||||
* @return the string
|
||||
*/
|
||||
@Override
|
||||
public String toString();
|
||||
|
||||
/**
|
||||
* Returns a String representation of the address using the
|
||||
* given string as a prefix. Equivalent of prefix + ":" + toString(false)
|
||||
* Returns a String representation of the address using the given string as a prefix.
|
||||
* Equivalent of prefix + ":" + toString(false)
|
||||
* @param prefix the string to prepend to the address string.
|
||||
* @return the string
|
||||
*/
|
||||
public String toString(String prefix);
|
||||
|
||||
/**
|
||||
* Returns a String representation that may include the address space name
|
||||
* @param showAddressSpace true if the address space should be included in
|
||||
* resulting string.
|
||||
* @param showAddressSpace true if the address space should be included in resulting string.
|
||||
* @return String the string representation of the address
|
||||
*/
|
||||
public String toString(boolean showAddressSpace);
|
||||
|
||||
/**
|
||||
* Returns a String representation that may include the address space name and may or may
|
||||
* not pad the address with leading zeros.
|
||||
* @param showAddressSpace if true, the addressSpace name will be prepended to the address string.
|
||||
* Returns a String representation that may include the address space name and may or may not
|
||||
* pad the address with leading zeros.
|
||||
* @param showAddressSpace if true, the addressSpace name will be prepended to the address
|
||||
* string.
|
||||
* @param pad if true, the address will be prepended with leading zeros to completely fill out
|
||||
* the max digits the address could contain. If false, the address will be prepended only to make
|
||||
* the number of hex digits at least 4.
|
||||
* the max digits the address could contain. If false, the address will be prepended only to
|
||||
* make the number of hex digits at least 4.
|
||||
* @return the address as a String.
|
||||
*/
|
||||
public String toString(boolean showAddressSpace, boolean pad);
|
||||
|
||||
/**
|
||||
* Returns a String representation that may include the address space name and may or may
|
||||
* not pad the address with leading zeros.
|
||||
* @param showAddressSpace if true, the addressSpace name will be prepended to the address string.
|
||||
* @param minNumDigits specifies the minimum number of digits to use. If the address space size
|
||||
* is less that minNumDigits, the address will be padded to the address space size. If the address
|
||||
* space size is larger that minNumDigits, the address will be displayed with as many digits as
|
||||
* necessary, but will contain leading zeros to make the address string have at least minNumDigits.
|
||||
* Returns a String representation that may include the address space name and may or may not
|
||||
* pad the address with leading zeros.
|
||||
* @param showAddressSpace if true, the addressSpace name will be prepended to the address
|
||||
* string.
|
||||
* @param minNumDigits specifies the minimum number of digits to use. If the address space
|
||||
* size is less that minNumDigits, the address will be padded to the address space size. If
|
||||
* the address space size is larger that minNumDigits, the address will be displayed with as
|
||||
* many digits as necessary, but will contain leading zeros to make the address string have at
|
||||
* least minNumDigits.
|
||||
* @return the address as a String.
|
||||
*/
|
||||
public String toString(boolean showAddressSpace, int minNumDigits);
|
||||
|
||||
/**
|
||||
* Compares this Address to the specified object.
|
||||
* The result is <code>true</code> if and only if the argument is not
|
||||
* <code>null</code> and is a <code>Address</code> object that represents
|
||||
* the same address as this object.
|
||||
* Compares this Address to the specified object. The result is <code>true</code> if and only
|
||||
* if the argument is not <code>null</code> and is a <code>Address</code> object that
|
||||
* represents the same address as this object.
|
||||
*
|
||||
* @param o the object to compare this <code>String</code>
|
||||
* against.
|
||||
* @return <code>true</code> if the <code>Addresses</code>are equal;
|
||||
* <code>false</code> otherwise.
|
||||
* @param o the object to compare this <code>String</code> against.
|
||||
* @return <code>true</code> if the <code>Addresses</code>are equal; <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o);
|
||||
|
||||
/**
|
||||
* Returns a hashcode for this Address. The hashcode for an
|
||||
* <code>Address</code> should be a value such that two Address
|
||||
* objects which are equal will return the same hashcode.
|
||||
* This method should generally return the same value as getLong().
|
||||
* Returns a hash code for this Address. The hash code for an <code>Address</code> should be a
|
||||
* value such that two Address objects which are equal will return the same hash code. This
|
||||
* method should generally return the same value as getLong().
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
*/
|
||||
|
@ -347,61 +344,69 @@ public interface Address extends Comparable<Address> {
|
|||
/**
|
||||
* Returns the physical Address that corresponds to this Address.
|
||||
*
|
||||
* @return address in a physical space corresponding to this
|
||||
* address.
|
||||
* @return address in a physical space corresponding to this address.
|
||||
*/
|
||||
public Address getPhysicalAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in memory
|
||||
* Returns true if this address represents a location in memory.
|
||||
* @return true if this address represents a location in memory.
|
||||
*/
|
||||
public boolean isMemoryAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents an address in a loaded memory block
|
||||
* Returns true if this address represents an address in a loaded memory block.
|
||||
* @return true if this address represents an address in a loaded memory block.
|
||||
*/
|
||||
public boolean isLoadedMemoryAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents an address not loaded in real memory (i.e. OTHER)
|
||||
* Returns true if this address represents an address not loaded in real memory (i.e. OTHER).
|
||||
* @return true if this address represents an address not loaded in real memory (i.e. OTHER).
|
||||
*/
|
||||
public boolean isNonLoadedMemoryAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in stack space
|
||||
* Returns true if this address represents a location in stack space.
|
||||
* @return true if this address represents a location in stack space.
|
||||
*/
|
||||
public boolean isStackAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in unique space
|
||||
* Returns true if this address represents a location in unique space.
|
||||
* @return true if this address represents a location in unique space.
|
||||
*/
|
||||
public boolean isUniqueAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in constant space
|
||||
* Returns true if this address represents a location in constant space.
|
||||
* @return true if this address represents a location in constant space.
|
||||
*/
|
||||
public boolean isConstantAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in the HASH space
|
||||
* Returns true if this address represents a location in the HASH space.
|
||||
* @return true if this address represents a location in the HASH space.
|
||||
*/
|
||||
public boolean isHashAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in the register space.
|
||||
* <P>NOTE: It is important to note that a {@link Register} could reside within
|
||||
* a memory space and not the register space in which case this method would return
|
||||
* false for its address.
|
||||
* <P>NOTE: It is important to note that a {@link Register} could reside within a memory space
|
||||
* and not the register space in which case this method would return false for its address.
|
||||
* @return true if a register address
|
||||
*/
|
||||
public boolean isRegisterAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents a location in variable space
|
||||
* Returns true if this address represents a location in variable space.
|
||||
* @return true if this address represents a location in variable space.
|
||||
*/
|
||||
public boolean isVariableAddress();
|
||||
|
||||
/**
|
||||
* Returns true if this address represents an external location in the external address space
|
||||
* Returns true if this address represents an external location in the external address space.
|
||||
* @return true if this address represents an external location in the external address space.
|
||||
*/
|
||||
public boolean isExternalAddress();
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* 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.
|
||||
|
@ -30,38 +29,43 @@ public interface BookmarkType {
|
|||
public static final String ERROR = "Error";
|
||||
public static final String WARNING = "Warning";
|
||||
public static final String ANALYSIS = "Analysis";
|
||||
public static final String ALL_TYPES = "All Bookmark Types";
|
||||
|
||||
/**
|
||||
* Returns the type as a string
|
||||
* Returns the type as a string.
|
||||
* @return the type as a string.
|
||||
*/
|
||||
String getTypeString();
|
||||
public String getTypeString();
|
||||
|
||||
/**
|
||||
* Returns Icon associated with this type or null if one has not been
|
||||
* set by a plugin.
|
||||
* @return the icon.
|
||||
*/
|
||||
ImageIcon getIcon();
|
||||
public ImageIcon getIcon();
|
||||
|
||||
/**
|
||||
* Returns marker color associated with this type or null if one has not been
|
||||
* set by a plugin.
|
||||
* @return the color.
|
||||
*/
|
||||
Color getMarkerColor();
|
||||
public Color getMarkerColor();
|
||||
|
||||
/**
|
||||
* Returns marker priority associated with this type or -1 if one has not been
|
||||
* set by a plugin.
|
||||
* @return the priority.
|
||||
*/
|
||||
int getMarkerPriority();
|
||||
public int getMarkerPriority();
|
||||
|
||||
/**
|
||||
* Returns true if there is at least one bookmark defined for this type
|
||||
* Returns true if there is at least one bookmark defined for this type.
|
||||
* @return true if there is at least one bookmark defined for this type.
|
||||
*/
|
||||
boolean hasBookmarks();
|
||||
public boolean hasBookmarks();
|
||||
|
||||
/**
|
||||
* Returns the id associated with this bookmark type.
|
||||
* @return the id associated with this bookmark type.
|
||||
*/
|
||||
int getTypeId();
|
||||
public int getTypeId();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue