mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-22 19:15:32 +08:00
GP-1689 - Added analysis options update mechanism to allow for changing option names and types
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
/* ###
|
||||
* 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.analysis;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import ghidra.framework.options.Options;
|
||||
|
||||
/**
|
||||
* An object that allows analyzers to rename options. This is required to move old options stored
|
||||
* in the program to the new equivalent option. This class is not required for options that have
|
||||
* simply been removed.
|
||||
* <p>
|
||||
* Notes:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Replacement options must be registered with one of the register methods of this class.
|
||||
* </li>
|
||||
* <li>
|
||||
* This is intended for use with the UI; access analysis options from the API will not use this
|
||||
* replacer. This means that any client, such as script, retrieving the old option value will not
|
||||
* work for new programs that no longer have that old option registered. Further, for programs
|
||||
* that have the old options saved, but no longer registered, changing the old option value will
|
||||
* have no effect.
|
||||
* </li>
|
||||
* <li>
|
||||
* Old option values will only be used if they are non-default and the new option value is default.
|
||||
* </li>
|
||||
* <li>
|
||||
* Clients can change the type of the option if they wish using
|
||||
* {@link #registerReplacement(String, String, Function)}.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public class AnalysisOptionsUpdater {
|
||||
|
||||
private static final Function<Object, Object> OLD_VALUE_REPLACER = oldValue -> oldValue;
|
||||
|
||||
private Map<String, ReplaceableOption> optionsByNewName = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Register the given old option name to be replaced with the new option name. The
|
||||
* replacement strategy used in this case will be to return the old value for the new option.
|
||||
* @param newOptionName the new option name
|
||||
* @param oldOptionName the old option name
|
||||
*/
|
||||
public void registerReplacement(String newOptionName, String oldOptionName) {
|
||||
|
||||
registerReplacement(newOptionName, oldOptionName, OLD_VALUE_REPLACER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given old option name to be replaced with the new option name. The given
|
||||
* replacer function will be called with the old option value to get the new option value.
|
||||
* @param newOptionName the new option name
|
||||
* @param oldOptionName the old option name
|
||||
* @param replacer the function to update the update the old option value
|
||||
*/
|
||||
public void registerReplacement(String newOptionName, String oldOptionName,
|
||||
Function<Object, Object> replacer) {
|
||||
|
||||
optionsByNewName.put(newOptionName,
|
||||
new ReplaceableOption(newOptionName, oldOptionName, replacer));
|
||||
}
|
||||
|
||||
Set<ReplaceableOption> getReplaceableOptions() {
|
||||
return new HashSet<>(optionsByNewName.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple object that contains the new and old option name along with the replacer function
|
||||
* that will handle the option replacement.
|
||||
*/
|
||||
public static class ReplaceableOption {
|
||||
|
||||
private final String newName;
|
||||
private final String oldName;
|
||||
private final Function<Object, Object> replacer;
|
||||
|
||||
ReplaceableOption(String newName, String oldName, Function<Object, Object> replacer) {
|
||||
this.newName = newName;
|
||||
this.oldName = oldName;
|
||||
this.replacer = replacer;
|
||||
}
|
||||
|
||||
// note: this method expects to be called within a transaction
|
||||
void replace(Options options) {
|
||||
Object oldValue = options.getObject(oldName, null);
|
||||
if (oldValue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.isDefaultValue(oldName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.isDefaultValue(newName)) {
|
||||
return; // don't overwrite user's updated value
|
||||
}
|
||||
|
||||
Object newValue = replacer.apply(oldValue);
|
||||
options.putObject(newName, newValue);
|
||||
}
|
||||
|
||||
String getNewName() {
|
||||
return newName;
|
||||
}
|
||||
|
||||
String getOldName() {
|
||||
return oldName;
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
-8
@@ -40,6 +40,7 @@ import docking.widgets.combobox.GhidraComboBox;
|
||||
import docking.widgets.label.GLabel;
|
||||
import docking.widgets.table.GTable;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.plugin.core.analysis.AnalysisOptionsUpdater.ReplaceableOption;
|
||||
import ghidra.app.services.Analyzer;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.GenericRunInfo;
|
||||
@@ -70,13 +71,15 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
// preference which retains last used analyzer_options file name
|
||||
public static final String LAST_USED_OPTIONS_CONFIG = "LAST_USED_OPTIONS_CONFIG";
|
||||
|
||||
static final String ANALYZER_OPTIONS_PANEL_NAME = "analyzer.options.panel";
|
||||
|
||||
private List<Program> programs;
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Options analysisOptions;
|
||||
private Options currentProgramOptions; // this will have all the non-default options from the program
|
||||
private Options selectedOptions = STANDARD_DEFAULT_OPTIONS;
|
||||
|
||||
private JTable table;
|
||||
private GTable table;
|
||||
private AnalysisEnablementTableModel model;
|
||||
private JTextArea descriptionComponent;
|
||||
private JPanel analyzerOptionsPanel;
|
||||
@@ -130,6 +133,9 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
currentProgramOptions = getNonDefaultProgramOptions();
|
||||
setName("Analysis Panel");
|
||||
build();
|
||||
|
||||
replaceOldOptions();
|
||||
|
||||
load();
|
||||
loadCurrentOptionsIntoEditors();
|
||||
}
|
||||
@@ -169,13 +175,13 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
Program program = programs.get(0);
|
||||
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(program);
|
||||
|
||||
List<String> propertyNames = analysisOptions.getOptionNames();
|
||||
Collections.sort(propertyNames, (o1, o2) -> o1.compareToIgnoreCase(o2));
|
||||
for (String analyzerName : propertyNames) {
|
||||
List<String> optionNames = analysisOptions.getOptionNames();
|
||||
Collections.sort(optionNames, (o1, o2) -> o1.compareToIgnoreCase(o2));
|
||||
for (String analyzerName : optionNames) {
|
||||
if (analyzerName.indexOf('.') == -1) {
|
||||
if (analysisOptions.getType(analyzerName) != OptionType.BOOLEAN_TYPE) {
|
||||
throw new AssertException(
|
||||
"Analyzer enable property that is not boolean - " + analyzerName);
|
||||
"Analyzer 'enable' property that is not boolean - " + analyzerName);
|
||||
}
|
||||
|
||||
Analyzer analyzer = manager.getAnalyzer(analyzerName);
|
||||
@@ -408,7 +414,7 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
|
||||
private void reloadOptionsCombo(Options newDefaultOptions) {
|
||||
optionConfigurationChoices = loadPossibleOptionsChoicesForComboBox();
|
||||
optionsComboBox.setModel(new DefaultComboBoxModel<Options>(optionConfigurationChoices));
|
||||
optionsComboBox.setModel(new DefaultComboBoxModel<>(optionConfigurationChoices));
|
||||
Options selected = findOptionsByName(newDefaultOptions.getName());
|
||||
optionsComboBox.setSelectedItem(selected);
|
||||
}
|
||||
@@ -587,6 +593,66 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceOldOptions() {
|
||||
|
||||
for (Program program : programs) {
|
||||
|
||||
boolean commit = false;
|
||||
int id = program.startTransaction("Replacing old analysis properties");
|
||||
try {
|
||||
doReplaceOldOptions(program);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(id, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doReplaceOldOptions(Program program) {
|
||||
|
||||
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(program);
|
||||
|
||||
Options programAnalysisOptions = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
||||
List<Options> allAnalyzersOptions = programAnalysisOptions.getChildOptions();
|
||||
for (Options analyzerOptions : allAnalyzersOptions) {
|
||||
String analyzerName = analyzerOptions.getName();
|
||||
Analyzer analyzer = manager.getAnalyzer(analyzerName);
|
||||
if (analyzer == null) {
|
||||
// can be null if an analyzer no longer exists
|
||||
continue;
|
||||
}
|
||||
AnalysisOptionsUpdater updater = analyzer.getOptionsUpdater();
|
||||
if (updater == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
applyOptionUpdater(analyzerOptions, updater);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyOptionUpdater(Options analyzerOptions, AnalysisOptionsUpdater updater) {
|
||||
|
||||
Set<ReplaceableOption> replaceableOptions = updater.getReplaceableOptions();
|
||||
for (ReplaceableOption ro : replaceableOptions) {
|
||||
String newName = ro.getNewName();
|
||||
String oldName = ro.getOldName();
|
||||
if (!analyzerOptions.contains(oldName)) {
|
||||
continue; // the old option was never saved or has been removed
|
||||
}
|
||||
|
||||
if (!analyzerOptions.contains(newName)) {
|
||||
Msg.error(this,
|
||||
"Found an option replacer without having the new option registered" +
|
||||
"new option: '" + newName + "'; old option: '" + oldName + "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
ro.replace(analyzerOptions);
|
||||
analyzerOptions.removeOption(ro.getOldName());
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAnalyzerOptionsPanels() {
|
||||
List<Options> optionGroups = analysisOptions.getChildOptions();
|
||||
noOptionsPanel = new JPanel(new VerticalLayout(5));
|
||||
@@ -599,6 +665,7 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
String analyzerName = optionsGroup.getName();
|
||||
|
||||
JPanel optionsContainer = new JPanel(new VerticalLayout(5));
|
||||
optionsContainer.setName(ANALYZER_OPTIONS_PANEL_NAME);
|
||||
optionsContainer.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(optionsContainer);
|
||||
@@ -645,11 +712,17 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||
List<String> subOptions = optionsGroup.getLeafOptionNames();
|
||||
Iterator<String> it = subOptions.iterator();
|
||||
while (it.hasNext()) {
|
||||
String next = it.next();
|
||||
if (!isEditable(optionsGroup, next)) {
|
||||
String name = it.next();
|
||||
if (!isEditable(optionsGroup, name)) {
|
||||
it.remove();
|
||||
}
|
||||
|
||||
// also filter out unregistered options
|
||||
if (!optionsGroup.isRegistered(name)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return subOptions;
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -90,8 +90,7 @@ class AnalyzeAllOpenProgramsTask extends Task {
|
||||
return; // no need to log this - it's a valid condition
|
||||
}
|
||||
|
||||
AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(prototypeProgram);
|
||||
if (!setOptions(prototypeProgram, mgr)) {
|
||||
if (!setOptions(prototypeProgram)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -169,7 +168,7 @@ class AnalyzeAllOpenProgramsTask extends Task {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setOptions(final Program program, AutoAnalysisManager mgr) {
|
||||
private boolean setOptions(final Program program) {
|
||||
AtomicBoolean analyze = new AtomicBoolean();
|
||||
int id = program.startTransaction("analysis");
|
||||
try {
|
||||
|
||||
+5
-24
@@ -63,21 +63,15 @@ import ghidra.util.task.TaskLauncher;
|
||||
public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerListener {
|
||||
|
||||
private static final String SHOW_ANALYSIS_OPTIONS = "Show Analysis Options";
|
||||
|
||||
private static final String ANALYZE_GROUP_NAME = "Analyze";
|
||||
|
||||
private DockingAction autoAnalyzeAction;
|
||||
private DockingAction analyzeAllAction;
|
||||
|
||||
private HelpLocation helpLocation;
|
||||
|
||||
private List<Analyzer> analyzers = new ArrayList<>();
|
||||
private List<OneShotAnalyzerAction> oneShotActions = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance of the plugin giving it the tool that it will work
|
||||
* in.
|
||||
*/
|
||||
public AutoAnalysisPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
|
||||
@@ -125,8 +119,7 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
|
||||
.onAction(this::analyzeCallback)
|
||||
.buildAndInstall(tool);
|
||||
|
||||
analyzeAllAction =
|
||||
new ActionBuilder("Analyze All Open", getName())
|
||||
new ActionBuilder("Analyze All Open", getName())
|
||||
.supportsDefaultToolContext(true)
|
||||
.menuPath("&Analysis", "Analyze All &Open...")
|
||||
.menuGroup(ANALYZE_GROUP_NAME, "" + subGroupIndex++)
|
||||
@@ -206,31 +199,18 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
|
||||
analysisMgr.reAnalyzeAll(selection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of this plugin.
|
||||
*/
|
||||
public static String getDescription() {
|
||||
return "Provides coordination and a service for All Auto Analysis tasks";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the descriptive name.
|
||||
*/
|
||||
public static String getDescriptiveName() {
|
||||
return "AutoAnalysisManager";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category.
|
||||
*/
|
||||
public static String getCategory() {
|
||||
return "Analysis";
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of AutoAnalysis Service
|
||||
*/
|
||||
|
||||
protected void programClosed(Program program) {
|
||||
|
||||
if (AutoAnalysisManager.hasAutoAnalysisManager(program)) {
|
||||
@@ -276,9 +256,10 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
|
||||
|
||||
private void programActivated(final Program program) {
|
||||
|
||||
program.getOptions(StoredAnalyzerTimes.OPTIONS_LIST).registerOption(
|
||||
StoredAnalyzerTimes.OPTION_NAME, OptionType.CUSTOM_TYPE, null, null,
|
||||
"Cumulative analysis task times", new StoredAnalyzerTimesPropertyEditor());
|
||||
program.getOptions(StoredAnalyzerTimes.OPTIONS_LIST)
|
||||
.registerOption(
|
||||
StoredAnalyzerTimes.OPTION_NAME, OptionType.CUSTOM_TYPE, null, null,
|
||||
"Cumulative analysis task times", new StoredAnalyzerTimesPropertyEditor());
|
||||
|
||||
// invokeLater() to ensure that all other plugins have been notified of the program
|
||||
// activated. This makes sure plugins like the Listing have opened and painted the
|
||||
|
||||
+73
-18
@@ -36,50 +36,79 @@ import ghidra.util.task.TaskMonitor;
|
||||
public class DWARFAnalyzer extends AbstractAnalyzer {
|
||||
private static final String DWARF_LOADED_OPTION_NAME = "DWARF Loaded";
|
||||
|
||||
private static final String OPTION_IMPORT_DATATYPES = "Import data types";
|
||||
private static final String OPTION_IMPORT_DATATYPES = "Import Data Types";
|
||||
private static final String OPTION_IMPORT_DATATYPES_DESC =
|
||||
"Import data types defined in the DWARF debug info.";
|
||||
|
||||
private static final String OPTION_PRELOAD_ALL_DIES = "Preload all DIEs";
|
||||
private static final String OPTION_PRELOAD_ALL_DIES = "Preload All DIEs";
|
||||
private static final String OPTION_PRELOAD_ALL_DIES_DESC =
|
||||
"Preload all DIE records. Requires more memory, but necessary for some non-standard layouts.";
|
||||
"Preload all DIE records. Requires more memory, but necessary for some non-standard " +
|
||||
"layouts.";
|
||||
|
||||
private static final String OPTION_IMPORT_FUNCS = "Import functions";
|
||||
private static final String OPTION_IMPORT_FUNCS = "Import Functions";
|
||||
private static final String OPTION_IMPORT_FUNCS_DESC =
|
||||
"Import function information defined in the DWARF debug info. (implies import data types)";
|
||||
"Import function information defined in the DWARF debug info\n" +
|
||||
"(implies 'Import Data Types' is selected).";
|
||||
|
||||
private static final String OPTION_IMPORT_LIMIT_DIE_COUNT = "Debug item count limit";
|
||||
private static final String OPTION_IMPORT_LIMIT_DIE_COUNT = "Debug Item Limit";
|
||||
private static final String OPTION_IMPORT_LIMIT_DIE_COUNT_DESC =
|
||||
"If the number of DWARF debug items are greater than this setting, DWARF analysis will be skipped.";
|
||||
"If the number of DWARF debug items are greater than this setting, DWARF analysis will " +
|
||||
"be skipped.";
|
||||
|
||||
private static final String OPTION_OUTPUT_SOURCE_INFO = "Output Source info";
|
||||
private static final String OPTION_OUTPUT_SOURCE_INFO = "Output Source Info";
|
||||
private static final String OPTION_OUTPUT_SOURCE_INFO_DESC =
|
||||
"Include source code location info (filename:linenumber) in comments attached to the Ghidra datatype or function or variable created.";
|
||||
"Include source code location info (filename:linenumber) in comments attached to the " +
|
||||
"Ghidra datatype or function or variable created.";
|
||||
|
||||
private static final String OPTION_OUTPUT_DWARF_DIE_INFO = "Output DWARF DIE info";
|
||||
private static final String OPTION_OUTPUT_DWARF_DIE_INFO = "Output DWARF DIE Info";
|
||||
private static final String OPTION_OUTPUT_DWARF_DIE_INFO_DESC =
|
||||
"Include DWARF DIE offset info in comments attached to the Ghidra datatype or function or variable created.";
|
||||
"Include DWARF DIE offset info in comments attached to the Ghidra datatype or function " +
|
||||
"or variable created.";
|
||||
|
||||
private static final String OPTION_NAME_LENGTH_CUTOFF = "Name length cutoff";
|
||||
private static final String OPTION_NAME_LENGTH_CUTOFF = "Maximum Name Length";
|
||||
private static final String OPTION_NAME_LENGTH_CUTOFF_DESC =
|
||||
"Truncate symbol and type names longer than this limit. Range 20..2000";
|
||||
|
||||
private static final String OPTION_OUTPUT_LEXICAL_BLOCK_COMMENTS = "Lexical block comments";
|
||||
private static final String OPTION_OUTPUT_LEXICAL_BLOCK_COMMENTS = "Add Lexical Block Comments";
|
||||
private static final String OPTION_OUTPUT_LEXICAL_BLOCK_COMMENTS_DESC =
|
||||
"Add comments to the start of lexical blocks";
|
||||
|
||||
private static final String OPTION_OUTPUT_INLINE_FUNC_COMMENTS = "Inlined functions comments";
|
||||
private static final String OPTION_OUTPUT_INLINE_FUNC_COMMENTS =
|
||||
"Add Inlined Functions Comments";
|
||||
private static final String OPTION_OUTPUT_INLINE_FUNC_COMMENTS_DESC =
|
||||
"Add comments to the start of inlined functions";
|
||||
|
||||
private static final String OPTION_OUTPUT_FUNC_SIGS = "Output function signatures";
|
||||
private static final String OPTION_OUTPUT_FUNC_SIGS = "Create Function Signatures";
|
||||
private static final String OPTION_OUTPUT_FUNC_SIGS_DESC =
|
||||
"Create function signature data types for each function encountered in the DWARF debug data.";
|
||||
"Create function signature data types for each function encountered in the DWARF debug " +
|
||||
"data.";
|
||||
|
||||
private static final String DWARF_ANALYZER_NAME = "DWARF";
|
||||
private static final String DWARF_ANALYZER_DESCRIPTION =
|
||||
"Automatically extracts DWARF info from an ELF file.";
|
||||
|
||||
//==================================================================================================
|
||||
// Old Option Names - Should stick around for multiple major versions after 10.2
|
||||
//==================================================================================================
|
||||
|
||||
private static final String OPTION_IMPORT_DATATYPES_OLD = "Import data types";
|
||||
private static final String OPTION_PRELOAD_ALL_DIES_OLD = "Preload all DIEs";
|
||||
private static final String OPTION_IMPORT_FUNCS_OLD = "Import functions";
|
||||
private static final String OPTION_IMPORT_LIMIT_DIE_COUNT_OLD = "Debug item count limit";
|
||||
private static final String OPTION_OUTPUT_SOURCE_INFO_OLD = "Output Source info";
|
||||
private static final String OPTION_OUTPUT_DWARF_DIE_INFO_OLD = "Output DWARF DIE info";
|
||||
private static final String OPTION_NAME_LENGTH_CUTOFF_OLD = "Name length cutoff";
|
||||
private static final String OPTION_OUTPUT_LEXICAL_BLOCK_COMMENTS_OLD = "Lexical block comments";
|
||||
private static final String OPTION_OUTPUT_INLINE_FUNC_COMMENTS_OLD =
|
||||
"Inlined functions comments";
|
||||
private static final String OPTION_OUTPUT_FUNC_SIGS_OLD = "Output function signatures";
|
||||
|
||||
private AnalysisOptionsUpdater optionsUpdater = new AnalysisOptionsUpdater();
|
||||
|
||||
//==================================================================================================
|
||||
// End Old Option Names
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Returns true if DWARF has already been imported into the specified program.
|
||||
*
|
||||
@@ -87,8 +116,8 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
||||
* @return true if DWARF has already been imported, false if not yet
|
||||
*/
|
||||
public static boolean isAlreadyImported(Program program) {
|
||||
Options propList = program.getOptions(Program.PROGRAM_INFO);
|
||||
return propList.getBoolean(DWARF_LOADED_OPTION_NAME, false) ||
|
||||
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||
return options.getBoolean(DWARF_LOADED_OPTION_NAME, false) ||
|
||||
oldCheckIfDWARFImported(program);
|
||||
}
|
||||
|
||||
@@ -100,6 +129,26 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
||||
setDefaultEnablement(true);
|
||||
setPriority(AnalysisPriority.FORMAT_ANALYSIS.after());
|
||||
setSupportsOneTimeAnalysis();
|
||||
|
||||
optionsUpdater.registerReplacement(OPTION_IMPORT_DATATYPES,
|
||||
OPTION_IMPORT_DATATYPES_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_PRELOAD_ALL_DIES,
|
||||
OPTION_PRELOAD_ALL_DIES_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_IMPORT_FUNCS,
|
||||
OPTION_IMPORT_FUNCS_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_IMPORT_LIMIT_DIE_COUNT,
|
||||
OPTION_IMPORT_LIMIT_DIE_COUNT_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_OUTPUT_SOURCE_INFO,
|
||||
OPTION_OUTPUT_SOURCE_INFO_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_OUTPUT_DWARF_DIE_INFO,
|
||||
OPTION_OUTPUT_DWARF_DIE_INFO_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_NAME_LENGTH_CUTOFF,
|
||||
OPTION_NAME_LENGTH_CUTOFF_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_OUTPUT_LEXICAL_BLOCK_COMMENTS,
|
||||
OPTION_OUTPUT_LEXICAL_BLOCK_COMMENTS_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_OUTPUT_INLINE_FUNC_COMMENTS,
|
||||
OPTION_OUTPUT_INLINE_FUNC_COMMENTS_OLD);
|
||||
optionsUpdater.registerReplacement(OPTION_OUTPUT_FUNC_SIGS, OPTION_OUTPUT_FUNC_SIGS_OLD);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,6 +234,7 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
@Override
|
||||
public void registerOptions(Options options, Program program) {
|
||||
|
||||
options.registerOption(OPTION_IMPORT_DATATYPES, importOptions.isImportDataTypes(), null,
|
||||
OPTION_IMPORT_DATATYPES_DESC);
|
||||
|
||||
@@ -218,6 +268,11 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
||||
null, OPTION_OUTPUT_FUNC_SIGS_DESC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalysisOptionsUpdater getOptionsUpdater() {
|
||||
return optionsUpdater;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void optionsChanged(Options options, Program program) {
|
||||
importOptions.setOutputDIEInfo(
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package ghidra.app.services;
|
||||
|
||||
import ghidra.app.plugin.core.analysis.AnalysisOptionsUpdater;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
@@ -24,12 +25,13 @@ import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* NOTE: ALL ANALYZER CLASSES MUST END IN "Analyzer". If not,
|
||||
* the ClassSearcher will not find them.
|
||||
*
|
||||
* Interface to perform automatic analysis.
|
||||
*
|
||||
* NOTE: ALL ANALYZER CLASSES MUST END IN "Analyzer". If not, the ClassSearcher will not find
|
||||
* them.
|
||||
*/
|
||||
public interface Analyzer extends ExtensionPoint {
|
||||
|
||||
/**
|
||||
* Get the name of this analyzer
|
||||
* @return analyzer name
|
||||
@@ -43,15 +45,18 @@ public interface Analyzer extends ExtensionPoint {
|
||||
public AnalyzerType getAnalysisType();
|
||||
|
||||
/**
|
||||
* Returns true if this analyzer should be enabled by default. Generally useful
|
||||
* analyzers should return true. Specialized analyzers should return false;
|
||||
* Returns true if this analyzer should be enabled by default. Generally useful analyzers
|
||||
* should return true. Specialized analyzers should return false;
|
||||
* @param program the program
|
||||
* @return true if enabled by default
|
||||
*/
|
||||
public boolean getDefaultEnablement(Program program);
|
||||
|
||||
/**
|
||||
* Returns true if it makes sense for this analyzer to directly invoked on an address or
|
||||
* addressSet. The AutoAnalyzer plug-in will automatically create an action for each
|
||||
* analyzer that returns true.
|
||||
* addressSet. The AutoAnalyzer plug-in will automatically create an action for each analyzer
|
||||
* that returns true.
|
||||
* @return true if supports one-time analysis
|
||||
*/
|
||||
public boolean supportsOneTimeAnalysis();
|
||||
|
||||
@@ -75,29 +80,31 @@ public interface Analyzer extends ExtensionPoint {
|
||||
public boolean canAnalyze(Program program);
|
||||
|
||||
/**
|
||||
* Called when the requested information type has been added.
|
||||
* (ie: function added.)
|
||||
* Called when the requested information type has been added, for example, when a function is
|
||||
* added.
|
||||
*
|
||||
* @param program program to analyze
|
||||
* @param set AddressSet of locations that have been added
|
||||
* @param monitor monitor that indicates progress and indicates whether
|
||||
* the user canceled the analysis
|
||||
* @param monitor monitor that indicates progress and indicates whether the user canceled the
|
||||
* analysis
|
||||
* @param log a message log to record analysis information
|
||||
* @return true if the analysis succeeded
|
||||
* @throws CancelledException if the analysis is cancelled
|
||||
*/
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException;
|
||||
|
||||
/**
|
||||
* Called when the requested information type has been removed.
|
||||
* (ie: function removed.)
|
||||
* Called when the requested information type has been removed, for example, when a function is
|
||||
* removed.
|
||||
*
|
||||
* @param program program to analyze
|
||||
* @param set AddressSet of locations that have been added
|
||||
* @param monitor monitor that indicates progress and indicates whether
|
||||
* the user canceled the analysis
|
||||
* @param monitor monitor that indicates progress and indicates whether the user canceled the
|
||||
* analysis
|
||||
* @param log a message log to record analysis information
|
||||
* @return true if the analysis succeeded
|
||||
* @throws CancelledException if the analysis is cancelled
|
||||
*/
|
||||
public boolean removed(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException;
|
||||
@@ -111,8 +118,18 @@ public interface Analyzer extends ExtensionPoint {
|
||||
public void registerOptions(Options options, Program program);
|
||||
|
||||
/**
|
||||
* Analyzers should initialize their options from the values in the given Options,
|
||||
* providing appropriate default values.
|
||||
* Returns an optional options updater that allows clients to migrate old options to new
|
||||
* options. This can be used to facilitate option name changes, as well as option value type
|
||||
* changes.
|
||||
* @return the updater; null if no updater
|
||||
*/
|
||||
public default AnalysisOptionsUpdater getOptionsUpdater() {
|
||||
return null; // stub; clients will override as needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzers should initialize their options from the values in the given Options, providing
|
||||
* appropriate default values.
|
||||
* @param options the program options/property list that contains the options
|
||||
* @param program program to be analyzed
|
||||
*/
|
||||
|
||||
+520
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -72,7 +72,6 @@ public class AnalysisOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
env.release(program);
|
||||
env.dispose();
|
||||
cleanUpStoredPreferences();
|
||||
}
|
||||
@@ -258,6 +257,7 @@ public class AnalysisOptionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
|
||||
private void createConfig(String name, boolean stackOn, boolean refOn, boolean stringOn) {
|
||||
setAnalyzerEnabled("Stack", stackOn);
|
||||
setAnalyzerEnabled("Reference", refOn);
|
||||
|
||||
+35
-5
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package ghidra.feature.fid.analyzer;
|
||||
|
||||
import ghidra.app.plugin.core.analysis.AnalysisOptionsUpdater;
|
||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
@@ -42,7 +43,8 @@ public class FidAnalyzer extends AbstractAnalyzer {
|
||||
private static final String OPTION_DESCRIPTION_CREATE_BOOKMARKS =
|
||||
"If checked, an analysis bookmark will be created for each function which was matched " +
|
||||
"against one or more known library functions.";
|
||||
public static final String APPLY_ALL_FID_LABELS_OPTION_NAME = "Always apply FID labels";
|
||||
|
||||
public static final String APPLY_ALL_FID_LABELS_OPTION_NAME = "Always Apply FID Labels";
|
||||
private static final String APPLY_ALL_FID_LABELS_OPTION_DESCRIPTION = "Enable this option to " +
|
||||
"always apply FID labels at functions regardless of existing labels at that function." +
|
||||
" When enabled, FID labels will always be added." +
|
||||
@@ -57,18 +59,33 @@ public class FidAnalyzer extends AbstractAnalyzer {
|
||||
private boolean alwaysApplyFidLabels = APPLY_ALL_FID_LABELS_DEFAULT;
|
||||
private boolean createBookmarksEnabled = OPTION_DEFAULT_CREATE_BOOKMARKS_ENABLED;
|
||||
|
||||
public static final String SCORE_THRESHOLD_OPTION_NAME = "Instruction count threshold";
|
||||
private static final String SCORE_THRESHOLD_OPTION_NAME = "Instruction Count Threshold";
|
||||
|
||||
private static final String SCORE_THRESHOLD_OPTION_DESCRIPTION =
|
||||
"The minimum score that a potential match must meet to be labeled by the analyzer. " +
|
||||
"Score corresponds roughly to the number of instructions in the function.";
|
||||
private float scoreThreshold;
|
||||
|
||||
public static final String MULTIMATCH_THRESHOLD_OPTION_NAME = "Multiple match threshold";
|
||||
private static final String MULTIMATCH_THRESHOLD_OPTION_NAME = "Multiple Match Threshold";
|
||||
private static final String MULTIMATCH_THRESHOLD_OPTION_DESCRIPTION =
|
||||
"If there are multiple conflicting matches for a function, its score must exceed " +
|
||||
"this secondary threshold in order to be labeled by the analyzer";
|
||||
private float multiScoreThreshold;
|
||||
|
||||
//==================================================================================================
|
||||
// Old Option Names - Should stick around for multiple major versions after 10.2
|
||||
//==================================================================================================
|
||||
|
||||
private static final String SCORE_THRESHOLD_OPTION_NAME_OLD = "Instruction count threshold";
|
||||
private static final String MULTIMATCH_THRESHOLD_OPTION_NAME_OLD = "Multiple match threshold";
|
||||
private static final String APPLY_ALL_FID_LABELS_OPTION_NAME_OLD = "Always apply FID labels";
|
||||
|
||||
private AnalysisOptionsUpdater optionsUpdater = new AnalysisOptionsUpdater();
|
||||
|
||||
//==================================================================================================
|
||||
// End Old Option Names
|
||||
//==================================================================================================
|
||||
|
||||
public FidAnalyzer() {
|
||||
/*
|
||||
* FID is listed as a byte analyzer because we don't want to run it all the time. It
|
||||
@@ -86,6 +103,13 @@ public class FidAnalyzer extends AbstractAnalyzer {
|
||||
setPriority(AnalysisPriority.FUNCTION_ID_ANALYSIS.before());
|
||||
scoreThreshold = service.getDefaultScoreThreshold();
|
||||
multiScoreThreshold = service.getDefaultMultiNameThreshold();
|
||||
|
||||
optionsUpdater.registerReplacement(SCORE_THRESHOLD_OPTION_NAME,
|
||||
SCORE_THRESHOLD_OPTION_NAME_OLD);
|
||||
optionsUpdater.registerReplacement(MULTIMATCH_THRESHOLD_OPTION_NAME,
|
||||
MULTIMATCH_THRESHOLD_OPTION_NAME_OLD);
|
||||
optionsUpdater.registerReplacement(APPLY_ALL_FID_LABELS_OPTION_NAME,
|
||||
APPLY_ALL_FID_LABELS_OPTION_NAME_OLD);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,8 +136,9 @@ public class FidAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
// Name Change can change the nature of a function from a system
|
||||
// library. Probably a better way to do this.
|
||||
AutoAnalysisManager.getAnalysisManager(program).functionModifierChanged(
|
||||
cmd.getFIDLocations());
|
||||
AutoAnalysisManager.getAnalysisManager(program)
|
||||
.functionModifierChanged(
|
||||
cmd.getFIDLocations());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,6 +154,11 @@ public class FidAnalyzer extends AbstractAnalyzer {
|
||||
OPTION_DESCRIPTION_CREATE_BOOKMARKS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnalysisOptionsUpdater getOptionsUpdater() {
|
||||
return optionsUpdater;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void optionsChanged(Options options, Program program) {
|
||||
scoreThreshold =
|
||||
|
||||
+4
@@ -81,4 +81,8 @@ public class DefaultOptionComponent extends GenericOptionsComponent {
|
||||
int maxHeight = Math.max(dimension.height, component.getPreferredSize().height);
|
||||
return new Dimension(dimension.width, maxHeight);
|
||||
}
|
||||
|
||||
public String getLabelText() {
|
||||
return label.getText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public interface Options {
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public abstract String getName();
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Returns a unique id for option in this options with the given name. This will be the full
|
||||
@@ -89,13 +89,13 @@ public interface Options {
|
||||
* Set the location for where help can be found for this entire options object.
|
||||
* @param helpLocation location for help on the option
|
||||
*/
|
||||
public abstract void setOptionsHelpLocation(HelpLocation helpLocation);
|
||||
public void setOptionsHelpLocation(HelpLocation helpLocation);
|
||||
|
||||
/**
|
||||
* Returns the HelpLocation for this entire Options object.
|
||||
* @return the HelpLocation for this entire Options object.
|
||||
*/
|
||||
public abstract HelpLocation getOptionsHelpLocation();
|
||||
public HelpLocation getOptionsHelpLocation();
|
||||
|
||||
/**
|
||||
* Get the location for where help can be found for the option with
|
||||
@@ -103,7 +103,7 @@ public interface Options {
|
||||
* @param optionName name of the option
|
||||
* @return null if the help location was not set on the option
|
||||
*/
|
||||
public abstract HelpLocation getHelpLocation(String optionName);
|
||||
public HelpLocation getHelpLocation(String optionName);
|
||||
|
||||
/**
|
||||
* Registers an option with a description, help location, and a default value without specifying
|
||||
@@ -117,7 +117,7 @@ public interface Options {
|
||||
* @param description a description of the option.
|
||||
* @throws IllegalArgumentException if the defaultValue is null
|
||||
*/
|
||||
public abstract void registerOption(String optionName, Object defaultValue, HelpLocation help,
|
||||
public void registerOption(String optionName, Object defaultValue, HelpLocation help,
|
||||
String description);
|
||||
|
||||
/**
|
||||
@@ -130,7 +130,7 @@ public interface Options {
|
||||
* @param help the HelpLocation for this option.
|
||||
* @param description a description of the option.
|
||||
*/
|
||||
public abstract void registerOption(String optionName, OptionType type, Object defaultValue,
|
||||
public void registerOption(String optionName, OptionType type, Object defaultValue,
|
||||
HelpLocation help, String description);
|
||||
|
||||
/**
|
||||
@@ -146,20 +146,20 @@ public interface Options {
|
||||
* then the property editor can't be null;
|
||||
* @throws IllegalStateException if the options is a custom option and the editor is null.
|
||||
*/
|
||||
public abstract void registerOption(String optionName, OptionType type, Object defaultValue,
|
||||
public void registerOption(String optionName, OptionType type, Object defaultValue,
|
||||
HelpLocation help, String description, PropertyEditor editor);
|
||||
|
||||
/**
|
||||
* Register the options editor that will handle the editing for all the options or a sub group of options.
|
||||
* @param editor the custom editor panel to be used to edit the options or sub group of options.
|
||||
*/
|
||||
public abstract void registerOptionsEditor(OptionsEditor editor);
|
||||
public void registerOptionsEditor(OptionsEditor editor);
|
||||
|
||||
/**
|
||||
* Get the editor that will handle editing all the values in this options or sub group of options.
|
||||
* @return null if no options editor was registered
|
||||
*/
|
||||
public abstract OptionsEditor getOptionsEditor();
|
||||
public OptionsEditor getOptionsEditor();
|
||||
|
||||
/**
|
||||
* Put the object value. If the option exists, the type must match the type of the existing
|
||||
@@ -169,7 +169,7 @@ public interface Options {
|
||||
* @throws IllegalStateException if the object does not match the existing type of the option.
|
||||
* @throws IllegalArgumentException if the object is null or not a supported type.
|
||||
*/
|
||||
public abstract void putObject(String optionName, Object obj);
|
||||
public void putObject(String optionName, Object obj);
|
||||
|
||||
/**
|
||||
* Get the object value; called when the options dialog is being
|
||||
@@ -179,7 +179,7 @@ public interface Options {
|
||||
* @return object with the given option name; if no option was found,
|
||||
* return default value (this value is not stored in the option maps)
|
||||
*/
|
||||
public abstract Object getObject(String optionName, Object defaultValue);
|
||||
public Object getObject(String optionName, Object defaultValue);
|
||||
|
||||
/**
|
||||
* Get the boolean value for the given option name.
|
||||
@@ -188,7 +188,7 @@ public interface Options {
|
||||
* is no option with the given name.
|
||||
* @return boolean option value
|
||||
*/
|
||||
public abstract boolean getBoolean(String optionName, boolean defaultValue);
|
||||
public boolean getBoolean(String optionName, boolean defaultValue);
|
||||
|
||||
/**
|
||||
* Get the byte array for the given option name.
|
||||
@@ -197,7 +197,7 @@ public interface Options {
|
||||
* is no option with the given name
|
||||
* @return byte[] byte array value
|
||||
*/
|
||||
public abstract byte[] getByteArray(String optionName, byte[] defaultValue);
|
||||
public byte[] getByteArray(String optionName, byte[] defaultValue);
|
||||
|
||||
/**
|
||||
* Get the int value for the given option name.
|
||||
@@ -206,7 +206,7 @@ public interface Options {
|
||||
* is no option with the given name
|
||||
* @return int option value
|
||||
*/
|
||||
public abstract int getInt(String optionName, int defaultValue);
|
||||
public int getInt(String optionName, int defaultValue);
|
||||
|
||||
/**
|
||||
* Get the double value for the given option name.
|
||||
@@ -215,7 +215,7 @@ public interface Options {
|
||||
* is no option with the given name
|
||||
* @return double value for the option
|
||||
*/
|
||||
public abstract double getDouble(String optionName, double defaultValue);
|
||||
public double getDouble(String optionName, double defaultValue);
|
||||
|
||||
/**
|
||||
* Get the float value for the given option name.
|
||||
@@ -224,7 +224,7 @@ public interface Options {
|
||||
* is no option with the given name
|
||||
* @return float value for the option
|
||||
*/
|
||||
public abstract float getFloat(String optionName, float defaultValue);
|
||||
public float getFloat(String optionName, float defaultValue);
|
||||
|
||||
/**
|
||||
* Get the long value for the given option name.
|
||||
@@ -233,7 +233,7 @@ public interface Options {
|
||||
* is no option with the given name
|
||||
* @return long value for the option
|
||||
*/
|
||||
public abstract long getLong(String optionName, long defaultValue);
|
||||
public long getLong(String optionName, long defaultValue);
|
||||
|
||||
/**
|
||||
* Get the custom option value for the given option name.
|
||||
@@ -242,7 +242,7 @@ public interface Options {
|
||||
* is no option with the given name
|
||||
* @return WrappedOption value for the option
|
||||
*/
|
||||
public abstract CustomOption getCustomOption(String optionName, CustomOption defaultValue);
|
||||
public CustomOption getCustomOption(String optionName, CustomOption defaultValue);
|
||||
|
||||
/**
|
||||
* Get the Color for the given option name.
|
||||
@@ -253,7 +253,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException is a option exists with the given
|
||||
* name but it is not a Color
|
||||
*/
|
||||
public abstract Color getColor(String optionName, Color defaultValue);
|
||||
public Color getColor(String optionName, Color defaultValue);
|
||||
|
||||
/**
|
||||
* Get the File for the given option name.
|
||||
@@ -264,7 +264,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException is a option exists with the given
|
||||
* name but it is not a File options
|
||||
*/
|
||||
public abstract File getFile(String optionName, File defaultValue);
|
||||
public File getFile(String optionName, File defaultValue);
|
||||
|
||||
/**
|
||||
* Get the Date for the given option name.
|
||||
@@ -275,7 +275,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException is a option exists with the given
|
||||
* name but it is not a Date options
|
||||
*/
|
||||
public abstract Date getDate(String pName, Date date);
|
||||
public Date getDate(String pName, Date date);
|
||||
|
||||
/**
|
||||
* Get the Font for the given option name.
|
||||
@@ -286,7 +286,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException is a option exists with the given
|
||||
* name but it is not a Font
|
||||
*/
|
||||
public abstract Font getFont(String optionName, Font defaultValue);
|
||||
public Font getFont(String optionName, Font defaultValue);
|
||||
|
||||
/**
|
||||
* Get the KeyStrokg for the given action name.
|
||||
@@ -297,7 +297,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException is a option exists with the given
|
||||
* name but it is not a KeyStroke
|
||||
*/
|
||||
public abstract KeyStroke getKeyStroke(String optionName, KeyStroke defaultValue);
|
||||
public KeyStroke getKeyStroke(String optionName, KeyStroke defaultValue);
|
||||
|
||||
/**
|
||||
* Get the string value for the given option name.
|
||||
@@ -306,7 +306,7 @@ public interface Options {
|
||||
* option with the given name
|
||||
* @return String value for the option
|
||||
*/
|
||||
public abstract String getString(String optionName, String defaultValue);
|
||||
public String getString(String optionName, String defaultValue);
|
||||
|
||||
/**
|
||||
* Get the Enum value for the given option name.
|
||||
@@ -315,70 +315,70 @@ public interface Options {
|
||||
* no option with the given name
|
||||
* @return Enum value for the option
|
||||
*/
|
||||
public abstract <T extends Enum<T>> T getEnum(String optionName, T defaultValue);
|
||||
public <T extends Enum<T>> T getEnum(String optionName, T defaultValue);
|
||||
|
||||
/**
|
||||
* Sets the long value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value value of the option
|
||||
*/
|
||||
public abstract void setLong(String optionName, long value);
|
||||
public void setLong(String optionName, long value);
|
||||
|
||||
/**
|
||||
* Sets the boolean value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value value of the option
|
||||
*/
|
||||
public abstract void setBoolean(String optionName, boolean value);
|
||||
public void setBoolean(String optionName, boolean value);
|
||||
|
||||
/**
|
||||
* Sets the int value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value value of the option
|
||||
*/
|
||||
public abstract void setInt(String optionName, int value);
|
||||
public void setInt(String optionName, int value);
|
||||
|
||||
/**
|
||||
* Sets the double value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value value of the option
|
||||
*/
|
||||
public abstract void setDouble(String optionName, double value);
|
||||
public void setDouble(String optionName, double value);
|
||||
|
||||
/**
|
||||
* Sets the float value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value value of the option
|
||||
*/
|
||||
public abstract void setFloat(String optionName, float value);
|
||||
public void setFloat(String optionName, float value);
|
||||
|
||||
/**
|
||||
* Sets the Custom option value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value the value
|
||||
*/
|
||||
public abstract void setCustomOption(String optionName, CustomOption value);
|
||||
public void setCustomOption(String optionName, CustomOption value);
|
||||
|
||||
/**
|
||||
* Sets the byte[] value for the given option name.
|
||||
* @param optionName the name of the option on which to save bytes.
|
||||
* @param value the value
|
||||
*/
|
||||
public abstract void setByteArray(String optionName, byte[] value);
|
||||
public void setByteArray(String optionName, byte[] value);
|
||||
|
||||
/**
|
||||
* Sets the File value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value the value
|
||||
*/
|
||||
public abstract void setFile(String optionName, File value);
|
||||
public void setFile(String optionName, File value);
|
||||
|
||||
/**
|
||||
* Sets the Date value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param newSetting the Date to set
|
||||
*/
|
||||
public abstract void setDate(String optionName, Date newSetting);
|
||||
public void setDate(String optionName, Date newSetting);
|
||||
|
||||
/**
|
||||
* Sets the Color value for the option
|
||||
@@ -387,7 +387,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException if a option with the given
|
||||
* name already exists, but it is not a Color
|
||||
*/
|
||||
public abstract void setColor(String optionName, Color value);
|
||||
public void setColor(String optionName, Color value);
|
||||
|
||||
/**
|
||||
* Sets the Font value for the option
|
||||
@@ -396,7 +396,7 @@ public interface Options {
|
||||
* @throws IllegalArgumentException if a option with the given
|
||||
* name already exists, but it is not a Font
|
||||
*/
|
||||
public abstract void setFont(String optionName, Font value);
|
||||
public void setFont(String optionName, Font value);
|
||||
|
||||
/**
|
||||
* Sets the KeyStroke value for the option
|
||||
@@ -405,27 +405,27 @@ public interface Options {
|
||||
* @throws IllegalArgumentException if a option with the given
|
||||
* name already exists, but it is not a KeyStroke
|
||||
*/
|
||||
public abstract void setKeyStroke(String optionName, KeyStroke value);
|
||||
public void setKeyStroke(String optionName, KeyStroke value);
|
||||
|
||||
/**
|
||||
* Set the String value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value value of the option
|
||||
*/
|
||||
public abstract void setString(String optionName, String value);
|
||||
public void setString(String optionName, String value);
|
||||
|
||||
/**
|
||||
* Set the Enum value for the option.
|
||||
* @param optionName name of the option
|
||||
* @param value Enum value of the option
|
||||
*/
|
||||
public abstract <T extends Enum<T>> void setEnum(String optionName, T value);
|
||||
public <T extends Enum<T>> void setEnum(String optionName, T value);
|
||||
|
||||
/**
|
||||
* Remove the option name.
|
||||
* @param optionName name of option to remove
|
||||
*/
|
||||
public abstract void removeOption(String optionName);
|
||||
public void removeOption(String optionName);
|
||||
|
||||
/**
|
||||
* Get the list of option names. This method will return the names (paths) of all options contained
|
||||
@@ -434,21 +434,21 @@ public interface Options {
|
||||
* the "aaa" and "bbb" names.
|
||||
* @return the list of all option names(paths) under this options.
|
||||
*/
|
||||
public abstract List<String> getOptionNames();
|
||||
public List<String> getOptionNames();
|
||||
|
||||
/**
|
||||
* Return true if a option exists with the given name.
|
||||
* @param optionName option name
|
||||
* @return true if there exists an option with the given name
|
||||
*/
|
||||
public abstract boolean contains(String optionName);
|
||||
public boolean contains(String optionName);
|
||||
|
||||
/**
|
||||
* Get the description for the given option name.
|
||||
* @param optionName name of the option
|
||||
* @return null if the description or option name does not exist
|
||||
*/
|
||||
public abstract String getDescription(String optionName);
|
||||
public String getDescription(String optionName);
|
||||
|
||||
/**
|
||||
* Returns true if the specified option has been registered. Only registered names
|
||||
@@ -456,21 +456,21 @@ public interface Options {
|
||||
* @param optionName the option name
|
||||
* @return true if registered
|
||||
*/
|
||||
public abstract boolean isRegistered(String optionName);
|
||||
public boolean isRegistered(String optionName);
|
||||
|
||||
/**
|
||||
* Returns true if the option with the given name's current value is the default value.
|
||||
* @param optionName the name of the option.
|
||||
* @return true if the options has its current value equal to its default value.
|
||||
*/
|
||||
public abstract boolean isDefaultValue(String optionName);
|
||||
public boolean isDefaultValue(String optionName);
|
||||
|
||||
/**
|
||||
* Restores <b>all</b> options contained herein to their default values.
|
||||
*
|
||||
* @see #restoreDefaultValue(String)
|
||||
*/
|
||||
public abstract void restoreDefaultValues();
|
||||
public void restoreDefaultValues();
|
||||
|
||||
/**
|
||||
* Restores the option denoted by the given name to its default value.
|
||||
@@ -478,7 +478,7 @@ public interface Options {
|
||||
* @param optionName The name of the option to restore
|
||||
* @see #restoreDefaultValues()
|
||||
*/
|
||||
public abstract void restoreDefaultValue(String optionName);
|
||||
public void restoreDefaultValue(String optionName);
|
||||
|
||||
/**
|
||||
* Returns a Options object that is a sub-options of this options.
|
||||
@@ -520,14 +520,14 @@ public interface Options {
|
||||
* @param name the name of the option for which to retrieve the value as a string
|
||||
* @return the value as a string for the given option.
|
||||
*/
|
||||
public abstract String getValueAsString(String name);
|
||||
public String getValueAsString(String name);
|
||||
|
||||
/**
|
||||
* Returns the default value as a string for the given option.
|
||||
* @param optionName the name of the option for which to retrieve the default value as a string
|
||||
* @return the default value as a string for the given option.
|
||||
*/
|
||||
public abstract String getDefaultValueAsString(String optionName);
|
||||
public String getDefaultValueAsString(String optionName);
|
||||
|
||||
/**
|
||||
* Returns true if the two options objects have the same set of options and values
|
||||
|
||||
+9
-4
@@ -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,6 +15,8 @@
|
||||
*/
|
||||
package ghidra.util.constraint;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import generic.constraint.ConstraintData;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.SystemUtilities;
|
||||
@@ -26,8 +27,8 @@ public class PropertyConstraint extends ProgramConstraint {
|
||||
super("property");
|
||||
}
|
||||
|
||||
private String name; // name of the program property to constrain
|
||||
private String value; // value the property should take
|
||||
private String name; // name of the program property to constrain
|
||||
private String value; // value the property should take
|
||||
|
||||
@Override
|
||||
public boolean isSatisfied(Program program) {
|
||||
@@ -41,6 +42,11 @@ public class PropertyConstraint extends ProgramConstraint {
|
||||
value = data.getString("value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof PropertyConstraint)) {
|
||||
@@ -54,5 +60,4 @@ public class PropertyConstraint extends ProgramConstraint {
|
||||
public String getDescription() {
|
||||
return "property " + name + " = " + value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user