GP-1679 - Consolidated navigation buttons and added an action to invert the search

This commit is contained in:
dragonmacher 2022-03-04 15:55:26 -05:00
parent 0f3aa2b9de
commit ae37ca2e27
24 changed files with 1804 additions and 1492 deletions

View file

@ -940,6 +940,7 @@ src/main/resources/images/Program.gif||GHIDRA||||END|
src/main/resources/images/ThunkFunction.gif||GHIDRA||||END| src/main/resources/images/ThunkFunction.gif||GHIDRA||||END|
src/main/resources/images/U.gif||GHIDRA||||END| src/main/resources/images/U.gif||GHIDRA||||END|
src/main/resources/images/Unpackage.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/VCRFastForward.gif||GHIDRA||||END|
src/main/resources/images/V_slash.png||GHIDRA||||END| src/main/resources/images/V_slash.png||GHIDRA||||END|
src/main/resources/images/View.gif||GHIDRA||||END| src/main/resources/images/View.gif||GHIDRA||||END|

View file

@ -416,12 +416,27 @@
temporarily invert the direction of the search.</P> temporarily invert the direction of the search.</P>
</BLOCKQUOTE> </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> <H3><A name="Next_Instruction"></A>Navigate to Instruction</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<P>To move the cursor to the next instruction click on the Navigate by Instruction icon, <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 <IMG src="images/I.gif" alt="I" border="0">. This icon is disabled when no more
instructions exist in the current search direction.</P> 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> </BLOCKQUOTE>
<H3><A name="Next_Data"></A>Navigate to Data</H3> <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 <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 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> 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> </BLOCKQUOTE>
<H3><A name="Next_Undefined"></A>Navigate to Undefined</H3> <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, <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 <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> 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> </BLOCKQUOTE>
<H3><A name="Next_Label"></A>Navigate to Label</H3> <H3><A name="Next_Label"></A>Navigate to Label</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<P>To move the cursor to the next Label, click on the Navigate by Label icon, <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 <IMG src="images/L.gif" alt="L" border="0">.</P>
exist in the current search direction.</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> </BLOCKQUOTE>
<H3><A name="Next_Function"></A>Navigate to Function</H3> <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 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> 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> </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 <BLOCKQUOTE>
the navigate to the next instruction block not contained in a function.&nbsp;
This can be useful when manually creating functions and
stepping over them to identify potential function candidates.&nbsp;</P>
<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>When inverted, this task will attempt to
<P style="margin-left: 40px;">This task (<IMG src="images/V_slash.png" alt="V">) will attempt to
the navigate to the first code-unit where the byte value is different from the byte value 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.&nbsp; This can be useful when trying to navigate 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> past a series of 0s or FFs</P>
</BLOCKQUOTE>
<H3><A name="Next_Bookmark"></A>Navigate to Bookmark</H3> <H3><A name="Next_Bookmark"></A>Navigate to Bookmark</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<P>To move the cursor to the next bookmark, click on the Navigate by Bookmark icon, <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 <IMG src="images/B.gif" alt="B" border="0">. You may use the pull-down menu to choose a
exist in the current search direction. You may use the pull-down menu to choose a specific specific type of bookmark (<IMG src="images/applications-system.png" alt="B" border="0">,
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/edit-delete.png" alt="B" border="0">,
<IMG src="images/information.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/notes.gif" alt="B" border="0">,
<IMG src="images/warning.png" alt="B" border="0">, <IMG src="images/warning.png" alt="B" border="0">,
<IMG src="images/unknown.gif" alt="B" border="0">) <IMG src="images/unknown.gif" alt="B" border="0">)
to navigate to as opposed to all types. </P> 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> </BLOCKQUOTE>

View file

@ -23,6 +23,7 @@ import javax.swing.KeyStroke;
import docking.action.KeyBindingData; import docking.action.KeyBindingData;
import docking.action.ToolBarData; import docking.action.ToolBarData;
import docking.tool.ToolConstants; import docking.tool.ToolConstants;
import generic.util.image.ImageUtils;
import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableActionContext;
import ghidra.app.context.NavigatableContextAction; import ghidra.app.context.NavigatableContextAction;
import ghidra.app.nav.Navigatable; import ghidra.app.nav.Navigatable;
@ -36,12 +37,19 @@ import ghidra.util.HelpLocation;
import ghidra.util.Swing; import ghidra.util.Swing;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
import ghidra.util.task.*; import ghidra.util.task.*;
import resources.*;
public abstract class AbstractNextPreviousAction extends NavigatableContextAction { 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 boolean isForward = true;
private PluginTool tool; private PluginTool tool;
protected boolean isInverted;
private Icon invertedIcon;
public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) { public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) {
super(name, owner); super(name, owner);
this.tool = tool; this.tool = tool;
@ -55,6 +63,16 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name)); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name));
setDescription(getDescriptionString()); setDescription(getDescriptionString());
addToWindowWhen(NavigatableActionContext.class); 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(); protected abstract Icon getIcon();
@ -63,13 +81,13 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
@Override @Override
public void actionPerformed(final NavigatableActionContext context) { 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 @Override
public void run(TaskMonitor monitor) { public void run(TaskMonitor monitor) {
gotoNextPrevious(monitor, context); gotoNextPrevious(monitor, context);
} }
}; };
new TaskLauncher(t, tool.getToolFrame(), 500); new TaskLauncher(t);
} }
void gotoNextPrevious(TaskMonitor monitor, final NavigatableActionContext context) { void gotoNextPrevious(TaskMonitor monitor, final NavigatableActionContext context) {
@ -93,7 +111,7 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
private void gotoAddress(NavigatableActionContext actionContext, Address address) { private void gotoAddress(NavigatableActionContext actionContext, Address address) {
if (address == null) { 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."); "\" past the current range, in the current direction.");
return; return;
} }
@ -119,14 +137,26 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
private String getDescriptionString() { private String getDescriptionString() {
String prefix = isForward ? "Go To Next " : "Go To Previous "; 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(); abstract protected String getNavigationTypeName();
protected String getInvertedNavigationTypeName() {
return "Non-" + getNavigationTypeName();
}
abstract protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) abstract protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException; throws CancelledException;
abstract protected Address getPreviousAddress(TaskMonitor monitor, Program program, abstract protected Address getPreviousAddress(TaskMonitor monitor, Program program,
Address address) throws CancelledException; Address address) throws CancelledException;
} }

View file

@ -20,8 +20,10 @@ import java.awt.event.KeyEvent;
import javax.swing.Icon; import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*; import docking.action.*;
import docking.tool.ToolConstants; import docking.tool.ToolConstants;
import generic.util.image.ImageUtils;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableActionContext;
import ghidra.app.context.NavigatableContextAction; import ghidra.app.context.NavigatableContextAction;
@ -58,14 +60,14 @@ import resources.ResourceManager;
//@formatter:on //@formatter:on
public class NextPrevCodeUnitPlugin extends Plugin { public class NextPrevCodeUnitPlugin extends Plugin {
private DockingAction toggleDirectionAction; private DockingAction toggleDirectionAction;
private InvertStateAction invertStateAction;
private AbstractNextPreviousAction instructionAction; private AbstractNextPreviousAction instructionAction;
private AbstractNextPreviousAction dataAction; private AbstractNextPreviousAction dataAction;
private AbstractNextPreviousAction undefinedAction; private AbstractNextPreviousAction undefinedAction;
private AbstractNextPreviousAction functionAction; private AbstractNextPreviousAction functionAction;
private AbstractNextPreviousAction nonFunctionAction;
private AbstractNextPreviousAction labelAction; private AbstractNextPreviousAction labelAction;
private NextPreviousBookmarkAction bookmarkAction; private NextPreviousBookmarkAction bookmarkAction;
private NextPreviousDifferentByteAction differentValueAction; private NextPreviousSameBytesAction sameValueAction;
public NextPrevCodeUnitPlugin(PluginTool tool) { public NextPrevCodeUnitPlugin(PluginTool tool) {
super(tool); super(tool);
@ -73,60 +75,107 @@ public class NextPrevCodeUnitPlugin extends Plugin {
} }
private void createActions() { private void createActions() {
// use this index to make sure that the following actions are ordered in the way that // use this index to ensure the actions are ordered in the way that they are inserted
// they are inserted char subGroupChar = 'a';
int subGroupIndex = 0;
toggleDirectionAction = new ToggleDirectionAction("" + subGroupIndex++); toggleDirectionAction = new ToggleDirectionAction(String.valueOf(subGroupChar++));
tool.addAction(toggleDirectionAction); tool.addAction(toggleDirectionAction);
invertStateAction = new InvertStateAction(String.valueOf(subGroupChar++));
tool.addAction(invertStateAction);
instructionAction = instructionAction =
new NextPreviousInstructionAction(tool, getName(), "" + subGroupIndex++); new NextPreviousInstructionAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(instructionAction); tool.addAction(instructionAction);
dataAction = new NextPreviousDefinedDataAction(tool, getName(), "" + subGroupIndex++); dataAction =
new NextPreviousDefinedDataAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(dataAction); tool.addAction(dataAction);
undefinedAction = new NextPreviousUndefinedAction(tool, getName(), "" + subGroupIndex++); undefinedAction =
new NextPreviousUndefinedAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(undefinedAction); tool.addAction(undefinedAction);
labelAction = new NextPreviousLabelAction(tool, getName(), "" + subGroupIndex++); labelAction = new NextPreviousLabelAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(labelAction); tool.addAction(labelAction);
functionAction = new NextPreviousFunctionAction(tool, getName(), "" + subGroupIndex++); functionAction =
new NextPreviousFunctionAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(functionAction); tool.addAction(functionAction);
nonFunctionAction = sameValueAction =
new NextPreviousNonFunctionAction(tool, getName(), "" + subGroupIndex++); new NextPreviousSameBytesAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(nonFunctionAction); tool.addAction(sameValueAction);
differentValueAction = bookmarkAction =
new NextPreviousDifferentByteAction(tool, getName(), "" + subGroupIndex++); new NextPreviousBookmarkAction(tool, getName(), String.valueOf(subGroupChar++));
tool.addAction(differentValueAction);
bookmarkAction = new NextPreviousBookmarkAction(tool, getName(), "" + subGroupIndex++);
tool.addAction(bookmarkAction); tool.addAction(bookmarkAction);
} }
private void updateActions(boolean searchForward) { private void updateActionsDirection(boolean searchForward) {
instructionAction.setDirection(searchForward); instructionAction.setDirection(searchForward);
dataAction.setDirection(searchForward); dataAction.setDirection(searchForward);
undefinedAction.setDirection(searchForward); undefinedAction.setDirection(searchForward);
functionAction.setDirection(searchForward); functionAction.setDirection(searchForward);
nonFunctionAction.setDirection(searchForward);
labelAction.setDirection(searchForward); labelAction.setDirection(searchForward);
differentValueAction.setDirection(searchForward); sameValueAction.setDirection(searchForward);
bookmarkAction.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 { private class ToggleDirectionAction extends NavigatableContextAction {
Icon forwardIcon = ResourceManager.loadImage("images/down.png"); private final Icon FORWARD_ICON = ResourceManager.loadImage("images/down.png");
Icon backwardIcon = ResourceManager.loadImage("images/up.png"); private final Icon BACKWARD_ICON = ResourceManager.loadImage("images/up.png");
private boolean isForward = true; private boolean isForward = true;
ToggleDirectionAction(String subGroup) { ToggleDirectionAction(String subGroup) {
super("Toggle Search Direction", NextPrevCodeUnitPlugin.this.getName()); super("Toggle Search Direction", NextPrevCodeUnitPlugin.this.getName());
setToolBarData(new ToolBarData(forwardIcon, setToolBarData(new ToolBarData(FORWARD_ICON,
ToolConstants.TOOLBAR_GROUP_FOUR, subGroup)); ToolConstants.TOOLBAR_GROUP_FOUR, subGroup));
setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK | setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK |
InputEvent.ALT_DOWN_MASK)); InputEvent.ALT_DOWN_MASK));
@ -136,14 +185,13 @@ public class NextPrevCodeUnitPlugin extends Plugin {
new HelpLocation(HelpTopics.NAVIGATION, longName)); new HelpLocation(HelpTopics.NAVIGATION, longName));
setDescription(longName); setDescription(longName);
addToWindowWhen(NavigatableActionContext.class); addToWindowWhen(NavigatableActionContext.class);
} }
@Override @Override
public void actionPerformed(NavigatableActionContext context) { public void actionPerformed(NavigatableActionContext context) {
isForward = !isForward; isForward = !isForward;
getToolBarData().setIcon(isForward ? forwardIcon : backwardIcon); getToolBarData().setIcon(isForward ? FORWARD_ICON : BACKWARD_ICON);
updateActions(isForward); updateActionsDirection(isForward);
} }
} }
} }

View file

@ -18,8 +18,7 @@ package ghidra.app.plugin.core.navigation;
import java.awt.event.*; import java.awt.event.*;
import java.util.Iterator; import java.util.Iterator;
import javax.swing.ImageIcon; import javax.swing.*;
import javax.swing.KeyStroke;
import docking.ActionContext; import docking.ActionContext;
import docking.action.*; import docking.action.*;
@ -27,6 +26,7 @@ import docking.menu.ActionState;
import docking.menu.MultiStateDockingAction; import docking.menu.MultiStateDockingAction;
import docking.tool.ToolConstants; import docking.tool.ToolConstants;
import docking.widgets.EventTrigger; import docking.widgets.EventTrigger;
import generic.util.image.ImageUtils;
import ghidra.app.context.ListingActionContext; import ghidra.app.context.ListingActionContext;
import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableActionContext;
import ghidra.app.nav.Navigatable; import ghidra.app.nav.Navigatable;
@ -38,29 +38,42 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.Swing; import ghidra.util.Swing;
import resources.ResourceManager; import resources.*;
public class NextPreviousBookmarkAction extends MultiStateDockingAction<String> { public class NextPreviousBookmarkAction extends MultiStateDockingAction<String> {
private boolean isForward = true;
private PluginTool tool;
private static ImageIcon bookmarkIcon = ResourceManager.loadImage("images/B.gif"); public static final String ALL_BOOKMARK_TYPES = "All Bookmark Types";
private static ImageIcon bookmarkAnalysisIcon =
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"); ResourceManager.loadImage("images/applications-system.png");
private static ImageIcon bookmarkErrorIcon = private static final ImageIcon BOOKMARK_ERROR_ICON =
ResourceManager.loadImage("images/edit-delete.png"); ResourceManager.loadImage("images/edit-delete.png");
private static ImageIcon bookmarkInfoIcon = ResourceManager.loadImage("images/information.png"); private static final ImageIcon BOOKMARK_INFO_ICON =
private static ImageIcon bookmarkNoteIcon = ResourceManager.loadImage("images/notes.gif"); ResourceManager.loadImage("images/information.png");
private static ImageIcon bookmarkWarningIcon = ResourceManager.loadImage("images/warning.png"); private static final ImageIcon BOOKMARK_NOTE_ICON =
private static ImageIcon bookmarkUnknownIcon = ResourceManager.loadImage("images/unknown.gif"); 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) { public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {
super("Next Bookmark", owner); super("Next Bookmark", owner);
this.tool = tool; this.tool = tool;
setSupportsDefaultToolContext(true); setSupportsDefaultToolContext(true);
ToolBarData toolBarData = ToolBarData toolBarData =
new ToolBarData(bookmarkIcon, ToolConstants.TOOLBAR_GROUP_FOUR); new ToolBarData(BOOKMARK_ICON, ToolConstants.TOOLBAR_GROUP_FOUR);
toolBarData.setToolBarSubGroup(subGroup); toolBarData.setToolBarSubGroup(subGroup);
setToolBarData(toolBarData); setToolBarData(toolBarData);
@ -71,16 +84,16 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
setDescription("Set bookmark options"); setDescription("Set bookmark options");
ActionState<String> allBookmarks = ActionState<String> allBookmarks =
new ActionState<>("All Types", bookmarkIcon, BookmarkType.ALL_TYPES); new ActionState<>("All Types", BOOKMARK_ICON, ALL_BOOKMARK_TYPES);
ActionState<String> analysis = ActionState<String> analysis =
new ActionState<>("Analysis", bookmarkAnalysisIcon, BookmarkType.ANALYSIS); new ActionState<>("Analysis", BOOKMARK_ANALYSIS_ICON, BookmarkType.ANALYSIS);
ActionState<String> error = ActionState<String> error =
new ActionState<>("Error", bookmarkErrorIcon, BookmarkType.ERROR); new ActionState<>("Error", BOOKMARK_ERROR_ICON, BookmarkType.ERROR);
ActionState<String> info = new ActionState<>("Info", bookmarkInfoIcon, BookmarkType.INFO); ActionState<String> info = new ActionState<>("Info", BOOKMARK_INFO_ICON, BookmarkType.INFO);
ActionState<String> note = new ActionState<>("Note", bookmarkNoteIcon, BookmarkType.NOTE); ActionState<String> note = new ActionState<>("Note", BOOKMARK_NOTE_ICON, BookmarkType.NOTE);
ActionState<String> warning = ActionState<String> warning =
new ActionState<>("Warning", bookmarkWarningIcon, BookmarkType.WARNING); new ActionState<>("Warning", BOOKMARK_WARNING_ICON, BookmarkType.WARNING);
ActionState<String> custom = new ActionState<>("Custom", bookmarkUnknownIcon, "Custom"); ActionState<String> custom = new ActionState<>("Custom", BOOKMARK_UNKNOWN_ICON, "Custom");
addActionState(allBookmarks); addActionState(allBookmarks);
addActionState(analysis); addActionState(analysis);
@ -110,19 +123,122 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
@Override @Override
public void actionStateChanged(ActionState<String> newActionState, EventTrigger trigger) { 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) { private Address getNextAddress(Program program, Address address, String bookmarkType) {
Address start = getNextAddressToBeginSearchingForward(program, address);
Bookmark nextBookmark = getNextBookmark(program, start, true, bookmarkType); if (isInverted) {
return nextBookmark == null ? null : nextBookmark.getAddress(); return getNextAddressOfNonBookmark(program, address, bookmarkType);
}
return getAddressOfNextBookmarkAfter(program, address, bookmarkType);
} }
private Address getPreviousAddress(Program program, Address address, String 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); 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(); return nextBookmark == null ? null : nextBookmark.getAddress();
} }
@ -150,19 +266,19 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
return cu; return cu;
} }
private Bookmark getNextBookmark(Program program, Address address, boolean forward, private Bookmark getNextPreviousBookmark(Program program, Address address, boolean forward,
String bookmarkType) { String bookmarkType) {
BookmarkManager bookmarkManager = program.getBookmarkManager();
Iterator<Bookmark> bookmarkIterator = BookmarkManager bm = program.getBookmarkManager();
bookmarkManager.getBookmarksIterator(address, forward); Iterator<Bookmark> it = bm.getBookmarksIterator(address, forward);
while (bookmarkIterator.hasNext()) { while (it.hasNext()) {
Bookmark nextBookmark = bookmarkIterator.next(); Bookmark nextBookmark = it.next();
Address nextAddress = nextBookmark.getAddress(); Address nextAddress = nextBookmark.getAddress();
if (nextAddress.isExternalAddress()) { if (nextAddress.isExternalAddress()) {
continue; continue;
} }
if (bookmarkType.equals(BookmarkType.ALL_TYPES)) { if (bookmarkType.equals(ALL_BOOKMARK_TYPES)) {
return nextBookmark; return nextBookmark;
} }
else if (bookmarkType.equals("Custom") && else if (bookmarkType.equals("Custom") &&
@ -172,12 +288,10 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
else if (nextBookmark.getTypeString().equals(bookmarkType)) { else if (nextBookmark.getTypeString().equals(bookmarkType)) {
return nextBookmark; return nextBookmark;
} }
} }
if (!bookmarkIterator.hasNext()) { return null;
return null;
}
return bookmarkIterator.next();
} }
private boolean isNotBuiltInType(Address address, Bookmark nextBookmark, Address nextAddress) { private boolean isNotBuiltInType(Address address, Bookmark nextBookmark, Address nextAddress) {
@ -231,10 +345,31 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
setDescription(getToolTipText()); 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 @Override
public String getToolTipText() { public String getToolTipText() {
String description = "Go To " + (isForward ? "Next" : "Previous"); 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)"; description += " (shift-click inverts direction)";
return description; return description;
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/ */
package ghidra.app.plugin.core.navigation; 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.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.KeyStroke; 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; import resources.ResourceManager;
public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction { public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
@ -52,28 +50,49 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
InputEvent.ALT_DOWN_MASK); InputEvent.ALT_DOWN_MASK);
} }
/**
* Find the beginning of the next instruction range
*/
@Override @Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getNextNonDataAddress(monitor, program, address);
}
if (isDefinedDataAt(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); address = getAddressOfNextPreviousNonDefinedData(monitor, program, address, true);
} }
// we know address is not an instruction at this point // we know address is not an instruction at this point
return getAddressOfNextDataAfter(program, address); 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 @Override
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address) protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getPreviousNonDataAddress(monitor, program, address);
}
if (isDefinedDataAt(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); address = getAddressOfNextPreviousNonDefinedData(monitor, program, address, false);
} }
@ -82,6 +101,22 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
return getAddressOfPreviousDataBefore(program, address); 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) { private boolean isDefinedDataAt(Program program, Address address) {
if (address == null) { if (address == null) {
return false; return false;

View file

@ -25,6 +25,7 @@ import ghidra.app.nav.Navigatable;
import ghidra.app.services.GoToService; import ghidra.app.services.GoToService;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.util.FunctionSignatureFieldLocation; import ghidra.program.util.FunctionSignatureFieldLocation;
import ghidra.util.exception.CancelledException; import ghidra.util.exception.CancelledException;
@ -53,15 +54,19 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
return "Function"; return "Function";
} }
/** @Override
* Find the beginning of the next instruction range protected String getInvertedNavigationTypeName() {
* @throws CancelledException return "Instruction Not In a Function";
*/ }
@Override @Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { 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(); return nextFunction == null ? null : nextFunction.getEntryPoint();
} }
@ -69,15 +74,68 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address) protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getPreviousNonFunctionAddress(monitor, program, address);
}
Function function = program.getListing().getFunctionContaining(address); Function function = program.getListing().getFunctionContaining(address);
if (isInsideFunctionNotAtEntry(function, address)) { if (isInsideFunctionNotAtEntry(function, address)) {
return function.getEntryPoint(); return function.getEntryPoint();
} }
Function nextFunction = getNextFunction(program, address, false); Function nextFunction = getNextFunctionNotAtAddress(program, address, false);
return nextFunction == null ? null : nextFunction.getEntryPoint(); 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) { private boolean isInsideFunctionNotAtEntry(Function function, Address address) {
if (function == null) { if (function == null) {
return false; return false;
@ -90,6 +148,15 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
if (!functionIterator.hasNext()) { if (!functionIterator.hasNext()) {
return null; 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(); Function nextFunction = functionIterator.next();
if (!nextFunction.getEntryPoint().equals(address)) { if (!nextFunction.getEntryPoint().equals(address)) {
return nextFunction; return nextFunction;
@ -102,6 +169,11 @@ public class NextPreviousFunctionAction extends AbstractNextPreviousAction {
@Override @Override
protected void gotoAddress(GoToService service, Navigatable navigatable, Address address) { protected void gotoAddress(GoToService service, Navigatable navigatable, Address address) {
if (isInverted) {
service.goTo(navigatable, address);
return;
}
Program program = navigatable.getProgram(); Program program = navigatable.getProgram();
Function function = program.getListing().getFunctionAt(address); Function function = program.getListing().getFunctionAt(address);
FunctionSignatureFieldLocation location = new FunctionSignatureFieldLocation(program, FunctionSignatureFieldLocation location = new FunctionSignatureFieldLocation(program,

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/ */
package ghidra.app.plugin.core.navigation; 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.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.KeyStroke; 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; import resources.ResourceManager;
public class NextPreviousInstructionAction extends AbstractNextPreviousAction { public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
@ -52,21 +50,20 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
return "Instruction"; return "Instruction";
} }
/**
* Find the beginning of the next instruction range
* @throws CancelledException
*/
@Override @Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getNextNonInstructionAddress(monitor, program, address);
}
if (isInstructionAt(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); address = getAddressOfNextPreviousNonInstruction(monitor, program, address, true);
} }
// we know address is not an instruction at this point // we know address is not an instruction at this point
return getAddressOfNextInstructionAfter(program, address); return getAddressOfNextInstructionAfter(program, address);
} }
@ -74,16 +71,51 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address) protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getPreviousNonInstructionAddress(monitor, program, address);
}
if (isInstructionAt(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); address = getAddressOfNextPreviousNonInstruction(monitor, program, address, false);
} }
// we know address is not at an instruction at this point // we know address is not at an instruction at this point
return getAddressOfPreviousInstructionBefore(program, address); 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) { private boolean isInstructionAt(Program program, Address address) {
if (address == null) { if (address == null) {
return false; return false;
@ -116,6 +148,10 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
private Address getAddressOfNextPreviousNonInstruction(TaskMonitor monitor, Program program, private Address getAddressOfNextPreviousNonInstruction(TaskMonitor monitor, Program program,
Address address, boolean forward) throws CancelledException { Address address, boolean forward) throws CancelledException {
if (address == null) {
return null;
}
CodeUnitIterator codeUnits = program.getListing().getCodeUnits(address, forward); CodeUnitIterator codeUnits = program.getListing().getCodeUnits(address, forward);
while (codeUnits.hasNext()) { while (codeUnits.hasNext()) {
monitor.checkCanceled(); monitor.checkCanceled();

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,21 +15,19 @@
*/ */
package ghidra.app.plugin.core.navigation; 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.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.KeyStroke; 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; import resources.ResourceManager;
public class NextPreviousLabelAction extends AbstractNextPreviousAction { public class NextPreviousLabelAction extends AbstractNextPreviousAction {
@ -59,6 +56,10 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getNextNonLabel(monitor, program, address);
}
address = getAddressOfNextCodeUnit(program, address); address = getAddressOfNextCodeUnit(program, address);
return getAddressOfNextPreviousLabel(program, address, true); return getAddressOfNextPreviousLabel(program, address, true);
} }
@ -67,10 +68,71 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address) protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getPreviousNonLabel(monitor, program, address);
}
address = getAddressOfPreviousCodeUnit(program, address); address = getAddressOfPreviousCodeUnit(program, address);
return getAddressOfNextPreviousLabel(program, address, false); 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) { private Address getAddressOfNextCodeUnit(Program program, Address address) {
CodeUnit cu = program.getListing().getCodeUnitAfter(address); CodeUnit cu = program.getListing().getCodeUnitAfter(address);
if (cu == null) { if (cu == null) {
@ -87,7 +149,8 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
return cu.getAddress(); return cu.getAddress();
} }
private Address getAddressOfNextPreviousLabel(Program program, Address address, boolean forward) { private Address getAddressOfNextPreviousLabel(Program program, Address address,
boolean forward) {
if (address == null) { if (address == null) {
return null; return null;
@ -95,7 +158,6 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
Address nextDefinedLableAddress = getNextDefinedLableAddress(program, address, forward); Address nextDefinedLableAddress = getNextDefinedLableAddress(program, address, forward);
Address nextReferenceToAddress = getNextReferenceToAddress(program, address, forward); Address nextReferenceToAddress = getNextReferenceToAddress(program, address, forward);
if (nextDefinedLableAddress == null) { if (nextDefinedLableAddress == null) {
return nextReferenceToAddress; return nextReferenceToAddress;
} }
@ -104,11 +166,9 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
} }
int compare = nextDefinedLableAddress.compareTo(nextReferenceToAddress); int compare = nextDefinedLableAddress.compareTo(nextReferenceToAddress);
if (forward) { if (forward) {
return compare <= 0 ? nextDefinedLableAddress : nextReferenceToAddress; return compare <= 0 ? nextDefinedLableAddress : nextReferenceToAddress;
} }
return compare >= 0 ? nextDefinedLableAddress : nextReferenceToAddress; return compare >= 0 ? nextDefinedLableAddress : nextReferenceToAddress;
} }

View file

@ -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);
}
}

View file

@ -15,17 +15,6 @@
*/ */
package ghidra.app.plugin.core.navigation; 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.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.Iterator; import java.util.Iterator;
@ -33,22 +22,35 @@ import java.util.Iterator;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.KeyStroke; 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; 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) { private static final Icon ICON = ResourceManager.loadImage("images/V.png");
super(tool, "Next Different Byte Value", owner, subGroup);
}
@Override NextPreviousSameBytesAction(PluginTool tool, String owner, String subGroup) {
protected String getNavigationTypeName() { super(tool, "Next Matching Byte Values", owner, subGroup);
return "Different Byte Value";
} }
@Override @Override
protected Icon getIcon() { protected Icon getIcon() {
return ResourceManager.loadImage("images/V_slash.png"); return ICON;
} }
@Override @Override
@ -57,13 +59,24 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
InputEvent.ALT_DOWN_MASK); InputEvent.ALT_DOWN_MASK);
} }
/** @Override
* Find the beginning of the next instruction range protected String getNavigationTypeName() {
*/ return "Same Bytes Value";
}
@Override
protected String getInvertedNavigationTypeName() {
return "Different Bytes Value";
}
@Override @Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getNextPreviousDifferentByteValueAddress(monitor, program, address, true);
}
return getNextPreviousAddress(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) protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getNextPreviousDifferentByteValueAddress(monitor, program, address, false);
}
return getNextPreviousAddress(monitor, program, address, false); return getNextPreviousAddress(monitor, program, address, false);
} }
protected Address getNextPreviousAddress(TaskMonitor monitor, Program program, Address address, private Address getNextPreviousDifferentByteValueAddress(TaskMonitor monitor, Program program,
boolean forward) throws CancelledException { Address address, boolean forward) throws CancelledException {
byte value = 0; byte value = 0;
try { try {
value = program.getMemory().getByte(address); value = program.getMemory().getByte(address);
@ -114,6 +130,55 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
return null; 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) { private CodeUnit getNextPreviousCodeUnit(Program program, Address address, boolean forward) {
if (forward) { if (forward) {
return program.getListing().getDefinedCodeUnitAfter(address); return program.getListing().getDefinedCodeUnitAfter(address);

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/ */
package ghidra.app.plugin.core.navigation; 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.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.KeyStroke; 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; import resources.ResourceManager;
public class NextPreviousUndefinedAction extends AbstractNextPreviousAction { public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
@ -52,21 +50,20 @@ public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
return "Undefined"; return "Undefined";
} }
/**
* Find the beginning of the next instruction range
* @throws CancelledException
*/
@Override @Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address) protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getNextNonUndefined(monitor, program, address);
}
if (isUndefinedAt(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); 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); return getAddressOfNextPreviousUndefined(monitor, program, address, true);
} }
@ -74,16 +71,51 @@ public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address) protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException { throws CancelledException {
if (isInverted) {
return getPreviousNonUndefined(monitor, program, address);
}
if (isUndefinedAt(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); 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); 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) { private boolean isUndefinedAt(Program program, Address address) {
if (address == null) { if (address == null) {
return false; return false;

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

View file

@ -659,7 +659,9 @@ public class BookmarkPluginTest extends AbstractGhidraHeadedIntegrationTest {
BookmarkManager bm = program.getBookmarkManager(); BookmarkManager bm = program.getBookmarkManager();
tx(program, () -> { tx(program, () -> {
bm.removeBookmarks(BookmarkType.ALL_TYPES); bm.removeBookmarks("Type1");
bm.removeBookmarks("Type2");
bm.removeBookmarks("Type3");
}); });
list = getBookmarks(program.getBookmarkManager()); list = getBookmarks(program.getBookmarkManager());

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,24 +27,29 @@ public class TranslateIcon implements Icon {
int translateX; int translateX;
int translateY; 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) { public TranslateIcon(Icon icon, int translateX, int translateY) {
this.icon = icon; this.icon = icon;
this.translateX = translateX; this.translateX = translateX;
this.translateY = translateY; this.translateY = translateY;
} }
/** @Override
* @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics, int, int)
*/
public void paintIcon(Component c, Graphics g, int x, int y) { public void paintIcon(Component c, Graphics g, int x, int y) {
icon.paintIcon(c, g, x + translateX, y + translateY); icon.paintIcon(c, g, x + translateX, y + translateY);
} }
@Override
public int getIconHeight() { public int getIconHeight() {
return icon.getIconHeight(); return icon.getIconHeight();
} }
@Override
public int getIconWidth() { public int getIconWidth() {
return icon.getIconWidth(); return icon.getIconWidth();
} }

View file

@ -31,12 +31,9 @@ import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.program.model.util.PropertyMap; import ghidra.program.model.util.PropertyMap;
import ghidra.util.exception.*; import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
/** /**
* Database implementation of Listing. * Database implementation of Listing.
*
*
*/ */
class ListingDB implements Listing { class ListingDB implements Listing {
@ -45,9 +42,6 @@ class ListingDB implements Listing {
private TreeManager treeMgr; private TreeManager treeMgr;
private FunctionManager functionMgr; private FunctionManager functionMgr;
/**
* Set the program.
*/
public void setProgram(ProgramDB program) { public void setProgram(ProgramDB program) {
this.program = program; this.program = program;
codeMgr = program.getCodeManager(); codeMgr = program.getCodeManager();
@ -55,261 +49,165 @@ class ListingDB implements Listing {
functionMgr = program.getFunctionManager(); functionMgr = program.getFunctionManager();
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitAt(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnit getCodeUnitAt(Address addr) { public CodeUnit getCodeUnitAt(Address addr) {
return codeMgr.getCodeUnitAt(addr); return codeMgr.getCodeUnitAt(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitContaining(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnit getCodeUnitContaining(Address addr) { public CodeUnit getCodeUnitContaining(Address addr) {
return codeMgr.getCodeUnitContaining(addr); return codeMgr.getCodeUnitContaining(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitAfter(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnit getCodeUnitAfter(Address addr) { public CodeUnit getCodeUnitAfter(Address addr) {
return codeMgr.getCodeUnitAfter(addr); return codeMgr.getCodeUnitAfter(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitBefore(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnit getCodeUnitBefore(Address addr) { public CodeUnit getCodeUnitBefore(Address addr) {
return codeMgr.getCodeUnitBefore(addr); return codeMgr.getCodeUnitBefore(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitIterator(java.lang.String)
*/
@Override @Override
public CodeUnitIterator getCodeUnitIterator(String property, boolean forward) { public CodeUnitIterator getCodeUnitIterator(String property, boolean forward) {
return codeMgr.getCodeUnitIterator(property, program.getMinAddress(), forward); return codeMgr.getCodeUnitIterator(property, program.getMinAddress(), forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitIterator(java.lang.String, ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnitIterator getCodeUnitIterator(String property, Address addr, boolean forward) { public CodeUnitIterator getCodeUnitIterator(String property, Address addr, boolean forward) {
return codeMgr.getCodeUnitIterator(property, addr, forward); return codeMgr.getCodeUnitIterator(property, addr, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnitIterator(java.lang.String, ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public CodeUnitIterator getCodeUnitIterator(String property, AddressSetView addrSet, public CodeUnitIterator getCodeUnitIterator(String property, AddressSetView addrSet,
boolean forward) { boolean forward) {
return codeMgr.getCodeUnitIterator(property, addrSet, forward); return codeMgr.getCodeUnitIterator(property, addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnits()
*/
@Override @Override
public CodeUnitIterator getCodeUnits(boolean forward) { public CodeUnitIterator getCodeUnits(boolean forward) {
return codeMgr.getCodeUnits(program.getMemory(), forward); return codeMgr.getCodeUnits(program.getMemory(), forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnits(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnitIterator getCodeUnits(Address addr, boolean forward) { public CodeUnitIterator getCodeUnits(Address addr, boolean forward) {
return codeMgr.getCodeUnits(addr, forward); return codeMgr.getCodeUnits(addr, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCodeUnits(ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public CodeUnitIterator getCodeUnits(AddressSetView addrSet, boolean forward) { public CodeUnitIterator getCodeUnits(AddressSetView addrSet, boolean forward) {
return codeMgr.getCodeUnits(addrSet, forward); return codeMgr.getCodeUnits(addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructionAt(ghidra.program.model.address.Address)
*/
@Override @Override
public Instruction getInstructionAt(Address addr) { public Instruction getInstructionAt(Address addr) {
return codeMgr.getInstructionAt(addr); return codeMgr.getInstructionAt(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructionContaining(ghidra.program.model.address.Address)
*/
@Override @Override
public Instruction getInstructionContaining(Address addr) { public Instruction getInstructionContaining(Address addr) {
return codeMgr.getInstructionContaining(addr); return codeMgr.getInstructionContaining(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructionAfter(ghidra.program.model.address.Address)
*/
@Override @Override
public Instruction getInstructionAfter(Address addr) { public Instruction getInstructionAfter(Address addr) {
return codeMgr.getInstructionAfter(addr); return codeMgr.getInstructionAfter(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructionBefore(ghidra.program.model.address.Address)
*/
@Override @Override
public Instruction getInstructionBefore(Address addr) { public Instruction getInstructionBefore(Address addr) {
return codeMgr.getInstructionBefore(addr); return codeMgr.getInstructionBefore(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructions()
*/
@Override @Override
public InstructionIterator getInstructions(boolean forward) { public InstructionIterator getInstructions(boolean forward) {
return codeMgr.getInstructions(forward ? program.getMinAddress() : program.getMaxAddress(), return codeMgr.getInstructions(forward ? program.getMinAddress() : program.getMaxAddress(),
forward); forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructions(ghidra.program.model.address.Address)
*/
@Override @Override
public InstructionIterator getInstructions(Address addr, boolean forward) { public InstructionIterator getInstructions(Address addr, boolean forward) {
return codeMgr.getInstructions(addr, forward); return codeMgr.getInstructions(addr, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getInstructions(ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public InstructionIterator getInstructions(AddressSetView addrSet, boolean forward) { public InstructionIterator getInstructions(AddressSetView addrSet, boolean forward) {
return codeMgr.getInstructions(addrSet, forward); return codeMgr.getInstructions(addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getDataAt(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDataAt(Address addr) { public Data getDataAt(Address addr) {
return codeMgr.getDataAt(addr); return codeMgr.getDataAt(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDataContaining(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDataContaining(Address addr) { public Data getDataContaining(Address addr) {
return codeMgr.getDataContaining(addr); return codeMgr.getDataContaining(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDataAfter(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDataAfter(Address addr) { public Data getDataAfter(Address addr) {
return codeMgr.getDataAfter(addr); return codeMgr.getDataAfter(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDataBefore(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDataBefore(Address addr) { public Data getDataBefore(Address addr) {
return codeMgr.getDataBefore(addr); return codeMgr.getDataBefore(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getData()
*/
@Override @Override
public DataIterator getData(boolean forward) { public DataIterator getData(boolean forward) {
return codeMgr.getData(forward ? program.getMinAddress() : program.getMaxAddress(), return codeMgr.getData(forward ? program.getMinAddress() : program.getMaxAddress(),
forward); forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getData(ghidra.program.model.address.Address)
*/
@Override @Override
public DataIterator getData(Address addr, boolean forward) { public DataIterator getData(Address addr, boolean forward) {
return codeMgr.getData(addr, forward); return codeMgr.getData(addr, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getData(ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public DataIterator getData(AddressSetView addrSet, boolean forward) { public DataIterator getData(AddressSetView addrSet, boolean forward) {
return codeMgr.getData(addrSet, forward); return codeMgr.getData(addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedDataAt(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDefinedDataAt(Address addr) { public Data getDefinedDataAt(Address addr) {
return codeMgr.getDefinedDataAt(addr); return codeMgr.getDefinedDataAt(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedDataContaining(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDefinedDataContaining(Address addr) { public Data getDefinedDataContaining(Address addr) {
return codeMgr.getDefinedDataContaining(addr); return codeMgr.getDefinedDataContaining(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedDataAfter(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDefinedDataAfter(Address addr) { public Data getDefinedDataAfter(Address addr) {
return codeMgr.getDefinedDataAfter(addr); return codeMgr.getDefinedDataAfter(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedDataBefore(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getDefinedDataBefore(Address addr) { public Data getDefinedDataBefore(Address addr) {
return codeMgr.getDefinedDataBefore(addr); return codeMgr.getDefinedDataBefore(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedData()
*/
@Override @Override
public DataIterator getDefinedData(boolean forward) { public DataIterator getDefinedData(boolean forward) {
return codeMgr.getDefinedData(forward ? program.getMinAddress() : program.getMaxAddress(), return codeMgr.getDefinedData(forward ? program.getMinAddress() : program.getMaxAddress(),
forward); forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedData(ghidra.program.model.address.Address)
*/
@Override @Override
public DataIterator getDefinedData(Address addr, boolean forward) { public DataIterator getDefinedData(Address addr, boolean forward) {
return codeMgr.getDefinedData(addr, forward); return codeMgr.getDefinedData(addr, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedData(ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public DataIterator getDefinedData(AddressSetView addrSet, boolean forward) { public DataIterator getDefinedData(AddressSetView addrSet, boolean forward) {
return codeMgr.getDefinedData(addrSet, forward); return codeMgr.getDefinedData(addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getUndefinedDataAt(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getUndefinedDataAt(Address addr) { public Data getUndefinedDataAt(Address addr) {
return codeMgr.getUndefinedAt(addr); return codeMgr.getUndefinedAt(addr);
@ -321,295 +219,190 @@ class ListingDB implements Listing {
return codeMgr.getUndefinedRanges(set, initializedMemoryOnly, monitor); return codeMgr.getUndefinedRanges(set, initializedMemoryOnly, monitor);
} }
/**
* @see ghidra.program.model.listing.Listing#getUndefinedDataAfter(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getUndefinedDataAfter(Address addr, TaskMonitor monitor) { public Data getUndefinedDataAfter(Address addr, TaskMonitor monitor) {
return codeMgr.getFirstUndefinedDataAfter(addr, monitor); return codeMgr.getFirstUndefinedDataAfter(addr, monitor);
} }
/**
* @see ghidra.program.model.listing.Listing#getFirstUndefinedData(ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public Data getFirstUndefinedData(AddressSetView set, TaskMonitor monitor) { public Data getFirstUndefinedData(AddressSetView set, TaskMonitor monitor) {
return codeMgr.getFirstUndefinedData(set, monitor); return codeMgr.getFirstUndefinedData(set, monitor);
} }
/**
* @see ghidra.program.model.listing.Listing#getUndefinedDataBefore(ghidra.program.model.address.Address)
*/
@Override @Override
public Data getUndefinedDataBefore(Address addr, TaskMonitor monitor) { public Data getUndefinedDataBefore(Address addr, TaskMonitor monitor) {
return codeMgr.getFirstUndefinedDataBefore(addr, monitor); return codeMgr.getFirstUndefinedDataBefore(addr, monitor);
} }
/**
* @see ghidra.program.model.listing.Listing#getCompositeData()
*/
@Override @Override
public DataIterator getCompositeData(boolean forward) { public DataIterator getCompositeData(boolean forward) {
return codeMgr.getCompositeData(forward ? program.getMinAddress() : program.getMaxAddress(), return codeMgr.getCompositeData(forward ? program.getMinAddress() : program.getMaxAddress(),
forward); forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCompositeData(ghidra.program.model.address.Address)
*/
@Override @Override
public DataIterator getCompositeData(Address start, boolean forward) { public DataIterator getCompositeData(Address start, boolean forward) {
return codeMgr.getCompositeData(start, forward); return codeMgr.getCompositeData(start, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCompositeData(ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) { public DataIterator getCompositeData(AddressSetView addrSet, boolean forward) {
return codeMgr.getCompositeData(addrSet, forward); return codeMgr.getCompositeData(addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getUserDefinedProperties()
*/
@Override @Override
public Iterator<String> getUserDefinedProperties() { public Iterator<String> getUserDefinedProperties() {
return codeMgr.getUserDefinedProperties(); return codeMgr.getUserDefinedProperties();
} }
/**
* @see ghidra.program.model.listing.Listing#removeUserDefinedProperty(java.lang.String)
*/
@Override @Override
public void removeUserDefinedProperty(String propertyName) { public void removeUserDefinedProperty(String propertyName) {
codeMgr.removeUserDefinedProperty(propertyName); codeMgr.removeUserDefinedProperty(propertyName);
} }
/**
* @see ghidra.program.model.listing.Listing#getPropertyMap(java.lang.String)
*/
@Override @Override
public PropertyMap getPropertyMap(String propertyName) { public PropertyMap getPropertyMap(String propertyName) {
return codeMgr.getPropertyMap(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 @Override
public Instruction createInstruction(Address addr, InstructionPrototype prototype, public Instruction createInstruction(Address addr, InstructionPrototype prototype,
MemBuffer memBuf, ProcessorContextView context) throws CodeUnitInsertionException { MemBuffer memBuf, ProcessorContextView context) throws CodeUnitInsertionException {
return codeMgr.createCodeUnit(addr, prototype, memBuf, context); return codeMgr.createCodeUnit(addr, prototype, memBuf, context);
} }
/**
* @see ghidra.program.model.listing.Listing#addInstructions(ghidra.program.model.lang.InstructionSet, boolean)
*/
@Override @Override
public AddressSetView addInstructions(InstructionSet instructionSet, boolean overwrite) public AddressSetView addInstructions(InstructionSet instructionSet, boolean overwrite)
throws CodeUnitInsertionException { throws CodeUnitInsertionException {
return codeMgr.addInstructions(instructionSet, overwrite); return codeMgr.addInstructions(instructionSet, overwrite);
} }
/**
*
* @see ghidra.program.model.listing.Listing#createData(ghidra.program.model.address.Address, ghidra.program.model.data.DataType)
*/
@Override @Override
public Data createData(Address addr, DataType dataType) public Data createData(Address addr, DataType dataType)
throws CodeUnitInsertionException, DataTypeConflictException { throws CodeUnitInsertionException, DataTypeConflictException {
return codeMgr.createCodeUnit(addr, dataType, dataType.getLength()); 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 @Override
public Data createData(Address addr, DataType dataType, int length) public Data createData(Address addr, DataType dataType, int length)
throws CodeUnitInsertionException, DataTypeConflictException { throws CodeUnitInsertionException, DataTypeConflictException {
return codeMgr.createCodeUnit(addr, dataType, length); 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 @Override
public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext) { public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext) {
try { try {
codeMgr.clearCodeUnits(startAddr, endAddr, clearContext, codeMgr.clearCodeUnits(startAddr, endAddr, clearContext,
TaskMonitorAdapter.DUMMY_MONITOR); TaskMonitor.DUMMY);
} }
catch (CancelledException e) { 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 @Override
public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext, public void clearCodeUnits(Address startAddr, Address endAddr, boolean clearContext,
TaskMonitor monitor) throws CancelledException { TaskMonitor monitor) throws CancelledException {
codeMgr.clearCodeUnits(startAddr, endAddr, clearContext, monitor); codeMgr.clearCodeUnits(startAddr, endAddr, clearContext, monitor);
} }
/**
* @see ghidra.program.model.listing.Listing#isUndefined(ghidra.program.model.address.Address, ghidra.program.model.address.Address)
*/
@Override @Override
public boolean isUndefined(Address start, Address end) { public boolean isUndefined(Address start, Address end) {
return codeMgr.isUndefined(start, end); return codeMgr.isUndefined(start, end);
} }
/**
* @see ghidra.program.model.listing.Listing#clearComments(ghidra.program.model.address.Address, ghidra.program.model.address.Address)
*/
@Override @Override
public void clearComments(Address startAddr, Address endAddr) { public void clearComments(Address startAddr, Address endAddr) {
codeMgr.clearComments(startAddr, endAddr); codeMgr.clearComments(startAddr, endAddr);
} }
/**
* @see ghidra.program.model.listing.Listing#clearProperties(ghidra.program.model.address.Address, ghidra.program.model.address.Address)
*/
@Override @Override
public void clearProperties(Address startAddr, Address endAddr, TaskMonitor monitor) public void clearProperties(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException { throws CancelledException {
codeMgr.clearProperties(startAddr, endAddr, monitor); codeMgr.clearProperties(startAddr, endAddr, monitor);
} }
/**
* @see ghidra.program.model.listing.Listing#clearAll(boolean, TaskMonitor)
*/
@Override @Override
public void clearAll(boolean clearContext, TaskMonitor monitor) { 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 @Override
public long getNumCodeUnits() { public long getNumCodeUnits() {
return getNumDefinedData() + getNumInstructions(); return getNumDefinedData() + getNumInstructions();
} }
/**
* @see ghidra.program.model.listing.Listing#getNumDefinedData()
*/
@Override @Override
public long getNumDefinedData() { public long getNumDefinedData() {
return codeMgr.getNumDefinedData(); return codeMgr.getNumDefinedData();
} }
/**
* @see ghidra.program.model.listing.Listing#getNumInstructions()
*/
@Override @Override
public long getNumInstructions() { public long getNumInstructions() {
return codeMgr.getNumInstructions(); return codeMgr.getNumInstructions();
} }
/**
* @see ghidra.program.model.listing.Listing#getFragment(java.lang.String, ghidra.program.model.address.Address)
*/
@Override @Override
public ProgramFragment getFragment(String treeName, Address addr) { public ProgramFragment getFragment(String treeName, Address addr) {
return treeMgr.getFragment(treeName, addr); return treeMgr.getFragment(treeName, addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getModule(java.lang.String, java.lang.String)
*/
@Override @Override
public ProgramModule getModule(String treeName, String name) { public ProgramModule getModule(String treeName, String name) {
return treeMgr.getModule(treeName, name); return treeMgr.getModule(treeName, name);
} }
/**
* @see ghidra.program.model.listing.Listing#getFragment(java.lang.String, java.lang.String)
*/
@Override @Override
public ProgramFragment getFragment(String treeName, String name) { public ProgramFragment getFragment(String treeName, String name) {
return treeMgr.getFragment(treeName, name); return treeMgr.getFragment(treeName, name);
} }
/**
* @see ghidra.program.model.listing.Listing#createRootModule(java.lang.String)
*/
@Override @Override
public ProgramModule createRootModule(String treeName) throws DuplicateNameException { public ProgramModule createRootModule(String treeName) throws DuplicateNameException {
return treeMgr.createRootModule(treeName); return treeMgr.createRootModule(treeName);
} }
/**
* @see ghidra.program.model.listing.Listing#getRootModule(java.lang.String)
*/
@Override @Override
public ProgramModule getRootModule(String treeName) { public ProgramModule getRootModule(String treeName) {
return treeMgr.getRootModule(treeName); return treeMgr.getRootModule(treeName);
} }
/**
* @see ghidra.program.model.listing.Listing#getRootModule(long)
*/
@Override @Override
public ProgramModule getRootModule(long treeID) { public ProgramModule getRootModule(long treeID) {
return treeMgr.getRootModule(treeID); return treeMgr.getRootModule(treeID);
} }
/**
* @see ghidra.program.model.listing.Listing#getRootModule(long)
*/
@Override @Override
public ProgramModule getDefaultRootModule() { public ProgramModule getDefaultRootModule() {
return treeMgr.getDefaultRootModule(); return treeMgr.getDefaultRootModule();
} }
/**
* @see ghidra.program.model.listing.Listing#getTreeNames()
*/
@Override @Override
public String[] getTreeNames() { public String[] getTreeNames() {
return treeMgr.getTreeNames(); return treeMgr.getTreeNames();
} }
/**
* @see ghidra.program.model.listing.Listing#removeTree(java.lang.String)
*/
@Override @Override
public boolean removeTree(String treeName) { public boolean removeTree(String treeName) {
return treeMgr.removeTree(treeName); return treeMgr.removeTree(treeName);
} }
/**
* @see ghidra.program.model.listing.Listing#renameTree(java.lang.String, java.lang.String)
*/
@Override @Override
public void renameTree(String oldName, String newName) throws DuplicateNameException { public void renameTree(String oldName, String newName) throws DuplicateNameException {
treeMgr.renameTree(oldName, newName); treeMgr.renameTree(oldName, newName);
} }
/**
* @see ghidra.program.model.listing.Listing#getDataTypeManager()
*/
@Override @Override
public DataTypeManager getDataTypeManager() { public DataTypeManager getDataTypeManager() {
return program.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 @Override
public Function createFunction(String name, Address entryPoint, AddressSetView body, public Function createFunction(String name, Address entryPoint, AddressSetView body,
SourceType source) throws InvalidInputException, OverlappingFunctionException { SourceType source) throws InvalidInputException, OverlappingFunctionException {
return functionMgr.createFunction(name, entryPoint, body, source); 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 @Override
public Function createFunction(String name, Namespace nameSpace, Address entryPoint, public Function createFunction(String name, Namespace nameSpace, Address entryPoint,
AddressSetView body, SourceType source) AddressSetView body, SourceType source)
@ -617,17 +410,11 @@ class ListingDB implements Listing {
return functionMgr.createFunction(name, nameSpace, entryPoint, body, source); return functionMgr.createFunction(name, nameSpace, entryPoint, body, source);
} }
/**
* @see ghidra.program.model.listing.Listing#removeFunction(ghidra.program.model.address.Address)
*/
@Override @Override
public void removeFunction(Address entryPoint) { public void removeFunction(Address entryPoint) {
functionMgr.removeFunction(entryPoint); functionMgr.removeFunction(entryPoint);
} }
/**
* @see ghidra.program.model.listing.Listing#getFunctionAt(ghidra.program.model.address.Address)
*/
@Override @Override
public Function getFunctionAt(Address entryPoint) { public Function getFunctionAt(Address entryPoint) {
return functionMgr.getFunctionAt(entryPoint); return functionMgr.getFunctionAt(entryPoint);
@ -662,9 +449,6 @@ class ListingDB implements Listing {
return list; return list;
} }
/**
* @see ghidra.program.model.listing.Listing#getFirstFunctionContaining(ghidra.program.model.address.Address)
*/
@Override @Override
public Function getFunctionContaining(Address addr) { public Function getFunctionContaining(Address addr) {
return functionMgr.getFunctionContaining(addr); return functionMgr.getFunctionContaining(addr);
@ -675,90 +459,57 @@ class ListingDB implements Listing {
return functionMgr.getExternalFunctions(); return functionMgr.getExternalFunctions();
} }
/**
* @see ghidra.program.model.listing.Listing#getFunctions(boolean)
*/
@Override @Override
public FunctionIterator getFunctions(boolean forward) { public FunctionIterator getFunctions(boolean forward) {
return functionMgr.getFunctions(forward); return functionMgr.getFunctions(forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getFunctions(ghidra.program.model.address.Address, boolean)
*/
@Override @Override
public FunctionIterator getFunctions(Address start, boolean forward) { public FunctionIterator getFunctions(Address start, boolean forward) {
return functionMgr.getFunctions(start, forward); return functionMgr.getFunctions(start, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getFunctions(ghidra.program.model.address.AddressSetView, boolean)
*/
@Override @Override
public FunctionIterator getFunctions(AddressSetView asv, boolean forward) { public FunctionIterator getFunctions(AddressSetView asv, boolean forward) {
return functionMgr.getFunctions(asv, forward); return functionMgr.getFunctions(asv, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#isInFunction(ghidra.program.model.address.Address)
*/
@Override @Override
public boolean isInFunction(Address addr) { public boolean isInFunction(Address addr) {
return functionMgr.isInFunction(addr); return functionMgr.isInFunction(addr);
} }
/**
* @see ghidra.program.model.listing.Listing#getCommentHistory(ghidra.program.model.address.Address, int)
*/
@Override @Override
public CommentHistory[] getCommentHistory(Address addr, int commentType) { public CommentHistory[] getCommentHistory(Address addr, int commentType) {
return codeMgr.getCommentHistory(addr, commentType); return codeMgr.getCommentHistory(addr, commentType);
} }
/**
* @see ghidra.program.model.listing.Listing#getCommentCodeUnitIterator(int, ghidra.program.model.address.AddressSetView)
*/
@Override @Override
public CodeUnitIterator getCommentCodeUnitIterator(int commentType, AddressSetView addrSet) { public CodeUnitIterator getCommentCodeUnitIterator(int commentType, AddressSetView addrSet) {
return codeMgr.getCommentCodeUnitIterator(commentType, addrSet); return codeMgr.getCommentCodeUnitIterator(commentType, addrSet);
} }
/**
* @see ghidra.program.model.listing.Listing#getCommentAddressIterator(int, ghidra.program.model.address.AddressSetView, boolean)
*/
@Override @Override
public AddressIterator getCommentAddressIterator(int commentType, AddressSetView addrSet, public AddressIterator getCommentAddressIterator(int commentType, AddressSetView addrSet,
boolean forward) { boolean forward) {
return codeMgr.getCommentAddressIterator(commentType, addrSet, forward); return codeMgr.getCommentAddressIterator(commentType, addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getCommentAddressIterator(ghidra.program.model.address.AddressSetView, boolean)
*/
@Override @Override
public AddressIterator getCommentAddressIterator(AddressSetView addrSet, boolean forward) { public AddressIterator getCommentAddressIterator(AddressSetView addrSet, boolean forward) {
return codeMgr.getCommentAddressIterator(addrSet, forward); return codeMgr.getCommentAddressIterator(addrSet, forward);
} }
/**
* @see ghidra.program.model.listing.Listing#getComment(int, ghidra.program.model.address.Address)
*/
@Override @Override
public String getComment(int commentType, Address address) { public String getComment(int commentType, Address address) {
return codeMgr.getComment(commentType, address); return codeMgr.getComment(commentType, address);
} }
/**
* @see ghidra.program.model.listing.Listing#setComment(ghidra.program.model.address.Address, int, java.lang.String)
*/
@Override @Override
public void setComment(Address address, int commentType, String comment) { public void setComment(Address address, int commentType, String comment) {
codeMgr.setComment(address, commentType, comment); codeMgr.setComment(address, commentType, comment);
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedCodeUnitAfter(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnit getDefinedCodeUnitAfter(Address addr) { public CodeUnit getDefinedCodeUnitAfter(Address addr) {
CodeUnit data = codeMgr.getDefinedDataAfter(addr); CodeUnit data = codeMgr.getDefinedDataAfter(addr);
@ -777,9 +528,6 @@ class ListingDB implements Listing {
return inst; return inst;
} }
/**
* @see ghidra.program.model.listing.Listing#getDefinedCodeUnitBefore(ghidra.program.model.address.Address)
*/
@Override @Override
public CodeUnit getDefinedCodeUnitBefore(Address addr) { public CodeUnit getDefinedCodeUnitBefore(Address addr) {
CodeUnit data = codeMgr.getDefinedDataBefore(addr); CodeUnit data = codeMgr.getDefinedDataBefore(addr);

View file

@ -50,7 +50,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
private boolean upgrade = false; 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 ObjectArray typesArray = new ObjectArray();
private Lock lock; private Lock lock;
@ -73,7 +73,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
bookmarkTypeAdapter = BookmarkTypeDBAdapter.getAdapter(handle, openMode); bookmarkTypeAdapter = BookmarkTypeDBAdapter.getAdapter(handle, openMode);
int[] types = bookmarkTypeAdapter.getTypeIds(); int[] types = bookmarkTypeAdapter.getTypeIds();
bookmarkAdapter = BookmarkDBAdapter.getAdapter(handle, openMode, types, addrMap, monitor); bookmarkAdapter = BookmarkDBAdapter.getAdapter(handle, openMode, types, addrMap, monitor);
cache = new DBObjectCache<BookmarkDB>(100); cache = new DBObjectCache<>(100);
} }
@Override @Override
@ -388,16 +388,6 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
lock.acquire(); lock.acquire();
try { 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 { try {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesByName.get(type); BookmarkTypeDB bmt = (BookmarkTypeDB) typesByName.get(type);
if (bmt.hasBookmarks()) { if (bmt.hasBookmarks()) {
@ -474,7 +464,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
lock.acquire(); lock.acquire();
try { try {
int n = typesArray.getLastNonEmptyIndex(); int n = typesArray.getLastNonEmptyIndex();
List<Bookmark> list = new ArrayList<Bookmark>(); List<Bookmark> list = new ArrayList<>();
for (int i = 0; i <= n; i++) { for (int i = 0; i <= n; i++) {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i); BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
if (bmt != null && bmt.hasBookmarks()) { if (bmt != null && bmt.hasBookmarks()) {
@ -512,7 +502,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
lock.acquire(); lock.acquire();
try { try {
Bookmark[] bookmarks = null; Bookmark[] bookmarks = null;
List<Bookmark> list = new ArrayList<Bookmark>(); List<Bookmark> list = new ArrayList<>();
BookmarkType bmt = getBookmarkType(type); BookmarkType bmt = getBookmarkType(type);
if (bmt != null && bmt.hasBookmarks()) { if (bmt != null && bmt.hasBookmarks()) {
getBookmarks(address, bmt.getTypeId(), list); getBookmarks(address, bmt.getTypeId(), list);
@ -681,18 +671,18 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
@Override @Override
public Iterator<Bookmark> getBookmarksIterator(Address startAddress, boolean forward) { 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(); int n = typesArray.getLastNonEmptyIndex();
for (int i = 0; i <= n; i++) { for (int i = 0; i <= n; i++) {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i); BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
if (bmt != null && bmt.hasBookmarks()) { if (bmt != null && bmt.hasBookmarks()) {
Iterator<Bookmark> bookmarksIterator = Iterator<Bookmark> bookmarksIterator =
getBookmarksIterator(startAddress, bmt, forward); 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 @Override
@ -880,7 +870,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
Iterator<Bookmark> bookmarkIt; Iterator<Bookmark> bookmarkIt;
TotalIterator() { TotalIterator() {
List<BookmarkTypeDB> list = new ArrayList<BookmarkTypeDB>(); List<BookmarkTypeDB> list = new ArrayList<>();
int n = typesArray.getLastNonEmptyIndex(); int n = typesArray.getLastNonEmptyIndex();
for (int i = 0; i <= n; i++) { for (int i = 0; i <= n; i++) {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i); BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);

View file

@ -21,7 +21,7 @@ import ghidra.program.model.address.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
/** /**
* Combines an Instruction iterator and Data iterator into a codeunit iterator * Combines an Instruction iterator and Data iterator into a code unit iterator
*/ */
class CodeUnitRecordIterator implements CodeUnitIterator { class CodeUnitRecordIterator implements CodeUnitIterator {
@ -38,7 +38,7 @@ class CodeUnitRecordIterator implements CodeUnitIterator {
/** /**
* Constructs a new CodeUnitRecordIterator * Constructs a new CodeUnitRecordIterator
* @param codeMgr the code managaer * @param codeMgr the code manager
* @param instIt the instruction iterator * @param instIt the instruction iterator
* @param dataIt the data iterator * @param dataIt the data iterator
* @param set the address set (required) * @param set the address set (required)
@ -57,17 +57,11 @@ class CodeUnitRecordIterator implements CodeUnitIterator {
} }
/**
* @see java.util.Iterator#remove()
*/
@Override @Override
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/**
* @see ghidra.program.model.listing.CodeUnitIterator#hasNext()
*/
@Override @Override
public boolean hasNext() { public boolean hasNext() {
if (nextCu == null) { if (nextCu == null) {
@ -76,9 +70,6 @@ class CodeUnitRecordIterator implements CodeUnitIterator {
return nextCu != null; return nextCu != null;
} }
/**
* @see ghidra.program.model.listing.CodeUnitIterator#next()
*/
@Override @Override
public CodeUnit next() { public CodeUnit next() {
if (hasNext()) { if (hasNext()) {

View file

@ -62,7 +62,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
private LiveMemoryHandler liveMemory; private LiveMemoryHandler liveMemory;
// lazy hashmap of block names to blocks, must be reloaded if blocks are removed or added // 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 private final static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out
Lock lock; 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 * 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 * 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) &amp; masks[i]) { * <PRE>
* return false; } } return false; * for(int i = 0; i &lt; bytes.length; i++) {
* if (bytes[i] != memory.getByte(addr+i) &amp; masks[i]) {
* return false;
* }
* }
* </PRE>
* *
* @param addr The beginning address in memory to test against. * @param addr The beginning address in memory to test against.
* @param bytes the array of bytes to test for. * @param bytes the array of bytes to test for.

View file

@ -18,23 +18,22 @@ package ghidra.program.model.address;
import java.math.BigInteger; import java.math.BigInteger;
import ghidra.program.model.data.DataOrganization; import ghidra.program.model.data.DataOrganization;
import ghidra.program.model.lang.Register;
/** /**
* An address represents a location in a program. Conceptually, addresses consist * An address represents a location in a program. Conceptually, addresses consist of an
* of an "address space" and an offset within that space. Many processors have only * "address space" and an offset within that space. Many processors have only one "real" address
* one "real" address space, but some have several spaces. Also, there are * space, but some have several spaces. Also, there are "artificial" address spaces used for
* "artificial" address spaces used for analysis and representing other non-memory locations * analysis and representing other non-memory locations such as a register or an offset on the
* such as a register or an offset on the stack relative to a functions frame pointer. * stack relative to a functions frame pointer.
*
*/ */
public interface Address extends Comparable<Address> { public interface Address extends Comparable<Address> {
/** /**
* Address object representing an invalid address. * Address object representing an invalid address.
*/ */
public static final Address NO_ADDRESS = new SpecialAddress("NO 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"); 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 = ':'; public final char SEPARATOR_CHAR = ':';
/** /**
* Creates a new Address by parsing a String representation of an address. The * Creates a new Address by parsing a String representation of an address. The string may be
* string may be either a simple number (just the offset part of an address) or take * either a simple number (just the offset part of an address) or take the form
* the form "addressSpaceName:offset". If the latter form is used, the * "addressSpaceName:offset". If the latter form is used, the "addressSpaceName" must match
* "addressSpaceName" must match the name of the space for this address. * the name of the space for this address.
* *
* @param addrString the String to parse. * @param addrString the String to parse.
* @return the new Address if the string is a legally formed address or null * @return the new Address if the string is a legally formed address or null if the string
* if the string contains an address space name that does not match this address's space. * contains an address space name that does not match this address's space.
* @throws AddressFormatException if the string cannot be parsed or the * @throws AddressFormatException if the string cannot be parsed or the
* parsed offset is larger than the size for this address' space. * parsed offset is larger than the size for this address' space.
*/ */
@ -68,71 +67,70 @@ public interface Address extends Comparable<Address> {
/** /**
* Returns a new address in this address's space with the given offset. * 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 * <P>NOTE: for those spaces with an addressable unit size other than 1, the address returned
* returned may not correspond to an addressable unit/word boundary if a byte-offset * may not correspond to an addressable unit/word boundary if a byte-offset is specified.
* is specified. *
* @param offset the offset for the new address. * @param offset the offset for the new address.
* @param isAddressableWordOffset if true the specified offset is an addressable unit/word offset, * @param isAddressableWordOffset if true the specified offset is an addressable unit/word
* otherwise offset is a byte offset. See {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize() * offset, otherwise offset is a byte offset. See
* {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize()
* AddressSpace#getAddressableUnitSize()} to understand the distinction * AddressSpace#getAddressableUnitSize()} to understand the distinction
* (i.e., wordOffset = byteOffset * addressableUnitSize). * (i.e., wordOffset = byteOffset * addressableUnitSize).
* @return address with given offset * @return address with given offset
* @throws AddressOutOfBoundsException if the offset is less than 0 or greater * @throws AddressOutOfBoundsException if the offset is less than 0 or greater than the max
* than the max offset allowed for this space. * offset allowed for this space.
*/ */
Address getNewAddress(long offset, boolean isAddressableWordOffset) Address getNewAddress(long offset, boolean isAddressableWordOffset)
throws AddressOutOfBoundsException; throws AddressOutOfBoundsException;
/** /**
* Returns a new address in this address's space with the given offset. The specified * Returns a new address in this address's space with the given offset. The specified offset
* offset will be truncated within the space and will not throw an exception. * 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 * <p>NOTE: for those spaces with an addressable unit size other than 1, the address returned
* returned may not correspond to a word boundary (addressable unit) if a byte-offset * may not correspond to a word boundary (addressable unit) if a byte-offset is specified.
* is specified.
* @param offset the offset for the new address. * @param offset the offset for the new address.
* @param isAddressableWordOffset if true the specified offset is an addressable unit/word offset, * @param isAddressableWordOffset if true the specified offset is an addressable unit/word
* otherwise offset is a byte offset. See {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize() * offset, otherwise offset is a byte offset. See
* {@link ghidra.program.model.address.AddressSpace#getAddressableUnitSize()
* AddressSpace#getAddressableUnitSize()} to understand the distinction * AddressSpace#getAddressableUnitSize()} to understand the distinction
* (i.e., wordOffset = byteOffset * addressableUnitSize). * (i.e., wordOffset = byteOffset * addressableUnitSize).
* @return address with given byte offset truncated to the physical space size * @return address with given byte offset truncated to the physical space size
*/ */
Address getNewTruncatedAddress(long offset, boolean isAddressableWordOffset); Address getNewTruncatedAddress(long offset, boolean isAddressableWordOffset);
/** /**
* Returns the number of bytes needed to form a pointer to this address. The * Returns the number of bytes needed to form a pointer to this address. The result will be
* result will be one of {1,2,4,8}. * one of {1,2,4,8}.
* @see DataOrganization#getPointerSize() for compiler-specific size of pointers stored in memory. * @return the pointer size
* @see DataOrganization#getPointerSize() for compiler-specific size of pointers stored in
* memory.
*/ */
public int getPointerSize(); public int getPointerSize();
/** /**
* Returns the address's successor. In most cases, this is equivalent * Returns the address's successor. In most cases, this is equivalent to addr.add(1), but
* to addr.add(1), but segmented addresses could span segments. The result * segmented addresses could span segments. The result of calling this on the highest address
* of calling this on the highest address will result in a null return value. * will result in a null return value.
* @return the next higher address, or null if already at the * @return the next higher address, or null if already at the highest address.
* highest address.
*/ */
public Address next(); public Address next();
/** /**
* Returns the address's predecessor. In most cases, this is equivalent to * Returns the address's predecessor. In most cases, this is equivalent to addr.subtract(1),
* addr.subtract(1), but segmented addresses could span segments. The * but segmented addresses could span segments. The result of calling this on the lowest
* result of calling this on the lowest address will result in a null return value. * address will result in a null return value.
* @return the next lower address, or null if already at the * @return the next lower address, or null if already at the lowest address.
* lowest address.
*/ */
public Address previous(); public Address previous();
/** /**
* Get the offset of this Address. * Get the offset of this Address.
*
* @return the offset of this Address. * @return the offset of this Address.
*/ */
public long getOffset(); 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. * @return the offset of this Address.
*/ */
public BigInteger getOffsetAsBigInteger(); public BigInteger getOffsetAsBigInteger();
@ -152,17 +150,21 @@ public interface Address extends Comparable<Address> {
/** /**
* Returns the address space associated with this address. * Returns the address space associated with this address.
* @return the address space
*/ */
public AddressSpace getAddressSpace(); public AddressSpace getAddressSpace();
/** /**
* Return true if this address' address space is equal to the * Return true if this address' address space is equal to the address space for addr.
* address space for addr. * @param addr the address to check
* @return true if the same space
*/ */
public boolean hasSameAddressSpace(Address addr); 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(); public int getSize();
@ -176,10 +178,9 @@ public interface Address extends Comparable<Address> {
public long subtract(Address addr); public long subtract(Address addr);
/** /**
* Creates a new address by subtracting the displacement from the current * Creates a new address by subtracting the displacement from the current address. The new
* address. The new address will wrap in a manner that depends on the * address will wrap in a manner that depends on the address space. For a generic address space
* address space. For a generic address space this will wrap at the * this will wrap at the extents of the address space. For a segmented address space it will
* extents of the address space. For a segmented address space it will
* wrap at the extents of the segment. * wrap at the extents of the segment.
* *
* @param displacement the displacement to subtract. * @param displacement the displacement to subtract.
@ -188,43 +189,41 @@ public interface Address extends Comparable<Address> {
public Address subtractWrap(long displacement); public Address subtractWrap(long displacement);
/** /**
* Creates a new address by subtracting the displacement from the current * Creates a new address by subtracting the displacement from the current address. If the
* address. If the offset is greater than the max offset of the address space, the high * offset is greater than the max offset of the address space, the high order bits are masked
* order bits are masked off, making the address wrap. For non-segmented addresses this * off, making the address wrap. For non-segmented addresses this will be the same as
* will be the same as subtractWrap(). For segmented addresses, the address will wrap when * subtractWrap(). For segmented addresses, the address will wrap when the 20 bit (oxfffff)
* the 20 bit (oxfffff) offset is exceeded, as opposed to when the segment offset is exceeded. * offset is exceeded, as opposed to when the segment offset is exceeded.
* @param displacement the displacement to add. * @param displacement the displacement to add.
* @return The new Address formed by subtracting the displacement from this address's offset. * @return The new Address formed by subtracting the displacement from this address's offset.
*/ */
public Address subtractWrapSpace(long displacement); public Address subtractWrapSpace(long displacement);
/** /**
* Creates a new Address by subtracting displacement from the * Creates a new Address by subtracting displacement from the Address. The Address will not
* Address. The Address will not wrap within the space and in fact will throw * wrap within the space and in fact will throw an exception if the result is less than the min
* an exception if the result is less than the min address in this space or * address in this space or greater than the max address in this space.
* greater than the max address in this space.
* *
* @param displacement the displacement to subtract. * @param displacement the displacement to subtract.
* @return The new Address * @return The new Address
* @throws AddressOverflowException if the offset in this Address would * @throws AddressOverflowException if the offset in this Address would overflow due to this
* overflow due to this operation. * operation.
*/ */
public Address subtractNoWrap(long displacement) throws AddressOverflowException; public Address subtractNoWrap(long displacement) throws AddressOverflowException;
/** /**
* Creates a new address (possibly in a new space) by subtracting the displacement to * Creates a new address (possibly in a new space) by subtracting the displacement to this
* this address. * address.
* @param displacement the amount to subtract from this offset. * @param displacement the amount to subtract from this offset.
* @return The address using the subtracted offset. * @return The address using the subtracted offset.
*/ */
public Address subtract(long displacement); public Address subtract(long displacement);
/** /**
* Creates a new address by adding the displacement to the current * Creates a new address by adding the displacement to the current address. The new address
* address. The new address will wrap in a manner that depends on the * will wrap in a manner that depends on the address space. For a generic address space this
* address space. For a generic address space this will wrap at the * will wrap at the extents of the address space. For a segmented address space it will wrap at
* extents of the address space. For a segmented address space it will * the extents of the segment.
* wrap at the extents of the segment.
* *
* @param displacement the displacement to add. * @param displacement the displacement to add.
* @return The new Address formed by adding the displacement to this address's offset. * @return The new Address formed by adding the displacement to this address's offset.
@ -232,112 +231,110 @@ public interface Address extends Comparable<Address> {
public Address addWrap(long displacement); public Address addWrap(long displacement);
/** /**
* Creates a new address by adding the displacement to the current * Creates a new address by adding the displacement to the current address. If the offset is
* address. If the offset is greater than the max offset of the address space, the high * greater than the max offset of the address space, the high order bits are masked off, making
* order bits are masked off, making the address wrap. For non-segmented addresses this * the address wrap. For non-segmented addresses this will be the same as addWrap(). For
* will be the same as addWrap(). For segmented addresses, the address will wrap when * segmented addresses, the address will wrap when the 20 bit (oxfffff) offset is exceeded, as
* the 20 bit (oxfffff) offset is exceeded, as opposed to when the segment offset is exceeded. * opposed to when the segment offset is exceeded.
* @param displacement the displacement to add. * @param displacement the displacement to add.
* @return The new Address formed by adding the displacement to this address's offset. * @return The new Address formed by adding the displacement to this address's offset.
*/ */
public Address addWrapSpace(long displacement); public Address addWrapSpace(long displacement);
/** /**
* Creates a new Address with a displacement relative to this * Creates a new Address with a displacement relative to this Address. The Address will not
* Address. The Address will not wrap around! An exception will be * wrap around! An exception will be throw if the result is not within this address space.
* throw if the result is not within this address space.
* *
* @param displacement the displacement to add. * @param displacement the displacement to add.
* @return The new Address * @return the new address.
* @throws AddressOverflowException if the offset in this Address would * @throws AddressOverflowException if the offset in this Address would overflow (wrap around)
* overflow (wrap around) due to this operation. * due to this operation.
*/ */
public Address addNoWrap(long displacement) throws AddressOverflowException; public Address addNoWrap(long displacement) throws AddressOverflowException;
public Address addNoWrap(BigInteger displacement) throws AddressOverflowException; public Address addNoWrap(BigInteger displacement) throws AddressOverflowException;
/** /**
* Creates a new address (possibly in a new space) by adding the displacement to * Creates a new address (possibly in a new space) by adding the displacement to this address.
* this address.
* @param displacement the amount to add to this offset. * @param displacement the amount to add to this offset.
* @return The new address. * @return The new address.
* @throws AddressOutOfBoundsException if wrapping is not supported by the * @throws AddressOutOfBoundsException if wrapping is not supported by the corresponding
* corresponding address space and the addition causes an out-of-bounds * address space and the addition causes an out-of-bounds error
* error
*/ */
public Address add(long displacement) throws AddressOutOfBoundsException; public Address add(long displacement) throws AddressOutOfBoundsException;
/** /**
* Tests whether the given address immediately follows this address. * Tests whether the given address immediately follows this address.
* *
* @param addr the address to test. * @param addr the address to test.
* @return true if the address follows this address.
*/ */
public boolean isSuccessor(Address addr); public boolean isSuccessor(Address addr);
/** /**
* Returns a String representation of the address in hex and padded * Returns a String representation of the address in hex and padded to the appropriate size.
* to the appropriate size. * @return the string
*/ */
@Override @Override
public String toString(); public String toString();
/** /**
* Returns a String representation of the address using the * Returns a String representation of the address using the given string as a prefix.
* given string as a prefix. Equivalent of prefix + ":" + toString(false) * Equivalent of prefix + ":" + toString(false)
* @param prefix the string to prepend to the address string. * @param prefix the string to prepend to the address string.
* @return the string
*/ */
public String toString(String prefix); public String toString(String prefix);
/** /**
* Returns a String representation that may include the address space name * Returns a String representation that may include the address space name
* @param showAddressSpace true if the address space should be included in * @param showAddressSpace true if the address space should be included in resulting string.
* resulting string.
* @return String the string representation of the address * @return String the string representation of the address
*/ */
public String toString(boolean showAddressSpace); public String toString(boolean showAddressSpace);
/** /**
* Returns a String representation that may include the address space name and may or may * Returns a String representation that may include the address space name and may or may not
* not pad the address with leading zeros. * pad the address with leading zeros.
* @param showAddressSpace if true, the addressSpace name will be prepended to the address string. * @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 * @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 max digits the address could contain. If false, the address will be prepended only to
* the number of hex digits at least 4. * make the number of hex digits at least 4.
* @return the address as a String. * @return the address as a String.
*/ */
public String toString(boolean showAddressSpace, boolean pad); public String toString(boolean showAddressSpace, boolean pad);
/** /**
* Returns a String representation that may include the address space name and may or may * Returns a String representation that may include the address space name and may or may not
* not pad the address with leading zeros. * pad the address with leading zeros.
* @param showAddressSpace if true, the addressSpace name will be prepended to the address string. * @param showAddressSpace if true, the addressSpace name will be prepended to the address
* @param minNumDigits specifies the minimum number of digits to use. If the address space size * string.
* is less that minNumDigits, the address will be padded to the address space size. If the address * @param minNumDigits specifies the minimum number of digits to use. If the address space
* space size is larger that minNumDigits, the address will be displayed with as many digits as * size is less that minNumDigits, the address will be padded to the address space size. If
* necessary, but will contain leading zeros to make the address string have at least minNumDigits. * 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. * @return the address as a String.
*/ */
public String toString(boolean showAddressSpace, int minNumDigits); public String toString(boolean showAddressSpace, int minNumDigits);
/** /**
* Compares this Address to the specified object. * Compares this Address to the specified object. The result is <code>true</code> if and only
* The result is <code>true</code> if and only if the argument is not * if the argument is not <code>null</code> and is a <code>Address</code> object that
* <code>null</code> and is a <code>Address</code> object that represents * represents the same address as this object.
* the same address as this object.
* *
* @param o the object to compare this <code>String</code> * @param o the object to compare this <code>String</code> against.
* against. * @return <code>true</code> if the <code>Addresses</code>are equal; <code>false</code>
* @return <code>true</code> if the <code>Addresses</code>are equal; * otherwise.
* <code>false</code> otherwise.
*/ */
@Override @Override
public boolean equals(Object o); public boolean equals(Object o);
/** /**
* Returns a hashcode for this Address. The hashcode for an * Returns a hash code for this Address. The hash code for an <code>Address</code> should be a
* <code>Address</code> should be a value such that two Address * value such that two Address objects which are equal will return the same hash code. This
* objects which are equal will return the same hashcode. * method should generally return the same value as getLong().
* This method should generally return the same value as getLong().
* *
* @return a hash code value for this object. * @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. * Returns the physical Address that corresponds to this Address.
* *
* @return address in a physical space corresponding to this * @return address in a physical space corresponding to this address.
* address.
*/ */
public Address getPhysicalAddress(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); public boolean isHashAddress();
/** /**
* Returns true if this address represents a location in the register space. * 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 * <P>NOTE: It is important to note that a {@link Register} could reside within a memory space
* a memory space and not the register space in which case this method would return * and not the register space in which case this method would return false for its address.
* false for its address. * @return true if a register address
*/ */
public boolean isRegisterAddress(); 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(); 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(); public boolean isExternalAddress();

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -30,38 +29,43 @@ public interface BookmarkType {
public static final String ERROR = "Error"; public static final String ERROR = "Error";
public static final String WARNING = "Warning"; public static final String WARNING = "Warning";
public static final String ANALYSIS = "Analysis"; 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 * Returns Icon associated with this type or null if one has not been
* set by a plugin. * 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 * Returns marker color associated with this type or null if one has not been
* set by a plugin. * 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 * Returns marker priority associated with this type or -1 if one has not been
* set by a plugin. * 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. * Returns the id associated with this bookmark type.
* @return the id associated with this bookmark type.
*/ */
int getTypeId(); public int getTypeId();
} }