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/U.gif||GHIDRA||||END|
src/main/resources/images/Unpackage.gif||GHIDRA||||END|
src/main/resources/images/V.png||GHIDRA||||END|
src/main/resources/images/VCRFastForward.gif||GHIDRA||||END|
src/main/resources/images/V_slash.png||GHIDRA||||END|
src/main/resources/images/View.gif||GHIDRA||||END|

View file

@ -416,12 +416,27 @@
temporarily invert the direction of the search.</P>
</BLOCKQUOTE>
<H3><A name="Invert_Search_Logic"></A>Invert Search Logic</H3>
<BLOCKQUOTE>
<P>The <IMG src="images/dialog-cancel.png" alt="down_arrow" border="0"> icon indicates the
search logic will be inverted / negated. The exact meaning of this depends upon the type
of search performed, as described below.
</BLOCKQUOTE>
<H3><A name="Next_Instruction"></A>Navigate to Instruction</H3>
<BLOCKQUOTE>
<P>To move the cursor to the next instruction click on the Navigate by Instruction icon,
<IMG src="images/I.gif" alt="I" border="0">. This icon is disabled when no more
instructions exist in the current search direction.</P>
<P>When inverted, this task, if on an instruction, will attempt to navigate to
the next data or undefined data. If not on an instruction, then this task
will find the next instruction and then find the data or undefined data after that.
</P>
</BLOCKQUOTE>
<H3><A name="Next_Data"></A>Navigate to Data</H3>
@ -430,6 +445,12 @@
<P>To move the cursor to the next data code unit, click on the Navigate by Data icon, <IMG
src="images/D.gif" alt="D" border="0">. This icon is disabled when no more data code units
exist in the current search direction.</P>
<P>When inverted, this task, if on a data code unit, will attempt to navigate to
the next instruction or undefined data. If not on a data, then this task
will find the next defined data and then find the instruction or undefined data after that.
</P>
</BLOCKQUOTE>
<H3><A name="Next_Undefined"></A>Navigate to Undefined</H3>
@ -438,14 +459,25 @@
<P>To move the cursor to the next undefined code unit, click on the Navigate by Data icon,
<IMG src="images/U.gif" alt="U" border="0">. This icon is disabled when no more undefined
code units exist in the current search direction.</P>
<P>When inverted, this task, if on an undefined code unit, will attempt to navigate to
the next instruction or data. If not on an undefined, then this task
will find the next undefined and then find the instruction or data after that.
</P>
</BLOCKQUOTE>
<H3><A name="Next_Label"></A>Navigate to Label</H3>
<BLOCKQUOTE>
<P>To move the cursor to the next Label, click on the Navigate by Label icon,
<IMG src="images/L.gif" alt="L" border="0">. This icon is disabled when no more labels
exist in the current search direction.</P>
<IMG src="images/L.gif" alt="L" border="0">.</P>
<P>When inverted, this task, if on an address with a label, will attempt to navigate to
the next code unit without a label. If not on an address with a label, then this task
will find the next label and then find the next code unit after that without a label.
</P>
</BLOCKQUOTE>
<H3><A name="Next_Function"></A>Navigate to Function</H3>
@ -455,37 +487,49 @@
next function in the current direction. If inside a function and the direction is towards
lower addresses, then this action will go to the current function's entry point.</P>
<P>When inverted, this task (<IMG src="images/notF.gif" alt="F">) will attempt to
the navigate to the next instruction block not contained in a function.
This can be useful when manually creating functions and
stepping over them to identify potential function candidates.</P>
</P>
</BLOCKQUOTE>
<H3><A name="Next_Non_Function"></A>Navigate to Non-Function</H3>
<H3><A name="Next_Matching_Byte_Values"></A>Navigate to Matching Byte Values</H3>
<P style="margin-left: 40px;">This task (<IMG src="images/notF.gif" alt="F">) will attempt to
the navigate to the next instruction block not contained in a function.&nbsp;
This can be useful when manually creating functions and
stepping over them to identify potential function candidates.&nbsp;</P>
<BLOCKQUOTE>
<H3><A name="Next_Different_Byte_Value"></A>Navigate to Different Byte Value</H3>
<P>This task (<IMG src="images/V.png" alt="V">) will attempt to navigate to the next matching
byte pattern of the code unit under the cursor.
</P>
<P style="margin-left: 40px;">This task (<IMG src="images/V_slash.png" alt="V">) will attempt to
<P>When inverted, this task will attempt to
the navigate to the first code-unit where the byte value is different from the byte value
of the first byte of the current code unit.&nbsp; This can be useful when trying to navigate
past a series of 0s or FFs;</P>
of the first byte of the current code unit. This can be useful when trying to navigate
past a series of 0s or FFs</P>
</BLOCKQUOTE>
<H3><A name="Next_Bookmark"></A>Navigate to Bookmark</H3>
<BLOCKQUOTE>
<P>To move the cursor to the next bookmark, click on the Navigate by Bookmark icon,
<IMG src="images/B.gif" alt="B" border="0">. This icon is disabled when no more bookmarks
exist in the current search direction. You may use the pull-down menu to choose a specific
type of bookmark (<IMG src="images/applications-system.png" alt="B" border="0">,
<IMG src="images/B.gif" alt="B" border="0">. You may use the pull-down menu to choose a
specific type of bookmark (<IMG src="images/applications-system.png" alt="B" border="0">,
<IMG src="images/edit-delete.png" alt="B" border="0">,
<IMG src="images/information.png" alt="B" border="0">,
<IMG src="images/notes.gif" alt="B" border="0">,
<IMG src="images/warning.png" alt="B" border="0">,
<IMG src="images/unknown.gif" alt="B" border="0">)
to navigate to as opposed to all types. </P>
<P>When inverted, this task will attempt to navigate to then next address with a bookmark
different than what is selected in the pull-down menu of the icon. If the 'all bookmarks'
state is selected, then this task will simply navigate to the next address that has no
bookmark.
</P>
</BLOCKQUOTE>

View file

@ -23,6 +23,7 @@ import javax.swing.KeyStroke;
import docking.action.KeyBindingData;
import docking.action.ToolBarData;
import docking.tool.ToolConstants;
import generic.util.image.ImageUtils;
import ghidra.app.context.NavigatableActionContext;
import ghidra.app.context.NavigatableContextAction;
import ghidra.app.nav.Navigatable;
@ -36,12 +37,19 @@ import ghidra.util.HelpLocation;
import ghidra.util.Swing;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.*;
import resources.*;
public abstract class AbstractNextPreviousAction extends NavigatableContextAction {
private static final Icon INVERTED_OVERLAY_ICON =
ImageUtils.makeTransparent(ResourceManager.loadImage("images/dialog-cancel.png"), .5f);
private boolean isForward = true;
private PluginTool tool;
protected boolean isInverted;
private Icon invertedIcon;
public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) {
super(name, owner);
this.tool = tool;
@ -55,6 +63,16 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name));
setDescription(getDescriptionString());
addToWindowWhen(NavigatableActionContext.class);
MultiIconBuilder builder = new MultiIconBuilder(getIcon());
builder.addIcon(INVERTED_OVERLAY_ICON, 10, 10, QUADRANT.LR);
invertedIcon = builder.build();
}
protected void setInverted(boolean isInverted) {
this.isInverted = isInverted;
getToolBarData().setIcon(isInverted ? invertedIcon : getIcon());
setDescription(getDescriptionString());
}
protected abstract Icon getIcon();
@ -63,13 +81,13 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
@Override
public void actionPerformed(final NavigatableActionContext context) {
Task t = new Task("Searching for " + getNavigationTypeName() + "...", true, false, true) {
Task t = new Task("Searching for " + doGetNavigationTypeName(), true, false, true) {
@Override
public void run(TaskMonitor monitor) {
gotoNextPrevious(monitor, context);
}
};
new TaskLauncher(t, tool.getToolFrame(), 500);
new TaskLauncher(t);
}
void gotoNextPrevious(TaskMonitor monitor, final NavigatableActionContext context) {
@ -93,7 +111,7 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
private void gotoAddress(NavigatableActionContext actionContext, Address address) {
if (address == null) {
tool.setStatusInfo("Unable to locate another \"" + getNavigationTypeName() +
tool.setStatusInfo("Unable to locate another \"" + doGetNavigationTypeName() +
"\" past the current range, in the current direction.");
return;
}
@ -119,14 +137,26 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio
private String getDescriptionString() {
String prefix = isForward ? "Go To Next " : "Go To Previous ";
return prefix + getNavigationTypeName() + " (shift-click inverts direction)";
return prefix + doGetNavigationTypeName() + " (shift-click inverts direction)";
}
private String doGetNavigationTypeName() {
if (isInverted) {
return getInvertedNavigationTypeName();
}
return getNavigationTypeName();
}
abstract protected String getNavigationTypeName();
protected String getInvertedNavigationTypeName() {
return "Non-" + getNavigationTypeName();
}
abstract protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException;
abstract protected Address getPreviousAddress(TaskMonitor monitor, Program program,
Address address) throws CancelledException;
}

View file

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

View file

@ -18,8 +18,7 @@ package ghidra.app.plugin.core.navigation;
import java.awt.event.*;
import java.util.Iterator;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import javax.swing.*;
import docking.ActionContext;
import docking.action.*;
@ -27,6 +26,7 @@ import docking.menu.ActionState;
import docking.menu.MultiStateDockingAction;
import docking.tool.ToolConstants;
import docking.widgets.EventTrigger;
import generic.util.image.ImageUtils;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.NavigatableActionContext;
import ghidra.app.nav.Navigatable;
@ -38,29 +38,42 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.HelpLocation;
import ghidra.util.Swing;
import resources.ResourceManager;
import resources.*;
public class NextPreviousBookmarkAction extends MultiStateDockingAction<String> {
private boolean isForward = true;
private PluginTool tool;
private static ImageIcon bookmarkIcon = ResourceManager.loadImage("images/B.gif");
private static ImageIcon bookmarkAnalysisIcon =
public static final String ALL_BOOKMARK_TYPES = "All Bookmark Types";
private static final Icon INVERTED_OVERLAY_ICON =
ImageUtils.makeTransparent(ResourceManager.loadImage("images/dialog-cancel.png"), .5f);
private PluginTool tool;
private boolean isForward = true;
private boolean isInverted;
private static final ImageIcon BOOKMARK_ICON = ResourceManager.getScaledIcon(
ResourceManager.loadImage("images/B.gif"), 16, 16);
private static final ImageIcon BOOKMARK_ANALYSIS_ICON =
ResourceManager.loadImage("images/applications-system.png");
private static ImageIcon bookmarkErrorIcon =
private static final ImageIcon BOOKMARK_ERROR_ICON =
ResourceManager.loadImage("images/edit-delete.png");
private static ImageIcon bookmarkInfoIcon = ResourceManager.loadImage("images/information.png");
private static ImageIcon bookmarkNoteIcon = ResourceManager.loadImage("images/notes.gif");
private static ImageIcon bookmarkWarningIcon = ResourceManager.loadImage("images/warning.png");
private static ImageIcon bookmarkUnknownIcon = ResourceManager.loadImage("images/unknown.gif");
private static final ImageIcon BOOKMARK_INFO_ICON =
ResourceManager.loadImage("images/information.png");
private static final ImageIcon BOOKMARK_NOTE_ICON =
ResourceManager.loadImage("images/notes.gif");
private static final ImageIcon BOOKMARK_WARNING_ICON =
ResourceManager.loadImage("images/warning.png");
private static final ImageIcon BOOKMARK_UNKNOWN_ICON =
ResourceManager.loadImage("images/unknown.gif");
public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {
super("Next Bookmark", owner);
this.tool = tool;
setSupportsDefaultToolContext(true);
ToolBarData toolBarData =
new ToolBarData(bookmarkIcon, ToolConstants.TOOLBAR_GROUP_FOUR);
new ToolBarData(BOOKMARK_ICON, ToolConstants.TOOLBAR_GROUP_FOUR);
toolBarData.setToolBarSubGroup(subGroup);
setToolBarData(toolBarData);
@ -71,16 +84,16 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
setDescription("Set bookmark options");
ActionState<String> allBookmarks =
new ActionState<>("All Types", bookmarkIcon, BookmarkType.ALL_TYPES);
new ActionState<>("All Types", BOOKMARK_ICON, ALL_BOOKMARK_TYPES);
ActionState<String> analysis =
new ActionState<>("Analysis", bookmarkAnalysisIcon, BookmarkType.ANALYSIS);
new ActionState<>("Analysis", BOOKMARK_ANALYSIS_ICON, BookmarkType.ANALYSIS);
ActionState<String> error =
new ActionState<>("Error", bookmarkErrorIcon, BookmarkType.ERROR);
ActionState<String> info = new ActionState<>("Info", bookmarkInfoIcon, BookmarkType.INFO);
ActionState<String> note = new ActionState<>("Note", bookmarkNoteIcon, BookmarkType.NOTE);
new ActionState<>("Error", BOOKMARK_ERROR_ICON, BookmarkType.ERROR);
ActionState<String> info = new ActionState<>("Info", BOOKMARK_INFO_ICON, BookmarkType.INFO);
ActionState<String> note = new ActionState<>("Note", BOOKMARK_NOTE_ICON, BookmarkType.NOTE);
ActionState<String> warning =
new ActionState<>("Warning", bookmarkWarningIcon, BookmarkType.WARNING);
ActionState<String> custom = new ActionState<>("Custom", bookmarkUnknownIcon, "Custom");
new ActionState<>("Warning", BOOKMARK_WARNING_ICON, BookmarkType.WARNING);
ActionState<String> custom = new ActionState<>("Custom", BOOKMARK_UNKNOWN_ICON, "Custom");
addActionState(allBookmarks);
addActionState(analysis);
@ -110,19 +123,122 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
@Override
public void actionStateChanged(ActionState<String> newActionState, EventTrigger trigger) {
// nothing
Icon icon = newActionState.getIcon();
ToolBarData tbData = getToolBarData();
tbData.setIcon(isInverted ? invertIcon(icon) : icon);
}
// Find the beginning of the next instruction range
private Address getNextAddress(Program program, Address address, String bookmarkType) {
Address start = getNextAddressToBeginSearchingForward(program, address);
Bookmark nextBookmark = getNextBookmark(program, start, true, bookmarkType);
return nextBookmark == null ? null : nextBookmark.getAddress();
if (isInverted) {
return getNextAddressOfNonBookmark(program, address, bookmarkType);
}
return getAddressOfNextBookmarkAfter(program, address, bookmarkType);
}
private Address getPreviousAddress(Program program, Address address, String bookmarkType) {
if (isInverted) {
return getPreviousAddressOfNonBookmark(program, address, bookmarkType);
}
return getAddressOfPreviousBookmarkBefore(program, address, bookmarkType);
}
private Address getNextAddressOfNonBookmark(Program program, Address address,
String bookmarkType) {
if (ALL_BOOKMARK_TYPES.equals(bookmarkType)) {
// special case: when 'all types' is negated, then we skip runs of non-bookmarks to
// allow users to quickly jump to areas with any bookmarks
address = getAddressOfNextBookmarkAfter(program, address, bookmarkType);
}
return getAdddressOfNextPreviousNonBookmark(program, address, bookmarkType, true);
}
private Address getPreviousAddressOfNonBookmark(Program program, Address address,
String bookmarkType) {
if (ALL_BOOKMARK_TYPES.equals(bookmarkType)) {
// special case: when 'all types' is negated, then we skip runs of non-bookmarks to
// allow users to quickly jump to areas with any bookmarks
address = getAddressOfPreviousBookmarkBefore(program, address, bookmarkType);
}
return getAdddressOfNextPreviousNonBookmark(program, address, bookmarkType, false);
}
private Address getAdddressOfNextPreviousNonBookmark(Program program, Address address,
String bookmarkType, boolean forward) {
if (address == null) {
return null;
}
address = forward ? address.next() : address.previous();
if (address == null) {
return null;
}
//
// By default, if we are given a specific bookmark type, then we need only to find the
// next bookmark of a different type. However, if the given type is 'all bookmarks', then
// do something reasonable, which is to find the next code unit without a bookmark. Users
// are not likely to use this option.
//
if (bookmarkType.equals(ALL_BOOKMARK_TYPES)) {
return getNextPreviousCuWithoutBookmarkAddress(program, address, forward);
}
BookmarkManager bm = program.getBookmarkManager();
Iterator<Bookmark> it = bm.getBookmarksIterator(address, forward);
while (it.hasNext()) {
Bookmark nextBookmark = it.next();
Address nextAddress = nextBookmark.getAddress();
if (nextAddress.isExternalAddress()) {
continue;
}
if (!nextBookmark.getTypeString().equals(bookmarkType)) {
return nextBookmark.getAddress();
}
}
return null;
}
private Address getNextPreviousCuWithoutBookmarkAddress(Program program, Address address,
boolean forward) {
CodeUnitIterator it = program.getListing().getCodeUnits(address, forward);
while (it.hasNext()) {
CodeUnit cu = it.next();
Address minAddress = cu.getMinAddress();
BookmarkManager bm = program.getBookmarkManager();
Bookmark[] bookmarks = bm.getBookmarks(minAddress);
if (bookmarks.length == 0) {
return minAddress;
}
}
return null;
}
private Address getAddressOfNextBookmarkAfter(Program program, Address address,
String bookmarkType) {
Address start = getNextAddressToBeginSearchingForward(program, address);
Bookmark nextBookmark = getNextPreviousBookmark(program, start, true, bookmarkType);
return nextBookmark == null ? null : nextBookmark.getAddress();
}
private Address getAddressOfPreviousBookmarkBefore(Program program, Address address,
String bookmarkType) {
Address start = getNextAddressToBeginSearchingBackward(program, address);
Bookmark nextBookmark = getNextBookmark(program, start, false, bookmarkType);
Bookmark nextBookmark = getNextPreviousBookmark(program, start, false, bookmarkType);
return nextBookmark == null ? null : nextBookmark.getAddress();
}
@ -150,19 +266,19 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
return cu;
}
private Bookmark getNextBookmark(Program program, Address address, boolean forward,
private Bookmark getNextPreviousBookmark(Program program, Address address, boolean forward,
String bookmarkType) {
BookmarkManager bookmarkManager = program.getBookmarkManager();
Iterator<Bookmark> bookmarkIterator =
bookmarkManager.getBookmarksIterator(address, forward);
while (bookmarkIterator.hasNext()) {
Bookmark nextBookmark = bookmarkIterator.next();
BookmarkManager bm = program.getBookmarkManager();
Iterator<Bookmark> it = bm.getBookmarksIterator(address, forward);
while (it.hasNext()) {
Bookmark nextBookmark = it.next();
Address nextAddress = nextBookmark.getAddress();
if (nextAddress.isExternalAddress()) {
continue;
}
if (bookmarkType.equals(BookmarkType.ALL_TYPES)) {
if (bookmarkType.equals(ALL_BOOKMARK_TYPES)) {
return nextBookmark;
}
else if (bookmarkType.equals("Custom") &&
@ -172,13 +288,11 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
else if (nextBookmark.getTypeString().equals(bookmarkType)) {
return nextBookmark;
}
}
if (!bookmarkIterator.hasNext()) {
return null;
}
return bookmarkIterator.next();
}
private boolean isNotBuiltInType(Address address, Bookmark nextBookmark, Address nextAddress) {
return !nextBookmark.getTypeString().equals(BookmarkType.ANALYSIS) &&
@ -231,10 +345,31 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
setDescription(getToolTipText());
}
public void setInverted(boolean isInverted) {
this.isInverted = isInverted;
ActionState<String> state = getCurrentState();
Icon icon = state.getIcon();
getToolBarData().setIcon(isInverted ? invertIcon(icon) : icon);
setDescription(getToolTipText());
}
private Icon invertIcon(Icon icon) {
MultiIconBuilder builder = new MultiIconBuilder(icon);
builder.addIcon(INVERTED_OVERLAY_ICON, 10, 10, QUADRANT.LR);
return builder.build();
}
@Override
public String getToolTipText() {
String description = "Go To " + (isForward ? "Next" : "Previous");
description += " Bookmark: " + getCurrentState().getName();
if (isInverted) {
description += " Non-Bookmark: ";
}
else {
description += " Bookmark: ";
}
description += getCurrentState().getName();
description += " (shift-click inverts direction)";
return description;
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/
package ghidra.app.plugin.core.navigation;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.Icon;
import javax.swing.KeyStroke;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
@ -52,28 +50,49 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
InputEvent.ALT_DOWN_MASK);
}
/**
* Find the beginning of the next instruction range
*/
@Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getNextNonDataAddress(monitor, program, address);
}
if (isDefinedDataAt(program, address)) {
// on an instruction, we have to find a non-instruction before finding the next instruction
// on a data, find a non-data before finding the next data
address = getAddressOfNextPreviousNonDefinedData(monitor, program, address, true);
}
// we know address is not an instruction at this point
return getAddressOfNextDataAfter(program, address);
}
private Address getNextNonDataAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
//
// Assumptions:
// -if on a data, find the next instruction or undefined
// -if not on a data, find the next data, then find the next instruction or undefined after
// that (this mimics the non-inverted case)
//
if (!isDefinedDataAt(program, address)) {
address = getAddressOfNextDataAfter(program, address);
}
return getAddressOfNextPreviousNonDefinedData(monitor, program, address, true);
}
@Override
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getPreviousNonDataAddress(monitor, program, address);
}
if (isDefinedDataAt(program, address)) {
// on an instruction, we have to find a non-instruction before finding the previous instruction
// on an data, find a non-data before finding the previous data
address = getAddressOfNextPreviousNonDefinedData(monitor, program, address, false);
}
@ -82,6 +101,22 @@ public class NextPreviousDefinedDataAction extends AbstractNextPreviousAction {
return getAddressOfPreviousDataBefore(program, address);
}
private Address getPreviousNonDataAddress(TaskMonitor monitor, Program program,
Address address) throws CancelledException {
//
// Assumptions:
// -if on an data, find the previous instruction or undefined
// -if not on a data, find the previous data, then find the previous instruction or
// undefined before that (this mimics the non-inverted case)
//
if (!isDefinedDataAt(program, address)) {
address = getAddressOfPreviousDataBefore(program, address);
}
return getAddressOfNextPreviousNonDefinedData(monitor, program, address, false);
}
private boolean isDefinedDataAt(Program program, Address address) {
if (address == null) {
return false;

View file

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

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/
package ghidra.app.plugin.core.navigation;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.Icon;
import javax.swing.KeyStroke;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
@ -52,21 +50,20 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
return "Instruction";
}
/**
* Find the beginning of the next instruction range
* @throws CancelledException
*/
@Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getNextNonInstructionAddress(monitor, program, address);
}
if (isInstructionAt(program, address)) {
// on an instruction, we have to find a non-instruction before finding the next instruction
// on an instruction, find a non-instruction before finding the next instruction
address = getAddressOfNextPreviousNonInstruction(monitor, program, address, true);
}
// we know address is not an instruction at this point
return getAddressOfNextInstructionAfter(program, address);
}
@ -74,16 +71,51 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getPreviousNonInstructionAddress(monitor, program, address);
}
if (isInstructionAt(program, address)) {
// on an instruction, we have to find a non-instruction before finding the previous instruction
// on an instruction, find a non-instruction before finding the previous instruction
address = getAddressOfNextPreviousNonInstruction(monitor, program, address, false);
}
// we know address is not at an instruction at this point
return getAddressOfPreviousInstructionBefore(program, address);
}
private Address getNextNonInstructionAddress(TaskMonitor monitor, Program program,
Address address) throws CancelledException {
//
// Assumptions:
// -if on an instruction, find the next data or undefined
// -if not on an instruction, find the next instruction, then find the next data or
// undefined after that (this mimics the non-inverted case)
//
if (!isInstructionAt(program, address)) {
address = getAddressOfNextInstructionAfter(program, address);
}
return getAddressOfNextPreviousNonInstruction(monitor, program, address, true);
}
private Address getPreviousNonInstructionAddress(TaskMonitor monitor, Program program,
Address address) throws CancelledException {
//
// Assumptions:
// -if on an instruction, find the previous data or undefined
// -if not on an instruction, find the previous instruction, then find the previous data or
// undefined before that (this mimics the non-inverted case)
//
if (!isInstructionAt(program, address)) {
address = getAddressOfPreviousInstructionBefore(program, address);
}
return getAddressOfNextPreviousNonInstruction(monitor, program, address, false);
}
private boolean isInstructionAt(Program program, Address address) {
if (address == null) {
return false;
@ -116,6 +148,10 @@ public class NextPreviousInstructionAction extends AbstractNextPreviousAction {
private Address getAddressOfNextPreviousNonInstruction(TaskMonitor monitor, Program program,
Address address, boolean forward) throws CancelledException {
if (address == null) {
return null;
}
CodeUnitIterator codeUnits = program.getListing().getCodeUnits(address, forward);
while (codeUnits.hasNext()) {
monitor.checkCanceled();

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,21 +15,19 @@
*/
package ghidra.app.plugin.core.navigation;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressIterator;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.Icon;
import javax.swing.KeyStroke;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressIterator;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class NextPreviousLabelAction extends AbstractNextPreviousAction {
@ -59,6 +56,10 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getNextNonLabel(monitor, program, address);
}
address = getAddressOfNextCodeUnit(program, address);
return getAddressOfNextPreviousLabel(program, address, true);
}
@ -67,10 +68,71 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getPreviousNonLabel(monitor, program, address);
}
address = getAddressOfPreviousCodeUnit(program, address);
return getAddressOfNextPreviousLabel(program, address, false);
}
private Address getNextNonLabel(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
//
// Assumptions:
// -if on a label, find the next non-label code unit
// -if not on a label, find the next label, then find the next non-label code unit after
// that (this mimics the non-inverted case)
//
if (!hasLabelAt(program, address)) {
address = getAddressOfNextPreviousLabel(program, address, true);
}
return getAddressOfNextPreviousNonLabel(monitor, program, address, true);
}
private Address getPreviousNonLabel(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
//
// Assumptions:
// -if on a label, find the previous non-label code unit
// -if not on a label, find the previous label, then find the previous non-label code unit
// before that (this mimics the non-inverted case)
//
if (!hasLabelAt(program, address)) {
address = getAddressOfNextPreviousLabel(program, address, false);
}
return getAddressOfNextPreviousNonLabel(monitor, program, address, false);
}
private Address getAddressOfNextPreviousNonLabel(TaskMonitor monitor, Program program,
Address address, boolean forward) throws CancelledException {
if (address == null) {
return null;
}
SymbolTable symbolTable = program.getSymbolTable();
CodeUnitIterator codeUnits = program.getListing().getCodeUnits(address, forward);
while (codeUnits.hasNext()) {
monitor.checkCanceled();
CodeUnit codeUnit = codeUnits.next();
Address minAddress = codeUnit.getMinAddress();
if (symbolTable.getPrimarySymbol(minAddress) == null) {
return minAddress;
}
}
return null;
}
private boolean hasLabelAt(Program program, Address address) {
SymbolTable symbolTable = program.getSymbolTable();
return symbolTable.getPrimarySymbol(address) != null;
}
private Address getAddressOfNextCodeUnit(Program program, Address address) {
CodeUnit cu = program.getListing().getCodeUnitAfter(address);
if (cu == null) {
@ -87,7 +149,8 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
return cu.getAddress();
}
private Address getAddressOfNextPreviousLabel(Program program, Address address, boolean forward) {
private Address getAddressOfNextPreviousLabel(Program program, Address address,
boolean forward) {
if (address == null) {
return null;
@ -95,7 +158,6 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
Address nextDefinedLableAddress = getNextDefinedLableAddress(program, address, forward);
Address nextReferenceToAddress = getNextReferenceToAddress(program, address, forward);
if (nextDefinedLableAddress == null) {
return nextReferenceToAddress;
}
@ -104,11 +166,9 @@ public class NextPreviousLabelAction extends AbstractNextPreviousAction {
}
int compare = nextDefinedLableAddress.compareTo(nextReferenceToAddress);
if (forward) {
return compare <= 0 ? nextDefinedLableAddress : nextReferenceToAddress;
}
return compare >= 0 ? nextDefinedLableAddress : nextReferenceToAddress;
}

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;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.Iterator;
@ -33,22 +22,35 @@ import java.util.Iterator;
import javax.swing.Icon;
import javax.swing.KeyStroke;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction {
/**
* Navigates to the same byte pattern value under the current code unit. When negated, the search
* will only consider a single byte, as it seems more useful to be able to skip runs of a
* particular byte.
*/
public class NextPreviousSameBytesAction extends AbstractNextPreviousAction {
public NextPreviousDifferentByteAction(PluginTool tool, String owner, String subGroup) {
super(tool, "Next Different Byte Value", owner, subGroup);
}
private static final Icon ICON = ResourceManager.loadImage("images/V.png");
@Override
protected String getNavigationTypeName() {
return "Different Byte Value";
NextPreviousSameBytesAction(PluginTool tool, String owner, String subGroup) {
super(tool, "Next Matching Byte Values", owner, subGroup);
}
@Override
protected Icon getIcon() {
return ResourceManager.loadImage("images/V_slash.png");
return ICON;
}
@Override
@ -57,13 +59,24 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
InputEvent.ALT_DOWN_MASK);
}
/**
* Find the beginning of the next instruction range
*/
@Override
protected String getNavigationTypeName() {
return "Same Bytes Value";
}
@Override
protected String getInvertedNavigationTypeName() {
return "Different Bytes Value";
}
@Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getNextPreviousDifferentByteValueAddress(monitor, program, address, true);
}
return getNextPreviousAddress(monitor, program, address, true);
}
@ -71,12 +84,15 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getNextPreviousDifferentByteValueAddress(monitor, program, address, false);
}
return getNextPreviousAddress(monitor, program, address, false);
}
protected Address getNextPreviousAddress(TaskMonitor monitor, Program program, Address address,
boolean forward) throws CancelledException {
private Address getNextPreviousDifferentByteValueAddress(TaskMonitor monitor, Program program,
Address address, boolean forward) throws CancelledException {
byte value = 0;
try {
value = program.getMemory().getByte(address);
@ -114,6 +130,55 @@ public class NextPreviousDifferentByteAction extends AbstractNextPreviousAction
return null;
}
private Address getNextPreviousAddress(TaskMonitor monitor, Program program,
Address address, boolean forward) {
Address startAddress;
byte[] bytes;
CodeUnit cu = program.getListing().getCodeUnitContaining(address);
if (cu != null) {
try {
bytes = cu.getBytes();
}
catch (MemoryAccessException e) {
Msg.debug(this, "Exception getting code unit bytes at " + cu.getAddress(), e);
return null; // not sure if this can happen
}
startAddress = forward ? cu.getMaxAddress().next() : cu.getMinAddress().previous();
}
else {
try {
Memory memory = program.getMemory();
bytes = new byte[] { memory.getByte(address) };
}
catch (MemoryAccessException e) {
Msg.debug(this, "Exception getting code unit bytes at " + address, e);
return null; // not sure if this can happen
}
startAddress = forward ? address.next() : address.previous();
}
return getNextPreviousSameBytes(monitor, program, startAddress, bytes, forward);
}
private Address getNextPreviousSameBytes(TaskMonitor monitor, Program program,
Address startAddress, byte[] bytes, boolean forward) {
Memory memory = program.getMemory();
byte[] mask = null; // null signals to use a full mask
AddressSetView addresses = memory.getAllInitializedAddressSet();
if (startAddress == null) {
return null;
}
Address endAddress =
forward ? addresses.getMaxAddress() : addresses.getMinAddress().previous();
Address matchAddress = memory.findBytes(startAddress, endAddress, bytes,
mask, forward, monitor);
return matchAddress;
}
private CodeUnit getNextPreviousCodeUnit(Program program, Address address, boolean forward) {
if (forward) {
return program.getListing().getDefinedCodeUnitAfter(address);

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,18 +15,17 @@
*/
package ghidra.app.plugin.core.navigation;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.Icon;
import javax.swing.KeyStroke;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
@ -52,21 +50,20 @@ public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
return "Undefined";
}
/**
* Find the beginning of the next instruction range
* @throws CancelledException
*/
@Override
protected Address getNextAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getNextNonUndefined(monitor, program, address);
}
if (isUndefinedAt(program, address)) {
// on an undefined, we have to find a defined before finding the next undefined
// on an undefined, find a defined before finding the next undefined
address = getAddressOfNextDefined(program, address);
}
// we know address is not an instruction at this point
// we know address is not an undefined at this point
return getAddressOfNextPreviousUndefined(monitor, program, address, true);
}
@ -74,16 +71,51 @@ public class NextPreviousUndefinedAction extends AbstractNextPreviousAction {
protected Address getPreviousAddress(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
if (isInverted) {
return getPreviousNonUndefined(monitor, program, address);
}
if (isUndefinedAt(program, address)) {
// on an instruction, we have to find a non-instruction before finding the previous instruction
// on an undefined, find a defined before finding the previous undefined
address = getAddressOfPreviousDefined(program, address);
}
// we know address is not at an instruction at this point
// we know address is not at an undefined at this point
return getAddressOfNextPreviousUndefined(monitor, program, address, false);
}
private Address getNextNonUndefined(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
//
// Assumptions:
// -if on an undefined, find the next instruction or data
// -if not on an undefined, find the next undefined, then find the next instruction or
// undefined after that (this mimics the non-inverted case)
//
if (!isUndefinedAt(program, address)) {
address = getAddressOfNextPreviousUndefined(monitor, program, address, true);
}
return getAddressOfNextDefined(program, address);
}
private Address getPreviousNonUndefined(TaskMonitor monitor, Program program, Address address)
throws CancelledException {
//
// Assumptions:
// -if on an undefined, find the previous data or instruction
// -if not on an undefined, find the previous undefined, then find the previous data or
// instruction before that (this mimics the non-inverted case)
//
if (!isUndefinedAt(program, address)) {
address = getAddressOfNextPreviousUndefined(monitor, program, address, false);
}
return getAddressOfPreviousDefined(program, address);
}
private boolean isUndefinedAt(Program program, Address address) {
if (address == null) {
return false;

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();
tx(program, () -> {
bm.removeBookmarks(BookmarkType.ALL_TYPES);
bm.removeBookmarks("Type1");
bm.removeBookmarks("Type2");
bm.removeBookmarks("Type3");
});
list = getBookmarks(program.getBookmarkManager());

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,24 +27,29 @@ public class TranslateIcon implements Icon {
int translateX;
int translateY;
/** Where the translate values are offset from the icon's upper corner */
/**
* Where the translate values are offset from the icon's upper corner
* @param icon the icon
* @param translateX the x translation
* @param translateY the y translation
*/
public TranslateIcon(Icon icon, int translateX, int translateY) {
this.icon = icon;
this.translateX = translateX;
this.translateY = translateY;
}
/**
* @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics, int, int)
*/
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
icon.paintIcon(c, g, x + translateX, y + translateY);
}
@Override
public int getIconHeight() {
return icon.getIconHeight();
}
@Override
public int getIconWidth() {
return icon.getIconWidth();
}

View file

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

View file

@ -50,7 +50,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
private boolean upgrade = false;
private Map<String, BookmarkType> typesByName = new TreeMap<String, BookmarkType>();
private Map<String, BookmarkType> typesByName = new TreeMap<>();
private ObjectArray typesArray = new ObjectArray();
private Lock lock;
@ -73,7 +73,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
bookmarkTypeAdapter = BookmarkTypeDBAdapter.getAdapter(handle, openMode);
int[] types = bookmarkTypeAdapter.getTypeIds();
bookmarkAdapter = BookmarkDBAdapter.getAdapter(handle, openMode, types, addrMap, monitor);
cache = new DBObjectCache<BookmarkDB>(100);
cache = new DBObjectCache<>(100);
}
@Override
@ -388,16 +388,6 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
lock.acquire();
try {
boolean isSpecificType = type != null && type != BookmarkType.ALL_TYPES;
if (!isSpecificType) {
// no type specified; remove all
Iterator<String> iter = typesByName.keySet().iterator();
while (iter.hasNext()) {
removeBookmarks(iter.next());
}
return;
}
try {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesByName.get(type);
if (bmt.hasBookmarks()) {
@ -474,7 +464,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
lock.acquire();
try {
int n = typesArray.getLastNonEmptyIndex();
List<Bookmark> list = new ArrayList<Bookmark>();
List<Bookmark> list = new ArrayList<>();
for (int i = 0; i <= n; i++) {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
if (bmt != null && bmt.hasBookmarks()) {
@ -512,7 +502,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
lock.acquire();
try {
Bookmark[] bookmarks = null;
List<Bookmark> list = new ArrayList<Bookmark>();
List<Bookmark> list = new ArrayList<>();
BookmarkType bmt = getBookmarkType(type);
if (bmt != null && bmt.hasBookmarks()) {
getBookmarks(address, bmt.getTypeId(), list);
@ -681,18 +671,18 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
@Override
public Iterator<Bookmark> getBookmarksIterator(Address startAddress, boolean forward) {
List<PeekableIterator<Bookmark>> list = new ArrayList<PeekableIterator<Bookmark>>();
List<PeekableIterator<Bookmark>> list = new ArrayList<>();
int n = typesArray.getLastNonEmptyIndex();
for (int i = 0; i <= n; i++) {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);
if (bmt != null && bmt.hasBookmarks()) {
Iterator<Bookmark> bookmarksIterator =
getBookmarksIterator(startAddress, bmt, forward);
list.add(new WrappingPeekableIterator<Bookmark>(bookmarksIterator));
list.add(new WrappingPeekableIterator<>(bookmarksIterator));
}
}
return new MultiIterator<Bookmark>(list, forward);
return new MultiIterator<>(list, forward);
}
@Override
@ -880,7 +870,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager
Iterator<Bookmark> bookmarkIt;
TotalIterator() {
List<BookmarkTypeDB> list = new ArrayList<BookmarkTypeDB>();
List<BookmarkTypeDB> list = new ArrayList<>();
int n = typesArray.getLastNonEmptyIndex();
for (int i = 0; i <= n; i++) {
BookmarkTypeDB bmt = (BookmarkTypeDB) typesArray.get(i);

View file

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

View file

@ -62,7 +62,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
private LiveMemoryHandler liveMemory;
// lazy hashmap of block names to blocks, must be reloaded if blocks are removed or added
private HashMap<String, MemoryBlock> nameBlockMap = new HashMap<String, MemoryBlock>();
private HashMap<String, MemoryBlock> nameBlockMap = new HashMap<>();
private final static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out
Lock lock;
@ -1257,8 +1257,13 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
* Tests if the memory contains a sequence of contiguous bytes that match the given byte array
* at all bit positions where the mask contains an "on" bit. The test will be something like
*
* for(int i=0;i<bytes.length;i++) { if (bytes[i] != memory.getByte(addr+i) &amp; masks[i]) {
* return false; } } return false;
* <PRE>
* 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 bytes the array of bytes to test for.

View file

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

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,38 +29,43 @@ public interface BookmarkType {
public static final String ERROR = "Error";
public static final String WARNING = "Warning";
public static final String ANALYSIS = "Analysis";
public static final String ALL_TYPES = "All Bookmark Types";
/**
* Returns the type as a string
* Returns the type as a string.
* @return the type as a string.
*/
String getTypeString();
public String getTypeString();
/**
* Returns Icon associated with this type or null if one has not been
* set by a plugin.
* @return the icon.
*/
ImageIcon getIcon();
public ImageIcon getIcon();
/**
* Returns marker color associated with this type or null if one has not been
* set by a plugin.
* @return the color.
*/
Color getMarkerColor();
public Color getMarkerColor();
/**
* Returns marker priority associated with this type or -1 if one has not been
* set by a plugin.
* @return the priority.
*/
int getMarkerPriority();
public int getMarkerPriority();
/**
* Returns true if there is at least one bookmark defined for this type
* Returns true if there is at least one bookmark defined for this type.
* @return true if there is at least one bookmark defined for this type.
*/
boolean hasBookmarks();
public boolean hasBookmarks();
/**
* Returns the id associated with this bookmark type.
* @return the id associated with this bookmark type.
*/
int getTypeId();
public int getTypeId();
}