mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/GP-1-dragonmacher-dt-filter-updates--SQUASHED'
This commit is contained in:
commit
9a7d3eb93f
11 changed files with 545 additions and 172 deletions
|
@ -202,7 +202,7 @@ public class BookmarkPlugin extends ProgramPlugin implements PopupActionProvider
|
||||||
*/
|
*/
|
||||||
public void filterBookmarks() {
|
public void filterBookmarks() {
|
||||||
FilterDialog d = new FilterDialog(provider, currentProgram);
|
FilterDialog d = new FilterDialog(provider, currentProgram);
|
||||||
tool.showDialog(d, provider);
|
tool.showDialog(d, provider.getComponent());
|
||||||
provider.contextChanged();
|
provider.contextChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,9 +282,7 @@ public class BookmarkPlugin extends ProgramPlugin implements PopupActionProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disposeAllBookmarkers() {
|
private void disposeAllBookmarkers() {
|
||||||
Iterator<BookmarkNavigator> it = bookmarkNavigators.values().iterator();
|
for (BookmarkNavigator nav : bookmarkNavigators.values()) {
|
||||||
while (it.hasNext()) {
|
|
||||||
BookmarkNavigator nav = it.next();
|
|
||||||
nav.dispose();
|
nav.dispose();
|
||||||
}
|
}
|
||||||
bookmarkNavigators.clear();
|
bookmarkNavigators.clear();
|
||||||
|
@ -624,9 +622,8 @@ public class BookmarkPlugin extends ProgramPlugin implements PopupActionProvider
|
||||||
types.add(type);
|
types.add(type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Iterator<String> it = bookmarkNavigators.keySet().iterator();
|
for (String element : bookmarkNavigators.keySet()) {
|
||||||
while (it.hasNext()) {
|
types.add(element);
|
||||||
types.add(it.next());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateMgr.update();
|
updateMgr.update();
|
||||||
|
@ -655,9 +652,7 @@ public class BookmarkPlugin extends ProgramPlugin implements PopupActionProvider
|
||||||
running = true;
|
running = true;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Iterator<String> it = myTypes.iterator();
|
for (String type : myTypes) {
|
||||||
while (it.hasNext()) {
|
|
||||||
String type = it.next();
|
|
||||||
updateNav(type);
|
updateNav(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class DtFilterAction extends DockingAction {
|
||||||
DataTypesProvider provider = (DataTypesProvider) context.getComponentProvider();
|
DataTypesProvider provider = (DataTypesProvider) context.getComponentProvider();
|
||||||
DtFilterState currentFilterState = provider.getFilterState();
|
DtFilterState currentFilterState = provider.getFilterState();
|
||||||
DtFilterDialog dialog = new DtFilterDialog(currentFilterState);
|
DtFilterDialog dialog = new DtFilterDialog(currentFilterState);
|
||||||
plugin.getTool().showDialog(dialog);
|
plugin.getTool().showDialog(dialog, provider.getComponent());
|
||||||
|
|
||||||
// if not cancelled
|
// if not cancelled
|
||||||
if (dialog.isCancelled()) {
|
if (dialog.isCancelled()) {
|
||||||
|
|
|
@ -22,8 +22,6 @@ import javax.swing.Icon;
|
||||||
import docking.widgets.tree.GTreeNode;
|
import docking.widgets.tree.GTreeNode;
|
||||||
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Enum;
|
|
||||||
import ghidra.program.model.listing.Function;
|
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
@ -61,7 +59,7 @@ public class CategoryNode extends DataTypeTreeNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DataType dataType : dataTypes) {
|
for (DataType dataType : dataTypes) {
|
||||||
if (!isFilteredType(dataType)) {
|
if (passesFilters(dataType)) {
|
||||||
list.add(new DataTypeNode(dataType));
|
list.add(new DataTypeNode(dataType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,33 +69,8 @@ public class CategoryNode extends DataTypeTreeNode {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFilteredType(DataType dataType) {
|
private boolean passesFilters(DataType dataType) {
|
||||||
if (!filterState.isShowArrays() && dataType instanceof Array) {
|
return filterState.passesFilters(dataType);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filterState.isShowPointers() && (dataType instanceof Pointer) &&
|
|
||||||
!(dataType.getDataTypeManager() instanceof BuiltInDataTypeManager)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filterState.isShowEnums() && (dataType instanceof Enum)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filterState.isShowFunctions() && (dataType instanceof Function)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filterState.isShowStructures() && (dataType instanceof Structure)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filterState.isShowUnions() && (dataType instanceof Union)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -212,7 +185,7 @@ public class CategoryNode extends DataTypeTreeNode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFilteredType(dataType)) {
|
if (!passesFilters(dataType)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,25 +15,29 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.datamgr.tree;
|
package ghidra.app.plugin.core.datamgr.tree;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridLayout;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
import docking.DialogComponentProvider;
|
import docking.DialogComponentProvider;
|
||||||
|
import docking.widgets.button.GButton;
|
||||||
import docking.widgets.checkbox.GCheckBox;
|
import docking.widgets.checkbox.GCheckBox;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.layout.PairLayout;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data Types provider dialog to allow users to change the types that are filtered.
|
* Data Types provider dialog to allow users to change the types that are filtered.
|
||||||
*/
|
*/
|
||||||
public class DtFilterDialog extends DialogComponentProvider {
|
public class DtFilterDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private GCheckBox arraysCheckBox = new GCheckBox("Show Arrays");
|
private TypeComponent arraysComponent = new TypeComponent("Arrays");
|
||||||
private GCheckBox enumsCheckBox = new GCheckBox("Show Enums");
|
private TypeComponent enumsComponent = new TypeComponent("Enums");
|
||||||
private GCheckBox functionsCheckBox = new GCheckBox("Show Functions");
|
private TypeComponent functionsComponent = new TypeComponent("Functions");
|
||||||
private GCheckBox pointersCheckBox = new GCheckBox("Show Pointers");
|
private TypeComponent pointersComponent = new TypeComponent("Pointers");
|
||||||
private GCheckBox structuresCheckBox = new GCheckBox("Show Structures");
|
private TypeComponent structuresComponent = new TypeComponent("Structures");
|
||||||
private GCheckBox unionsCheckBox = new GCheckBox("Show Unions");
|
private TypeComponent unionsComponent = new TypeComponent("Unions");
|
||||||
|
|
||||||
private DtFilterState filterState;
|
private DtFilterState filterState;
|
||||||
private boolean isCancelled;
|
private boolean isCancelled;
|
||||||
|
@ -47,7 +51,7 @@ public class DtFilterDialog extends DialogComponentProvider {
|
||||||
addOKButton();
|
addOKButton();
|
||||||
addCancelButton();
|
addCancelButton();
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.DATA_MANAGER, "Set Filter"));
|
setHelpLocation(new HelpLocation(HelpTopics.DATA_MANAGER, "Show Filter"));
|
||||||
|
|
||||||
initCheckBoxes();
|
initCheckBoxes();
|
||||||
setRememberSize(false);
|
setRememberSize(false);
|
||||||
|
@ -70,39 +74,136 @@ public class DtFilterDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
public DtFilterState getFilterState() {
|
public DtFilterState getFilterState() {
|
||||||
DtFilterState newState = new DtFilterState();
|
DtFilterState newState = new DtFilterState();
|
||||||
|
newState.setArraysFilter(arraysComponent.getFilter());
|
||||||
newState.setShowArrays(arraysCheckBox.isSelected());
|
newState.setEnumsFilter(enumsComponent.getFilter());
|
||||||
newState.setShowEnums(enumsCheckBox.isSelected());
|
newState.setFunctionsFilter(functionsComponent.getFilter());
|
||||||
newState.setShowFunctions(functionsCheckBox.isSelected());
|
newState.setPointersFilter(pointersComponent.getFilter());
|
||||||
newState.setShowPointers(pointersCheckBox.isSelected());
|
newState.setStructuresFilter(structuresComponent.getFilter());
|
||||||
newState.setShowStructures(structuresCheckBox.isSelected());
|
newState.setUnionsFilter(unionsComponent.getFilter());
|
||||||
newState.setShowUnions(unionsCheckBox.isSelected());
|
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel buildWorkPanel() {
|
private JPanel buildWorkPanel() {
|
||||||
|
|
||||||
JPanel panel = new JPanel(new PairLayout(5, 10));
|
JPanel panel = new JPanel();
|
||||||
|
panel.setLayout(new GridLayout(0, 2));
|
||||||
|
|
||||||
panel.add(arraysCheckBox);
|
JLabel l1 = new JLabel("<html><b>Show");
|
||||||
panel.add(enumsCheckBox);
|
l1.setHorizontalAlignment(SwingConstants.LEFT);
|
||||||
panel.add(functionsCheckBox);
|
panel.add(l1);
|
||||||
panel.add(pointersCheckBox);
|
|
||||||
panel.add(structuresCheckBox);
|
JLabel l2 = new JLabel("<html><b>Include Typedefs");
|
||||||
panel.add(unionsCheckBox);
|
l2.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
panel.add(l2);
|
||||||
|
|
||||||
|
panel.add(arraysComponent.getLeft());
|
||||||
|
panel.add(arraysComponent.getRight());
|
||||||
|
panel.add(enumsComponent.getLeft());
|
||||||
|
panel.add(enumsComponent.getRight());
|
||||||
|
panel.add(functionsComponent.getLeft());
|
||||||
|
panel.add(functionsComponent.getRight());
|
||||||
|
panel.add(pointersComponent.getLeft());
|
||||||
|
panel.add(pointersComponent.getRight());
|
||||||
|
panel.add(structuresComponent.getLeft());
|
||||||
|
panel.add(structuresComponent.getRight());
|
||||||
|
panel.add(unionsComponent.getLeft());
|
||||||
|
panel.add(unionsComponent.getRight());
|
||||||
|
|
||||||
|
GButton selectAll = new GButton("Select All");
|
||||||
|
GButton deselectAll = new GButton("Deselect All");
|
||||||
|
selectAll.addActionListener(e -> {
|
||||||
|
allButtons().forEach(b -> b.setSelected(true));
|
||||||
|
});
|
||||||
|
deselectAll.addActionListener(e -> {
|
||||||
|
allButtons().forEach(b -> b.setSelected(false));
|
||||||
|
});
|
||||||
|
|
||||||
|
// spacer above buttons
|
||||||
|
panel.add(Box.createRigidArea(new Dimension(10, 10)));
|
||||||
|
panel.add(Box.createRigidArea(new Dimension(10, 10)));
|
||||||
|
|
||||||
|
JPanel p1 = new JPanel();
|
||||||
|
p1.setLayout(new BoxLayout(p1, BoxLayout.LINE_AXIS));
|
||||||
|
p1.add(Box.createHorizontalGlue());
|
||||||
|
p1.add(selectAll);
|
||||||
|
p1.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
JPanel p2 = new JPanel();
|
||||||
|
p2.setLayout(new BoxLayout(p2, BoxLayout.LINE_AXIS));
|
||||||
|
p2.add(Box.createHorizontalGlue());
|
||||||
|
p2.add(deselectAll);
|
||||||
|
p2.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
|
panel.add(p1);
|
||||||
|
panel.add(p2);
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCheckBoxes() {
|
private List<AbstractButton> allButtons() {
|
||||||
|
//@formatter:off
|
||||||
arraysCheckBox.setSelected(filterState.isShowArrays());
|
return List.of(
|
||||||
enumsCheckBox.setSelected(filterState.isShowEnums());
|
arraysComponent.typeCb,
|
||||||
functionsCheckBox.setSelected(filterState.isShowFunctions());
|
arraysComponent.typeDefCb,
|
||||||
pointersCheckBox.setSelected(filterState.isShowPointers());
|
enumsComponent.typeCb,
|
||||||
structuresCheckBox.setSelected(filterState.isShowStructures());
|
enumsComponent.typeDefCb,
|
||||||
unionsCheckBox.setSelected(filterState.isShowUnions());
|
functionsComponent.typeCb,
|
||||||
|
functionsComponent.typeDefCb,
|
||||||
|
pointersComponent.typeCb,
|
||||||
|
pointersComponent.typeDefCb,
|
||||||
|
structuresComponent.typeCb,
|
||||||
|
structuresComponent.typeDefCb,
|
||||||
|
unionsComponent.typeCb,
|
||||||
|
unionsComponent.typeDefCb
|
||||||
|
);
|
||||||
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initCheckBoxes() {
|
||||||
|
arraysComponent.init(filterState.getArraysFilter());
|
||||||
|
enumsComponent.init(filterState.getEnumsFilter());
|
||||||
|
functionsComponent.init(filterState.getFunctionsFilter());
|
||||||
|
pointersComponent.init(filterState.getPointersFilter());
|
||||||
|
structuresComponent.init(filterState.getStructuresFilter());
|
||||||
|
unionsComponent.init(filterState.getUnionsFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TypeComponent {
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private GCheckBox typeCb;
|
||||||
|
private GCheckBox typeDefCb;
|
||||||
|
|
||||||
|
TypeComponent(String type) {
|
||||||
|
this.type = type;
|
||||||
|
this.typeCb = new GCheckBox(type);
|
||||||
|
this.typeDefCb = new GCheckBox();
|
||||||
|
this.typeDefCb.setName(type + "Typedefs");
|
||||||
|
}
|
||||||
|
|
||||||
|
JComponent getLeft() {
|
||||||
|
return typeCb;
|
||||||
|
}
|
||||||
|
|
||||||
|
JComponent getRight() {
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
|
||||||
|
panel.add(Box.createHorizontalGlue());
|
||||||
|
panel.add(typeDefCb);
|
||||||
|
panel.add(Box.createHorizontalGlue());
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(DtTypeFilter typeFilter) {
|
||||||
|
typeCb.setSelected(typeFilter.isTypeActive());
|
||||||
|
typeDefCb.setSelected(typeFilter.isTypeDefActive());
|
||||||
|
}
|
||||||
|
|
||||||
|
DtTypeFilter getFilter() {
|
||||||
|
DtTypeFilter filter = new DtTypeFilter(type);
|
||||||
|
filter.setTypeActive(typeCb.isSelected());
|
||||||
|
filter.setTypeDefActive(typeDefCb.isSelected());
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,11 @@ package ghidra.app.plugin.core.datamgr.tree;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.datamgr.util.DataTypeUtils;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.Enum;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple object to store various filter settings for the data type provider.
|
* A simple object to store various filter settings for the data type provider.
|
||||||
|
@ -26,118 +30,178 @@ public class DtFilterState {
|
||||||
|
|
||||||
private static final String XML_NAME = "DATA_TYPES_FILTER";
|
private static final String XML_NAME = "DATA_TYPES_FILTER";
|
||||||
|
|
||||||
private boolean showArrays = false;
|
private DtTypeFilter arraysFilter = new DtTypeFilter("Arrays");
|
||||||
private boolean showEnums = true;
|
private DtTypeFilter enumsFilter = new DtTypeFilter("Enums");
|
||||||
private boolean showFunctions = true;
|
private DtTypeFilter functionsFilter = new DtTypeFilter("Functions");
|
||||||
private boolean showStructures = true;
|
private DtTypeFilter structuresFilter = new DtTypeFilter("Structures");
|
||||||
private boolean showTypedefs = true;
|
private DtTypeFilter pointersFilter = new DtTypeFilter("Pointers");
|
||||||
private boolean showPointers = false;
|
private DtTypeFilter unionsFilter = new DtTypeFilter("Unions");
|
||||||
private boolean showUnions = true;
|
|
||||||
|
public DtFilterState() {
|
||||||
|
// these types are off by default, since users typically are not working with them
|
||||||
|
arraysFilter.setTypeActive(false);
|
||||||
|
pointersFilter.setTypeActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
public DtFilterState copy() {
|
public DtFilterState copy() {
|
||||||
DtFilterState filterState = new DtFilterState();
|
DtFilterState filterState = new DtFilterState();
|
||||||
filterState.setShowArrays(showArrays);
|
filterState.arraysFilter = arraysFilter.copy();
|
||||||
filterState.setShowEnums(showEnums);
|
filterState.enumsFilter = enumsFilter.copy();
|
||||||
filterState.setShowFunctions(showFunctions);
|
filterState.functionsFilter = functionsFilter.copy();
|
||||||
filterState.setShowStructures(showStructures);
|
filterState.structuresFilter = structuresFilter.copy();
|
||||||
filterState.setShowTypedefs(showTypedefs);
|
filterState.pointersFilter = pointersFilter.copy();
|
||||||
filterState.setShowPointers(showPointers);
|
filterState.unionsFilter = unionsFilter.copy();
|
||||||
filterState.setShowUnions(showUnions);
|
|
||||||
return filterState;
|
return filterState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowPointers() {
|
public boolean isShowArrays() {
|
||||||
return showPointers;
|
return arraysFilter.isTypeActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowPointers(boolean showPointers) {
|
public DtTypeFilter getArraysFilter() {
|
||||||
this.showPointers = showPointers;
|
return arraysFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowStructures() {
|
public void setArraysFilter(DtTypeFilter filter) {
|
||||||
return showStructures;
|
this.arraysFilter = filter;
|
||||||
}
|
|
||||||
|
|
||||||
public void setShowStructures(boolean showStructures) {
|
|
||||||
this.showStructures = showStructures;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isShowTypedefs() {
|
|
||||||
return showStructures;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShowTypedefs(boolean showTypedefs) {
|
|
||||||
this.showTypedefs = showTypedefs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowEnums() {
|
public boolean isShowEnums() {
|
||||||
return showEnums;
|
return enumsFilter.isTypeActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowEnums(boolean showEnums) {
|
public DtTypeFilter getEnumsFilter() {
|
||||||
this.showEnums = showEnums;
|
return enumsFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumsFilter(DtTypeFilter filter) {
|
||||||
|
this.enumsFilter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowFunctions() {
|
public boolean isShowFunctions() {
|
||||||
return showFunctions;
|
return functionsFilter.isTypeActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowFunctions(boolean showFunctions) {
|
public DtTypeFilter getFunctionsFilter() {
|
||||||
this.showFunctions = showFunctions;
|
return functionsFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunctionsFilter(DtTypeFilter filter) {
|
||||||
|
this.functionsFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShowPointers() {
|
||||||
|
return pointersFilter.isTypeActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DtTypeFilter getPointersFilter() {
|
||||||
|
return pointersFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPointersFilter(DtTypeFilter filter) {
|
||||||
|
this.pointersFilter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShowStructures() {
|
||||||
|
return structuresFilter.isTypeActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DtTypeFilter getStructuresFilter() {
|
||||||
|
return structuresFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStructuresFilter(DtTypeFilter filter) {
|
||||||
|
this.structuresFilter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowUnions() {
|
public boolean isShowUnions() {
|
||||||
return showUnions;
|
return unionsFilter.isTypeActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowUnions(boolean showUnions) {
|
public DtTypeFilter getUnionsFilter() {
|
||||||
this.showUnions = showUnions;
|
return unionsFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShowArrays() {
|
public void setUnionsFilter(DtTypeFilter filter) {
|
||||||
return showArrays;
|
this.unionsFilter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowArrays(boolean showArrays) {
|
public boolean passesFilters(DataType dt) {
|
||||||
this.showArrays = showArrays;
|
|
||||||
|
DataTypeManager dtm = dt.getDataTypeManager();
|
||||||
|
if (dtm instanceof BuiltInDataTypeManager) {
|
||||||
|
// never filter built-in types here; users can filter them using the text filter
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setshowPointers(boolean showPointers) {
|
DataType baseDt = DataTypeUtils.getBaseDataType(dt);
|
||||||
this.showPointers = showPointers;
|
|
||||||
|
if (dt instanceof Array) {
|
||||||
|
return passes(arraysFilter, dt, baseDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dt instanceof Pointer) {
|
||||||
|
return passes(pointersFilter, dt, baseDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseDt instanceof Enum) {
|
||||||
|
return passes(enumsFilter, dt, baseDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseDt instanceof Function) {
|
||||||
|
return passes(functionsFilter, dt, baseDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseDt instanceof Structure) {
|
||||||
|
return passes(structuresFilter, dt, baseDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseDt instanceof Union) {
|
||||||
|
return passes(unionsFilter, dt, baseDt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean passes(DtTypeFilter filter, DataType dt, DataType baseDt) {
|
||||||
|
if (filter.isTypeActive()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (filter.isTypeDefActive() && dt instanceof TypeDef) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(SaveState parentSaveState) {
|
public void save(SaveState parentSaveState) {
|
||||||
|
|
||||||
SaveState saveState = new SaveState(XML_NAME);
|
SaveState ss = new SaveState(XML_NAME);
|
||||||
saveState.putBoolean("SHOW_ARRAYS", showArrays);
|
ss.putSaveState(arraysFilter.getName(), arraysFilter.save());
|
||||||
saveState.putBoolean("SHOW_ENUMS", showEnums);
|
ss.putSaveState(enumsFilter.getName(), enumsFilter.save());
|
||||||
saveState.putBoolean("SHOW_FUNCTIONS", showFunctions);
|
ss.putSaveState(functionsFilter.getName(), functionsFilter.save());
|
||||||
saveState.putBoolean("SHOW_POINTERS", showPointers);
|
ss.putSaveState(pointersFilter.getName(), pointersFilter.save());
|
||||||
saveState.putBoolean("SHOW_STRUCTURES", showStructures);
|
ss.putSaveState(structuresFilter.getName(), structuresFilter.save());
|
||||||
saveState.putBoolean("SHOW_TYPEDEFS", showTypedefs);
|
ss.putSaveState(unionsFilter.getName(), unionsFilter.save());
|
||||||
saveState.putBoolean("SHOW_UNIONS", showUnions);
|
|
||||||
|
|
||||||
parentSaveState.putSaveState(XML_NAME, saveState);
|
parentSaveState.putSaveState(XML_NAME, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore(SaveState parentSaveState) {
|
public void restore(SaveState parentSaveState) {
|
||||||
|
|
||||||
parentSaveState.getSaveState(XML_NAME);
|
SaveState ss = parentSaveState.getSaveState(XML_NAME);
|
||||||
SaveState saveState = new SaveState();
|
|
||||||
|
|
||||||
showArrays = saveState.getBoolean("SHOW_ARRAYS", false);
|
arraysFilter = DtTypeFilter.restore("Arrays", ss.getSaveState("Arrays"));
|
||||||
showEnums = saveState.getBoolean("SHOW_ENUMS", true);
|
enumsFilter = DtTypeFilter.restore("Enums", ss.getSaveState("Enums"));
|
||||||
showFunctions = saveState.getBoolean("SHOW_FUNCTIONS", true);
|
functionsFilter = DtTypeFilter.restore("Functions", ss.getSaveState("Functions"));
|
||||||
showPointers = saveState.getBoolean("SHOW_POINTERS", false);
|
pointersFilter = DtTypeFilter.restore("Pointers", ss.getSaveState("Pointers"));
|
||||||
showStructures = saveState.getBoolean("SHOW_STRUCTURES", true);
|
structuresFilter = DtTypeFilter.restore("Structures", ss.getSaveState("Structures"));
|
||||||
showTypedefs = saveState.getBoolean("SHOW_TYPEDEFS", true);
|
unionsFilter = DtTypeFilter.restore("Unions", ss.getSaveState("Unions"));
|
||||||
showUnions = saveState.getBoolean("SHOW_UNIONS", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(showArrays, showEnums, showFunctions, showPointers, showStructures,
|
return Objects.hash(arraysFilter, enumsFilter, functionsFilter, pointersFilter,
|
||||||
showTypedefs, showUnions);
|
structuresFilter, unionsFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -152,10 +216,12 @@ public class DtFilterState {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DtFilterState other = (DtFilterState) obj;
|
DtFilterState other = (DtFilterState) obj;
|
||||||
return showArrays == other.showArrays && showEnums == other.showEnums &&
|
return Objects.equals(arraysFilter, other.arraysFilter) &&
|
||||||
showFunctions == other.showFunctions && showPointers == other.showPointers &&
|
Objects.equals(enumsFilter, other.enumsFilter) &&
|
||||||
showStructures == other.showStructures && showTypedefs == other.showTypedefs &&
|
Objects.equals(functionsFilter, other.functionsFilter) &&
|
||||||
showUnions == other.showUnions;
|
Objects.equals(pointersFilter, other.pointersFilter) &&
|
||||||
|
Objects.equals(structuresFilter, other.structuresFilter) &&
|
||||||
|
Objects.equals(unionsFilter, other.unionsFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* ###
|
||||||
|
* 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.datamgr.tree;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import generic.json.Json;
|
||||||
|
import ghidra.framework.options.SaveState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that holds enabled state for a type and related typedefs.
|
||||||
|
*/
|
||||||
|
public class DtTypeFilter {
|
||||||
|
|
||||||
|
private static final String IS_TYPE_ACTIVE_KEY = "IS_TYPE_ACTIVE";
|
||||||
|
private static final String IS_TYPE_DEF_ACTIVE_KEY = "IS_TYPE_DEF_ACTIVE";
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private boolean isTypeActive = true;
|
||||||
|
private boolean isTypeDefActive = true;
|
||||||
|
|
||||||
|
static DtTypeFilter restore(String typeName, SaveState ss) {
|
||||||
|
if (ss == null) {
|
||||||
|
return new DtTypeFilter(typeName);
|
||||||
|
}
|
||||||
|
return new DtTypeFilter(ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
DtTypeFilter(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DtTypeFilter(SaveState ss) {
|
||||||
|
name = ss.getName();
|
||||||
|
isTypeActive = ss.getBoolean(IS_TYPE_ACTIVE_KEY, true);
|
||||||
|
isTypeDefActive = ss.getBoolean(IS_TYPE_DEF_ACTIVE_KEY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveState save() {
|
||||||
|
SaveState ss = new SaveState(name);
|
||||||
|
ss.putBoolean(IS_TYPE_ACTIVE_KEY, isTypeActive);
|
||||||
|
ss.putBoolean(IS_TYPE_DEF_ACTIVE_KEY, isTypeDefActive);
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
DtTypeFilter copy() {
|
||||||
|
DtTypeFilter filter = new DtTypeFilter(name);
|
||||||
|
filter.isTypeActive = isTypeActive;
|
||||||
|
filter.isTypeDefActive = isTypeDefActive;
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTypeActive() {
|
||||||
|
return isTypeActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTypeDefActive() {
|
||||||
|
return isTypeDefActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeActive(boolean b) {
|
||||||
|
this.isTypeActive = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeDefActive(boolean b) {
|
||||||
|
this.isTypeDefActive = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Json.toString(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(isTypeActive, isTypeDefActive, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DtTypeFilter other = (DtTypeFilter) obj;
|
||||||
|
return isTypeActive == other.isTypeActive && isTypeDefActive == other.isTypeDefActive &&
|
||||||
|
Objects.equals(name, other.name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -166,6 +166,14 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
myStruct.setCategoryPath(cat2Path);
|
myStruct.setCategoryPath(cat2Path);
|
||||||
builder.addDataType(myStruct);
|
builder.addDataType(myStruct);
|
||||||
|
|
||||||
|
TypedefDataType typeDefMyStruct = new TypedefDataType("TypeDefToMyStruct", myStruct);
|
||||||
|
builder.addDataType(typeDefMyStruct);
|
||||||
|
|
||||||
|
Pointer16DataType ptr16 = new Pointer16DataType(new CharDataType());
|
||||||
|
builder.addDataType(ptr16);
|
||||||
|
ArrayDataType charDt = new ArrayDataType(new CharDataType(), 10);
|
||||||
|
builder.addDataType(charDt);
|
||||||
|
|
||||||
return builder.getProgram();
|
return builder.getProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,20 +920,51 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFilter() {
|
public void testFilter_DefaultFilter() {
|
||||||
|
|
||||||
|
DtFilterState filterState = provider.getFilterState();
|
||||||
|
assertFalse(filterState.getArraysFilter().isTypeActive());
|
||||||
|
assertFalse(filterState.getPointersFilter().isTypeActive());
|
||||||
|
|
||||||
|
DataTypeManager[] dtms = plugin.getDataTypeManagers();
|
||||||
|
for (DataTypeManager dtm : dtms) {
|
||||||
|
if (dtm instanceof BuiltInDataTypeManager) {
|
||||||
|
assertAllTypesInTree(dtm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertNoArrays(dtm);
|
||||||
|
assertNoPointers(dtm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFilter_Structures() {
|
||||||
|
|
||||||
|
assertStructures(true);
|
||||||
|
assertType("TypeDefToMyStruct", true);
|
||||||
|
|
||||||
// press the filter button
|
// press the filter button
|
||||||
DockingActionIf action = getAction(plugin, "Show Filter");
|
DockingActionIf action = getAction(plugin, "Show Filter");
|
||||||
performAction(action, provider, false);
|
performAction(action, provider, false);
|
||||||
|
|
||||||
assertStructures(true);
|
|
||||||
|
|
||||||
DtFilterDialog dialog = waitForDialogComponent(DtFilterDialog.class);
|
DtFilterDialog dialog = waitForDialogComponent(DtFilterDialog.class);
|
||||||
setToggleButtonSelected(dialog.getComponent(), "Show Structures", false);
|
setToggleButtonSelected(dialog.getComponent(), "Structures", false);
|
||||||
pressButtonByText(dialog, "OK");
|
pressButtonByText(dialog, "OK");
|
||||||
waitForTree();
|
waitForTree();
|
||||||
|
|
||||||
assertStructures(false);
|
assertStructures(false);
|
||||||
|
assertType("TypeDefToMyStruct", true);
|
||||||
|
|
||||||
|
// Now also turn off typedefs
|
||||||
|
performAction(action, provider, false);
|
||||||
|
dialog = waitForDialogComponent(DtFilterDialog.class);
|
||||||
|
setToggleButtonSelected(dialog.getComponent(), "StructuresTypedefs", false);
|
||||||
|
pressButtonByText(dialog, "OK");
|
||||||
|
waitForTree();
|
||||||
|
|
||||||
|
assertStructures(false);
|
||||||
|
assertType("TypeDefToMyStruct", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -935,7 +974,7 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
// press the filter button
|
// press the filter button
|
||||||
DtFilterDialog mainDialog = showFilterDialog(provider);
|
DtFilterDialog mainDialog = showFilterDialog(provider);
|
||||||
boolean isShowingStructures = false;
|
boolean isShowingStructures = false;
|
||||||
updateFilter(mainDialog, "Show Structures", isShowingStructures);
|
updateFilter(mainDialog, "Structures", isShowingStructures);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Launch a new data types provider window to verify it has the same settings as the main
|
// Launch a new data types provider window to verify it has the same settings as the main
|
||||||
|
@ -954,7 +993,7 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
|
|
||||||
// now change the new provider's filter for a different option and then make sure that the
|
// now change the new provider's filter for a different option and then make sure that the
|
||||||
// main provider is not changed
|
// main provider is not changed
|
||||||
updateFilter(otherFilterDialog, "Show Functions", false);
|
updateFilter(otherFilterDialog, "Functions", false);
|
||||||
|
|
||||||
DtFilterState mainFilterState = runSwing(() -> provider.getFilterState());
|
DtFilterState mainFilterState = runSwing(() -> provider.getFilterState());
|
||||||
DtFilterState otherFilterState = runSwing(() -> otherProvider.getFilterState());
|
DtFilterState otherFilterState = runSwing(() -> otherProvider.getFilterState());
|
||||||
|
@ -967,11 +1006,11 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
public void testSaveRestoreFilterStates() throws Exception {
|
public void testSaveRestoreFilterStates() throws Exception {
|
||||||
|
|
||||||
DtFilterDialog dialog = showFilterDialog(provider);
|
DtFilterDialog dialog = showFilterDialog(provider);
|
||||||
boolean isShowingEnums = getFilterState(dialog, "Show Enums");
|
boolean isShowingEnums = getFilterState(dialog, "Enums");
|
||||||
boolean isShowingUnions = getFilterState(dialog, "Show Unions");
|
boolean isShowingUnions = getFilterState(dialog, "Unions");
|
||||||
|
|
||||||
setToggleButtonSelected(dialog.getComponent(), "Show Enums", !isShowingEnums);
|
setToggleButtonSelected(dialog.getComponent(), "Enums", !isShowingEnums);
|
||||||
setToggleButtonSelected(dialog.getComponent(), "Show Unions", !isShowingUnions);
|
setToggleButtonSelected(dialog.getComponent(), "Unions", !isShowingUnions);
|
||||||
pressButtonByText(dialog, "OK");
|
pressButtonByText(dialog, "OK");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
|
@ -988,6 +1027,88 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
// Private methods
|
// Private methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
|
private void assertNoArrays(DataTypeManager dtm) {
|
||||||
|
Map<String, DataTypeNode> nodesByName = getNodes(dtm);
|
||||||
|
Collection<DataTypeNode> values = nodesByName.values();
|
||||||
|
for (DataTypeNode node : values) {
|
||||||
|
DataType dt = node.getDataType();
|
||||||
|
assertTrue("Found an array in '%s'".formatted(dtm.getName()),
|
||||||
|
!(dt instanceof Array));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNoPointers(DataTypeManager dtm) {
|
||||||
|
Map<String, DataTypeNode> nodesByName = getNodes(dtm);
|
||||||
|
Collection<DataTypeNode> values = nodesByName.values();
|
||||||
|
for (DataTypeNode node : values) {
|
||||||
|
DataType dt = node.getDataType();
|
||||||
|
assertTrue("Found a pointer in '%s'".formatted(dtm.getName()),
|
||||||
|
!(dt instanceof Pointer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertAllTypesInTree(DataTypeManager dtm) {
|
||||||
|
Iterator<DataType> types = dtm.getAllDataTypes();
|
||||||
|
Map<String, DataTypeNode> nodesByName = getNodes(dtm);
|
||||||
|
for (DataType dt : CollectionUtils.asIterable(types)) {
|
||||||
|
assertNotNull(
|
||||||
|
"Node not found for type '%s' in dtm '%s'".formatted(dt.getName(), dtm.getName()),
|
||||||
|
nodesByName.get(dt.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, DataTypeNode> getNodes(DataTypeManager dtm) {
|
||||||
|
|
||||||
|
DataTypeArchiveGTree gTree = provider.getGTree();
|
||||||
|
GTreeNode rootNode = gTree.getViewRoot();
|
||||||
|
GTreeNode dtmNode = rootNode.getChild(dtm.getName());
|
||||||
|
assertNotNull(dtmNode);
|
||||||
|
|
||||||
|
expandNode(dtmNode);
|
||||||
|
|
||||||
|
Map<String, DataTypeNode> nodesByName = new HashMap<>();
|
||||||
|
Iterator<GTreeNode> it = dtmNode.iterator(true);
|
||||||
|
for (GTreeNode node : CollectionUtils.asIterable(it)) {
|
||||||
|
if (!(node instanceof DataTypeNode)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DataTypeNode dtNode = (DataTypeNode) node;
|
||||||
|
DataType dt = dtNode.getDataType();
|
||||||
|
nodesByName.put(dt.getName(), dtNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodesByName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertType(String name, boolean isShowing) {
|
||||||
|
|
||||||
|
DataType dt = getTypeFromTree(name);
|
||||||
|
if (isShowing) {
|
||||||
|
assertNotNull("Data type not found: '%s'", dt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertNull(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataType getTypeFromTree(String name) {
|
||||||
|
DataTypeArchiveGTree gTree = provider.getGTree();
|
||||||
|
GTreeNode rootNode = gTree.getViewRoot();
|
||||||
|
Iterator<GTreeNode> it = rootNode.iterator(true);
|
||||||
|
for (GTreeNode node : CollectionUtils.asIterable(it)) {
|
||||||
|
if (!(node instanceof DataTypeNode)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DataTypeNode dtNode = (DataTypeNode) node;
|
||||||
|
DataType dt = dtNode.getDataType();
|
||||||
|
String dtName = dt.getName();
|
||||||
|
if (dtName.equals(name)) {
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean getFilterState(DtFilterDialog dialog, String optionName) {
|
private boolean getFilterState(DtFilterDialog dialog, String optionName) {
|
||||||
return isToggleButttonSelected(dialog.getComponent(), optionName);
|
return isToggleButttonSelected(dialog.getComponent(), optionName);
|
||||||
}
|
}
|
||||||
|
@ -1265,7 +1386,7 @@ public class DataTypeManagerPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
performAction(action, provider, false);
|
performAction(action, provider, false);
|
||||||
|
|
||||||
DtFilterDialog dialog = waitForDialogComponent(DtFilterDialog.class);
|
DtFilterDialog dialog = waitForDialogComponent(DtFilterDialog.class);
|
||||||
setToggleButtonSelected(dialog.getComponent(), "Show Pointers", true);
|
setToggleButtonSelected(dialog.getComponent(), "Pointers", true);
|
||||||
pressButtonByText(dialog, "OK");
|
pressButtonByText(dialog, "OK");
|
||||||
waitForTree();
|
waitForTree();
|
||||||
}
|
}
|
||||||
|
|
|
@ -383,7 +383,8 @@ public class GoToAddressLabelPluginTest extends AbstractGhidraHeadedIntegrationT
|
||||||
// The default space and 'Test Overlay 1' each have an address for 1002000. The
|
// The default space and 'Test Overlay 1' each have an address for 1002000. The
|
||||||
// 'Test Overlay 2' does not. So, put the cursor there.
|
// 'Test Overlay 2' does not. So, put the cursor there.
|
||||||
String name = overlay2Block.getName();
|
String name = overlay2Block.getName();
|
||||||
assertTrue(cbPlugin.goTo(new ProgramLocation(program, addr(name + "::1003000"))));
|
ProgramLocation location = new ProgramLocation(program, addr(name + "::1003000"));
|
||||||
|
assertTrue(cbPlugin.goTo(location));
|
||||||
|
|
||||||
showDialog();
|
showDialog();
|
||||||
setText("1002000");
|
setText("1002000");
|
||||||
|
|
|
@ -494,9 +494,7 @@ public class GProperties {
|
||||||
*/
|
*/
|
||||||
public Element saveToXml() {
|
public Element saveToXml() {
|
||||||
Element root = new Element(propertiesName);
|
Element root = new Element(propertiesName);
|
||||||
Iterator<String> iter = map.keySet().iterator();
|
for (String key : map.keySet()) {
|
||||||
while (iter.hasNext()) {
|
|
||||||
String key = iter.next();
|
|
||||||
Object value = map.get(key);
|
Object value = map.get(key);
|
||||||
Element elem = createElement(key, value);
|
Element elem = createElement(key, value);
|
||||||
root.addContent(elem);
|
root.addContent(elem);
|
||||||
|
@ -638,9 +636,7 @@ public class GProperties {
|
||||||
JsonObject types = new JsonObject();
|
JsonObject types = new JsonObject();
|
||||||
JsonObject values = new JsonObject();
|
JsonObject values = new JsonObject();
|
||||||
JsonObject enumClasses = new JsonObject();
|
JsonObject enumClasses = new JsonObject();
|
||||||
Iterator<String> iter = map.keySet().iterator();
|
for (String key : map.keySet()) {
|
||||||
while (iter.hasNext()) {
|
|
||||||
String key = iter.next();
|
|
||||||
Object value = map.get(key);
|
Object value = map.get(key);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
types.addProperty(key, "null");
|
types.addProperty(key, "null");
|
||||||
|
@ -835,15 +831,22 @@ public class GProperties {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the names of the properties in this GProperties.
|
* Returns the name of this GProperties
|
||||||
* @return the names of the properties in this GProperties.
|
* @return the name of this GProperties
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return propertiesName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the names of the properties in this GProperties
|
||||||
|
* @return the names of the properties in this GProperties
|
||||||
*/
|
*/
|
||||||
public String[] getNames() {
|
public String[] getNames() {
|
||||||
String[] names = new String[map.size()];
|
String[] names = new String[map.size()];
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
Iterator<String> iter = map.keySet().iterator();
|
for (String element : map.keySet()) {
|
||||||
while (iter.hasNext()) {
|
names[idx] = element;
|
||||||
names[idx] = iter.next();
|
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
|
|
|
@ -114,6 +114,7 @@ public class SaveState extends XmlProperties {
|
||||||
return getAsType(name, null, SaveState.class);
|
return getAsType(name, null, SaveState.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void processElement(Element element) {
|
protected void processElement(Element element) {
|
||||||
String tag = element.getName();
|
String tag = element.getName();
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ public interface FunctionDefinition extends DataType, FunctionSignature {
|
||||||
* @deprecated Use of {@link GenericCallingConvention} is deprecated since arbitrary calling
|
* @deprecated Use of {@link GenericCallingConvention} is deprecated since arbitrary calling
|
||||||
* convention names are now supported. {@link #setCallingConvention(String)} should be used.
|
* convention names are now supported. {@link #setCallingConvention(String)} should be used.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention);
|
public void setGenericCallingConvention(GenericCallingConvention genericCallingConvention);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue