mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-3282 Separated out the concepts of whether or not a program was analyzed from the state of if the user should be asked to analyze on open
This commit is contained in:
parent
008c299fa3
commit
bbadb4aed4
21 changed files with 215 additions and 152 deletions
|
@ -231,7 +231,7 @@ public class VariableValueHoverPluginScreenShots extends GhidraScreenShotGenerat
|
||||||
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
DebuggerEmulationService emuService = addPlugin(tool, DebuggerEmulationServicePlugin.class);
|
||||||
|
|
||||||
Function function = createFibonacciProgramX86_32();
|
Function function = createFibonacciProgramX86_32();
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
Address entry = function.getEntryPoint();
|
Address entry = function.getEntryPoint();
|
||||||
|
|
||||||
programManager.openProgram(program);
|
programManager.openProgram(program);
|
||||||
|
|
|
@ -129,6 +129,20 @@
|
||||||
applicable to the current program will be available within the One Shot sub-menu.</P>
|
applicable to the current program will be available within the One Shot sub-menu.</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3><A name="Ask_To_Analyze"></A>Ask To Analyze</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P> When opening a program for the first time, you will be asked if you want to analyze the
|
||||||
|
program. If you respond "Yes", The <A href= "#Auto_Analysis_Option">Auto Analysis Options</A>
|
||||||
|
dialog will appear, allowing you to begin analyzing the program. If you decide not to
|
||||||
|
analyze the program, you have the choice of having Ghidra asking you again the next time
|
||||||
|
you open the program. If you pick the "No" options, Ghidra will continue to ask you to
|
||||||
|
every time you open the program. If you pick "No (Don't ask again)" Ghidra will never ask you to
|
||||||
|
analyze the program again, but you can still manually initiate analysis at any time.
|
||||||
|
If you choose not to have Ghidra ask again, it will set a property in the program called
|
||||||
|
"Should Ask To Analyze" to false. Since this changes a property in the program, the program
|
||||||
|
now has changes that need to be saved. </P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H2><A name="Auto_Analysis_Option"></A> <A name=
|
<H2><A name="Auto_Analysis_Option"></A> <A name=
|
||||||
"ghidra_app_plugin_analysis_AutoAnalysisPlugin_AnalysisOptionsDialog"></A> <A name=
|
"ghidra_app_plugin_analysis_AutoAnalysisPlugin_AnalysisOptionsDialog"></A> <A name=
|
||||||
"AnalysisOptions"></A> Auto Analysis Options Panel</H2>
|
"AnalysisOptions"></A> Auto Analysis Options Panel</H2>
|
||||||
|
@ -199,9 +213,7 @@
|
||||||
<LI>Delete - Deletes the currently selected named configuration.</LI>
|
<LI>Delete - Deletes the currently selected named configuration.</LI>
|
||||||
</UL>
|
</UL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H2><A name="Auto_Analyzers"></A>Auto Analyzers</H2>
|
<H2><A name="Auto_Analyzers"></A>Auto Analyzers</H2>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
|
|
|
@ -72,7 +72,8 @@ public class PropertyListMergeManager implements MergeResolver {
|
||||||
* resultProgram and latestProgram start out the same
|
* resultProgram and latestProgram start out the same
|
||||||
*/
|
*/
|
||||||
public PropertyListMergeManager(ProgramMultiUserMergeManager mergeManager,
|
public PropertyListMergeManager(ProgramMultiUserMergeManager mergeManager,
|
||||||
Program resultProgram, Program myProgram, Program originalProgram, Program latestProgram) {
|
Program resultProgram, Program myProgram, Program originalProgram,
|
||||||
|
Program latestProgram) {
|
||||||
this.mergeManager = mergeManager;
|
this.mergeManager = mergeManager;
|
||||||
this.resultProgram = resultProgram;
|
this.resultProgram = resultProgram;
|
||||||
this.myProgram = myProgram;
|
this.myProgram = myProgram;
|
||||||
|
@ -142,7 +143,8 @@ public class PropertyListMergeManager implements MergeResolver {
|
||||||
currentMonitor.setProgress(i);
|
currentMonitor.setProgress(i);
|
||||||
String myName = myNames.get(i);
|
String myName = myNames.get(i);
|
||||||
int progress = (int) (((float) (i / myNamesCount)) * 100);
|
int progress = (int) (((float) (i / myNamesCount)) * 100);
|
||||||
mergeManager.updateProgress(progress, "Merging property list for " + myName + "...");
|
mergeManager.updateProgress(progress,
|
||||||
|
"Merging property list for " + myName + "...");
|
||||||
boolean isInLatest = latestNames.contains(myName);
|
boolean isInLatest = latestNames.contains(myName);
|
||||||
boolean isInOrig = origNames.contains(myName);
|
boolean isInOrig = origNames.contains(myName);
|
||||||
if (!isInLatest && !isInOrig) {
|
if (!isInLatest && !isInOrig) {
|
||||||
|
@ -277,11 +279,6 @@ public class PropertyListMergeManager implements MergeResolver {
|
||||||
// value was not modified in my program or it was changed the same as in latest
|
// value was not modified in my program or it was changed the same as in latest
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (propertyName.equals(Program.ANALYZED) && Boolean.TRUE.equals(myValue)) {
|
|
||||||
// If my version sets "Analyzed" to true, then it should result in true.
|
|
||||||
setValue(resultList, propertyName, myList.getType(propertyName), Boolean.TRUE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (SystemUtilities.isEqual(resultValue, origValue)) {
|
if (SystemUtilities.isEqual(resultValue, origValue)) {
|
||||||
// no change by latest - use my value
|
// no change by latest - use my value
|
||||||
setValue(resultList, propertyName, myList.getType(propertyName), myValue);
|
setValue(resultList, propertyName, myList.getType(propertyName), myValue);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class AnalysisBackgroundCommand extends MergeableBackgroundCommand {
|
||||||
@Override
|
@Override
|
||||||
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
if (markAsAnalyzed) {
|
if (markAsAnalyzed) {
|
||||||
GhidraProgramUtilities.setAnalyzedFlag((Program) obj, true);
|
GhidraProgramUtilities.markProgramAnalyzed((Program) obj);
|
||||||
}
|
}
|
||||||
mgr.startAnalysis(monitor);
|
mgr.startAnalysis(monitor);
|
||||||
return true;
|
return true;
|
||||||
|
@ -63,12 +63,12 @@ public class AnalysisBackgroundCommand extends MergeableBackgroundCommand {
|
||||||
@Override
|
@Override
|
||||||
public MergeableBackgroundCommand mergeCommands(MergeableBackgroundCommand command) {
|
public MergeableBackgroundCommand mergeCommands(MergeableBackgroundCommand command) {
|
||||||
SystemUtilities.assertTrue(command instanceof AnalysisBackgroundCommand,
|
SystemUtilities.assertTrue(command instanceof AnalysisBackgroundCommand,
|
||||||
"This code assumes that the "
|
"This code assumes that the " +
|
||||||
+ "two commands are both AnalysisBackgroundCommands and this is not the case.");
|
"two commands are both AnalysisBackgroundCommands and this is not the case.");
|
||||||
|
|
||||||
AnalysisBackgroundCommand abc = (AnalysisBackgroundCommand) command;
|
AnalysisBackgroundCommand abc = (AnalysisBackgroundCommand) command;
|
||||||
SystemUtilities.assertTrue(mgr == abc.mgr, "This code assumes that the "
|
SystemUtilities.assertTrue(mgr == abc.mgr, "This code assumes that the " +
|
||||||
+ "managers of the two commands are the same instance and this is not the case.");
|
"managers of the two commands are the same instance and this is not the case.");
|
||||||
|
|
||||||
// once we encounter a markAsAnalyzed value that is true, then leave it on
|
// once we encounter a markAsAnalyzed value that is true, then leave it on
|
||||||
markAsAnalyzed = markAsAnalyzed | abc.markAsAnalyzed;
|
markAsAnalyzed = markAsAnalyzed | abc.markAsAnalyzed;
|
||||||
|
|
|
@ -775,7 +775,7 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||||
|
|
||||||
private boolean isAnalyzed() {
|
private boolean isAnalyzed() {
|
||||||
Options options = programs.get(0).getOptions(Program.PROGRAM_INFO);
|
Options options = programs.get(0).getOptions(Program.PROGRAM_INFO);
|
||||||
return options.getBoolean(Program.ANALYZED, false);
|
return options.getBoolean(Program.ANALYZED_OPTION_NAME, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Options[] loadPossibleOptionsChoicesForComboBox() {
|
private Options[] loadPossibleOptionsChoicesForComboBox() {
|
||||||
|
|
|
@ -132,7 +132,7 @@ class AnalyzeAllOpenProgramsTask extends Task {
|
||||||
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(program);
|
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(program);
|
||||||
initializeAnalysisOptions(program, prototypeAnalysisOptions, manager);
|
initializeAnalysisOptions(program, prototypeAnalysisOptions, manager);
|
||||||
|
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
|
|
||||||
analyzeStrategy.analyzeProgram(program, manager, monitor);
|
analyzeStrategy.analyzeProgram(program, manager, monitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1048,8 +1048,8 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerOptions() {
|
public void registerOptions() {
|
||||||
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
registerGlobalAnalyisOptions();
|
||||||
registerOptions(options);
|
registerAnalyzerOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeOptions() {
|
public void initializeOptions() {
|
||||||
|
@ -1075,7 +1075,18 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
dataTasks.optionsChanged(options);
|
dataTasks.optionsChanged(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerOptions(Options options) {
|
private void registerGlobalAnalyisOptions() {
|
||||||
|
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
|
options.registerOption(Program.ANALYZED_OPTION_NAME, false, null,
|
||||||
|
"Indicates if program has ever been analyzed");
|
||||||
|
|
||||||
|
options.registerOption(Program.ASK_TO_ANALYZE_OPTION_NAME, true, null,
|
||||||
|
"Indicates if user should be prompted to analyze an unanalyzed program when opened");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerAnalyzerOptions() {
|
||||||
|
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
||||||
byteTasks.registerOptions(options);
|
byteTasks.registerOptions(options);
|
||||||
functionTasks.registerOptions(options);
|
functionTasks.registerOptions(options);
|
||||||
functionModifierChangedTasks.registerOptions(options);
|
functionModifierChangedTasks.registerOptions(options);
|
||||||
|
@ -1106,13 +1117,16 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
Swing.assertSwingThread("Asking to analyze must be on the swing thread!");
|
Swing.assertSwingThread("Asking to analyze must be on the swing thread!");
|
||||||
|
|
||||||
if (GhidraProgramUtilities.shouldAskToAnalyze(program)) {
|
if (GhidraProgramUtilities.shouldAskToAnalyze(program)) {
|
||||||
// initialize the analyzed flag to a non-null value to indicate we at least asked
|
String name = HTMLUtilities.escapeHTML(program.getDomainFile().getName());
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, false);
|
HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Ask_To_Analyze");
|
||||||
|
int result = OptionDialog.showOptionNoCancelDialog(tool.getToolFrame(), "Analyze?",
|
||||||
|
"<html>" + name + " has not been analyzed. Would you like to analyze it now?",
|
||||||
|
"Yes", "No", "No (Don't ask again)", OptionDialog.QUESTION_MESSAGE, help);
|
||||||
|
|
||||||
int answer = OptionDialog.showYesNoDialog(tool.getToolFrame(), "Analyze",
|
if (result == OptionDialog.OPTION_THREE) {
|
||||||
"<html>" + HTMLUtilities.escapeHTML(program.getDomainFile().getName()) +
|
GhidraProgramUtilities.markProgramNotToAskToAnalyze(program);
|
||||||
" has not been analyzed. Would you like to analyze it now?");
|
}
|
||||||
return answer == OptionDialog.OPTION_ONE; //Analyze
|
return result == OptionDialog.OPTION_ONE; //Analyze
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,7 +188,7 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
|
||||||
|
|
||||||
// check if this is the first time this program is being analyzed. If so,
|
// check if this is the first time this program is being analyzed. If so,
|
||||||
// schedule a callback when it is completed to send a FirstTimeAnalyzedPluginEvent
|
// schedule a callback when it is completed to send a FirstTimeAnalyzedPluginEvent
|
||||||
boolean isAnalyzed = GhidraProgramUtilities.isAnalyzedFlagSet(program);
|
boolean isAnalyzed = GhidraProgramUtilities.isAnalyzed(program);
|
||||||
if (!isAnalyzed) {
|
if (!isAnalyzed) {
|
||||||
analysisMgr.addListener(new FirstTimeAnalyzedCallback());
|
analysisMgr.addListener(new FirstTimeAnalyzedCallback());
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,7 +457,7 @@ public class GhidraScriptEditorComponentProvider extends ComponentProvider {
|
||||||
//
|
//
|
||||||
// Cancel
|
// Cancel
|
||||||
//
|
//
|
||||||
if (choice == OptionDialog.OPTION_THREE) {
|
if (choice == OptionDialog.CANCEL_OPTION) {
|
||||||
// Cancel
|
// Cancel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1019,7 +1019,7 @@ public class HeadlessAnalyzer {
|
||||||
mgr.startAnalysis(TaskMonitor.DUMMY); // kick start
|
mgr.startAnalysis(TaskMonitor.DUMMY); // kick start
|
||||||
|
|
||||||
Msg.info(this, "REPORT: Analysis succeeded for file: " + fileAbsolutePath);
|
Msg.info(this, "REPORT: Analysis succeeded for file: " + fileAbsolutePath);
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
HeadlessTimedTaskMonitor timerMonitor =
|
HeadlessTimedTaskMonitor timerMonitor =
|
||||||
|
@ -1042,7 +1042,7 @@ public class HeadlessAnalyzer {
|
||||||
timerMonitor.cancel();
|
timerMonitor.cancel();
|
||||||
|
|
||||||
Msg.info(this, "REPORT: Analysis succeeded for file: " + fileAbsolutePath);
|
Msg.info(this, "REPORT: Analysis succeeded for file: " + fileAbsolutePath);
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,6 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||||
MessageLog messageLog, Object consumer, TaskMonitor monitor) throws IOException,
|
MessageLog messageLog, Object consumer, TaskMonitor monitor) throws IOException,
|
||||||
CancelledException, VersionException, LoadException {
|
CancelledException, VersionException, LoadException {
|
||||||
|
|
||||||
|
|
||||||
if (!loadSpec.isComplete()) {
|
if (!loadSpec.isComplete()) {
|
||||||
throw new LoadException("Load spec is incomplete");
|
throw new LoadException("Load spec is incomplete");
|
||||||
}
|
}
|
||||||
|
@ -498,17 +497,19 @@ public abstract class AbstractProgramLoader implements Loader {
|
||||||
boolean anchorSymbols = shouldAnchorSymbols(options);
|
boolean anchorSymbols = shouldAnchorSymbols(options);
|
||||||
List<AddressLabelInfo> labels = lang.getDefaultSymbols();
|
List<AddressLabelInfo> labels = lang.getDefaultSymbols();
|
||||||
for (AddressLabelInfo info : labels) {
|
for (AddressLabelInfo info : labels) {
|
||||||
createSymbol(program, info.getLabel(), info.getAddress(), info.isEntry(), info.isPrimary(), anchorSymbols);
|
createSymbol(program, info.getLabel(), info.getAddress(), info.isEntry(),
|
||||||
|
info.isPrimary(), anchorSymbols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GhidraProgramUtilities.removeAnalyzedFlag(program);
|
GhidraProgramUtilities.resetAnalysisFlags(program);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(id, true);
|
program.endTransaction(id, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createSymbol(Program program, String labelname, Address address, boolean isEntry, boolean isPrimary, boolean anchorSymbols) {
|
private static void createSymbol(Program program, String labelname, Address address,
|
||||||
|
boolean isEntry, boolean isPrimary, boolean anchorSymbols) {
|
||||||
SymbolTable symTable = program.getSymbolTable();
|
SymbolTable symTable = program.getSymbolTable();
|
||||||
Address addr = address;
|
Address addr = address;
|
||||||
Symbol s = symTable.getPrimarySymbol(addr);
|
Symbol s = symTable.getPrimarySymbol(addr);
|
||||||
|
|
|
@ -389,7 +389,7 @@ public class ProgramXmlMgr {
|
||||||
|
|
||||||
//if instructions were imported, then remove the "needs analyzed" property
|
//if instructions were imported, then remove the "needs analyzed" property
|
||||||
if (options.isInstructions()) {
|
if (options.isInstructions()) {
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
return log;
|
return log;
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.plugins.fsbrowser.tasks;
|
package ghidra.plugins.fsbrowser.tasks;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.formats.gfilesystem.*;
|
import ghidra.formats.gfilesystem.*;
|
||||||
|
@ -140,7 +139,7 @@ public class GFileSystemLoadKernelTask extends Task {
|
||||||
file.getParentFile().getPath());
|
file.getParentFile().getPath());
|
||||||
String fileName = ProjectDataUtils.getUniqueName(folder, program.getName());
|
String fileName = ProjectDataUtils.getUniqueName(folder, program.getName());
|
||||||
|
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
|
|
||||||
folder.createFile(fileName, program, monitor);
|
folder.createFile(fileName, program, monitor);
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ public class ProgramBuilder {
|
||||||
CompilerSpec compilerSpec = compilerSpecID == null ? language.getDefaultCompilerSpec()
|
CompilerSpec compilerSpec = compilerSpecID == null ? language.getDefaultCompilerSpec()
|
||||||
: language.getCompilerSpecByID(new CompilerSpecID(compilerSpecID));
|
: language.getCompilerSpecByID(new CompilerSpecID(compilerSpecID));
|
||||||
program = new ProgramDB(name, language, compilerSpec, consumer == null ? this : consumer);
|
program = new ProgramDB(name, language, compilerSpec, consumer == null ? this : consumer);
|
||||||
setAnalyzed(true);
|
setAnalyzed();
|
||||||
program.setTemporary(true); // ignore changes
|
program.setTemporary(true); // ignore changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ public class ProgramBuilder {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
CompilerSpec compilerSpec = language.getDefaultCompilerSpec();
|
CompilerSpec compilerSpec = language.getDefaultCompilerSpec();
|
||||||
program = new ProgramDB(name, language, compilerSpec, this);
|
program = new ProgramDB(name, language, compilerSpec, this);
|
||||||
setAnalyzed(true);
|
setAnalyzed();
|
||||||
program.setTemporary(true); // ignore changes
|
program.setTemporary(true); // ignore changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,10 +281,9 @@ public class ProgramBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This prevents the 'ask to analyze' dialog from showing when called with {@code true}
|
* This prevents the 'ask to analyze' dialog from showing when called with {@code true}
|
||||||
* @param analyzed true to mark the program as analyzed
|
|
||||||
*/
|
*/
|
||||||
public void setAnalyzed(boolean analyzed) {
|
public void setAnalyzed() {
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, analyzed);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemoryBlock createMemory(String name, String address, int size) {
|
public MemoryBlock createMemory(String name, String address, int size) {
|
||||||
|
|
|
@ -25,8 +25,9 @@ public class GhidraProgramUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the current program, given a tool, if a program is opened;
|
* Returns the current program for the given tool or null if no program is open.
|
||||||
* otherwise returns null.
|
* @param tool the tool get get the current program for
|
||||||
|
* @return the current program for the given tool or null if no program is open
|
||||||
*/
|
*/
|
||||||
public static Program getCurrentProgram(PluginTool tool) {
|
public static Program getCurrentProgram(PluginTool tool) {
|
||||||
ProgramManager pmService = tool.getService(ProgramManager.class);
|
ProgramManager pmService = tool.getService(ProgramManager.class);
|
||||||
|
@ -34,11 +35,13 @@ public class GhidraProgramUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the program does not contain the analyzed flag. The assumption is that a
|
* Returns true if the user should be asked to analyze. They will only be asked if the program
|
||||||
* non-null value means that the user has already made a decision about analyzing.
|
* hasn't already been analyzed (analyzed flag property is false or null) or the
|
||||||
|
* "ask to analyze" flag property is true or null (default is true unless explicitly set to
|
||||||
|
* false).
|
||||||
*
|
*
|
||||||
* @param program the program to check for the property
|
* @param program the program to check for the property
|
||||||
* @return true if the program does not contain the analyzed flag
|
* @return true if the user should be prompted to analyze the program
|
||||||
*/
|
*/
|
||||||
public static boolean shouldAskToAnalyze(Program program) {
|
public static boolean shouldAskToAnalyze(Program program) {
|
||||||
|
|
||||||
|
@ -48,20 +51,27 @@ public class GhidraProgramUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
Options options = program.getOptions(Program.PROGRAM_INFO);
|
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
return !options.contains(Program.ANALYZED);
|
// older programs don't have a "Ask" property, so check analyzed flag
|
||||||
|
boolean isAnalyzed = options.getBoolean(Program.ANALYZED_OPTION_NAME, false);
|
||||||
|
if (isAnalyzed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return options.getBoolean(Program.ASK_TO_ANALYZE_OPTION_NAME, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the analyzed flag from the program properties.
|
* Resets the analysis flags to the program defaults
|
||||||
* With this property removed, the user will be prompted to analyze the
|
* With this reset, the user will be prompted to analyze the
|
||||||
* program the next time it is opened.
|
* program the next time it is opened.
|
||||||
* @param program the program containing the property to be removed
|
* @param program the program whose analysis flags should be reset
|
||||||
*/
|
*/
|
||||||
public static void removeAnalyzedFlag(Program program) {
|
public static void resetAnalysisFlags(Program program) {
|
||||||
int transactionID = program.startTransaction(Program.ANALYZED);
|
int transactionID = program.startTransaction("Reset Analysis Flags");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Options options = program.getOptions(Program.PROGRAM_INFO);
|
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
options.removeOption(Program.ANALYZED);
|
options.removeOption(Program.ANALYZED_OPTION_NAME);
|
||||||
|
options.removeOption(Program.ASK_TO_ANALYZE_OPTION_NAME);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(transactionID, true);
|
program.endTransaction(transactionID, true);
|
||||||
|
@ -69,21 +79,28 @@ public class GhidraProgramUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the analyzed flag to the specified value.
|
* Marks the program has having been analyzed
|
||||||
* @param program the program to set property
|
* @param program the program to set property
|
||||||
* @param analyzed the analyzed flag
|
|
||||||
*/
|
*/
|
||||||
public static void setAnalyzedFlag(Program program, boolean analyzed) {
|
public static void markProgramAnalyzed(Program program) {
|
||||||
Options options = program.getOptions(Program.PROGRAM_INFO);
|
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
|
|
||||||
// once the program is analyzed, register the value, so it won't keep writing it to the database.
|
int transactionID = program.startTransaction("Mark Program Analyzed");
|
||||||
if (analyzed && !options.isRegistered(Program.ANALYZED)) {
|
|
||||||
options.registerOption(Program.ANALYZED, false, null,
|
|
||||||
"Indicates if program has been analyzed");
|
|
||||||
}
|
|
||||||
int transactionID = program.startTransaction(Program.ANALYZED);
|
|
||||||
try {
|
try {
|
||||||
options.setBoolean(Program.ANALYZED, analyzed);
|
options.setBoolean(Program.ANALYZED_OPTION_NAME, true);
|
||||||
|
options.setBoolean(Program.ASK_TO_ANALYZE_OPTION_NAME, false);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markProgramNotToAskToAnalyze(Program program) {
|
||||||
|
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
|
|
||||||
|
int transactionID = program.startTransaction("Mark Program To Not Ask To Analyze");
|
||||||
|
try {
|
||||||
|
options.setBoolean(Program.ASK_TO_ANALYZE_OPTION_NAME, false);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(transactionID, true);
|
program.endTransaction(transactionID, true);
|
||||||
|
@ -95,17 +112,10 @@ public class GhidraProgramUtilities {
|
||||||
* @param program the program to test to see if it has been analyzed
|
* @param program the program to test to see if it has been analyzed
|
||||||
* @return true if the program has been analyzed at least once.
|
* @return true if the program has been analyzed at least once.
|
||||||
*/
|
*/
|
||||||
public static boolean isAnalyzedFlagSet(Program program) {
|
public static boolean isAnalyzed(Program program) {
|
||||||
Options options = program.getOptions(Program.PROGRAM_INFO);
|
Options options = program.getOptions(Program.PROGRAM_INFO);
|
||||||
|
|
||||||
// we first have to check if the flag has even been created because checking the flag
|
return options.getBoolean(Program.ANALYZED_OPTION_NAME, false);
|
||||||
// directly causes it to be created if it doesn't exist and we unfortunately use the
|
|
||||||
// existence of the flag to know whether or not to ask the user if they want to start
|
|
||||||
// analysis
|
|
||||||
if (!options.isRegistered(Program.ANALYZED)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return options.getBoolean(Program.ANALYZED, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1562,7 +1562,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
|
|
||||||
setAnalysisOptions(program.getOptions(Program.ANALYSIS_PROPERTIES));
|
setAnalysisOptions(program.getOptions(Program.ANALYSIS_PROPERTIES));
|
||||||
|
|
||||||
GhidraProgramUtilities.setAnalyzedFlag(program, true);
|
GhidraProgramUtilities.markProgramAnalyzed(program);
|
||||||
|
|
||||||
// Remove all single-byte functions created by Elf importer
|
// Remove all single-byte functions created by Elf importer
|
||||||
// NOTE: This is a known issues with optimized code and symbols marked as ElfSymbol.STT_FUNC
|
// NOTE: This is a known issues with optimized code and symbols marked as ElfSymbol.STT_FUNC
|
||||||
|
|
|
@ -18,6 +18,7 @@ package ghidra.app.util.pdb;
|
||||||
import ghidra.app.util.bin.format.pdb.PdbParserConstants;
|
import ghidra.app.util.bin.format.pdb.PdbParserConstants;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.util.GhidraProgramUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage of PDB-related attributes
|
* Storage of PDB-related attributes
|
||||||
|
@ -47,9 +48,7 @@ public class PdbProgramAttributes {
|
||||||
pdbLoaded = propList.contains(PdbParserConstants.PDB_LOADED)
|
pdbLoaded = propList.contains(PdbParserConstants.PDB_LOADED)
|
||||||
? propList.getBoolean(PdbParserConstants.PDB_LOADED, false)
|
? propList.getBoolean(PdbParserConstants.PDB_LOADED, false)
|
||||||
: false;
|
: false;
|
||||||
programAnalyzed = propList.contains(Program.ANALYZED)
|
programAnalyzed = GhidraProgramUtilities.isAnalyzed(program);
|
||||||
? propList.getBoolean(Program.ANALYZED, false)
|
|
||||||
: false;
|
|
||||||
pdbSignature = propList.contains(PdbParserConstants.PDB_SIGNATURE)
|
pdbSignature = propList.contains(PdbParserConstants.PDB_SIGNATURE)
|
||||||
? propList.getString(PdbParserConstants.PDB_SIGNATURE, null)
|
? propList.getString(PdbParserConstants.PDB_SIGNATURE, null)
|
||||||
: null;
|
: null;
|
||||||
|
@ -141,5 +140,4 @@ public class PdbProgramAttributes {
|
||||||
return programAnalyzed;
|
return programAnalyzed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package pdb;
|
package pdb;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
|
@ -39,6 +38,7 @@ import ghidra.framework.plugintool.*;
|
||||||
import ghidra.framework.plugintool.util.PluginStatus;
|
import ghidra.framework.plugintool.util.PluginStatus;
|
||||||
import ghidra.framework.preferences.Preferences;
|
import ghidra.framework.preferences.Preferences;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.util.GhidraProgramUtilities;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
@ -107,8 +107,7 @@ public class PdbPlugin extends Plugin {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean analyzed =
|
boolean analyzed = GhidraProgramUtilities.isAnalyzed(program);
|
||||||
program.getOptions(Program.PROGRAM_INFO).getBoolean(Program.ANALYZED, false);
|
|
||||||
|
|
||||||
if (analyzed) {
|
if (analyzed) {
|
||||||
int response =
|
int response =
|
||||||
|
|
|
@ -764,7 +764,7 @@ public class OptionDialog extends DialogComponentProvider {
|
||||||
return Swing.runNow(() -> {
|
return Swing.runNow(() -> {
|
||||||
OptionDialog info =
|
OptionDialog info =
|
||||||
new OptionDialog(title, message, option1, option2, PLAIN_MESSAGE, icon, false);
|
new OptionDialog(title, message, option1, option2, PLAIN_MESSAGE, icon, false);
|
||||||
return info.show();
|
return info.show(parent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,7 +794,39 @@ public class OptionDialog extends DialogComponentProvider {
|
||||||
return Swing.runNow(() -> {
|
return Swing.runNow(() -> {
|
||||||
OptionDialog info = new OptionDialog(title, message, option1, option2, option3,
|
OptionDialog info = new OptionDialog(title, message, option1, option2, option3,
|
||||||
messageType, null, false);
|
messageType, null, false);
|
||||||
return info.show();
|
return info.show(parent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static helper method to easily display an three-option dialog with no Cancel button.
|
||||||
|
* The dialog will remain until the user presses the
|
||||||
|
* Option1, Option 2, or Option 3 button.
|
||||||
|
*
|
||||||
|
* @param parent The parent component of this dialog. If the given component is
|
||||||
|
* a frame or dialog, then the component will be used to parent the option dialog.
|
||||||
|
* Otherwise, the parent frame or dialog will be found by traversing up the given
|
||||||
|
* component's parent hierarchy. Also, null can be used to not parent the dialog at all,
|
||||||
|
* but this promotes poor dialog behavior
|
||||||
|
* @param title The String to be placed in the dialogs title area
|
||||||
|
* @param message The information message to be displayed in the dialog
|
||||||
|
* @param option1 The text to place on the first option button
|
||||||
|
* @param option2 The text to place on the second option button
|
||||||
|
* @param option3 The text to place on the third option button
|
||||||
|
* @param messageType used to specify a default icon, can be ERROR_MESSAGE,
|
||||||
|
* INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or PLAIN_MESSAGE)
|
||||||
|
* @param help The help location for this dialog
|
||||||
|
* @return The options selected by the user. 1 for the first option and
|
||||||
|
* 2 for the second option. 0 is returned if the operation is cancelled
|
||||||
|
*/
|
||||||
|
public static int showOptionNoCancelDialog(Component parent, String title, String message,
|
||||||
|
String option1, String option2, String option3, int messageType, HelpLocation help) {
|
||||||
|
|
||||||
|
return Swing.runNow(() -> {
|
||||||
|
OptionDialog info = new OptionDialog(title, message, option1, option2, option3,
|
||||||
|
messageType, null, false);
|
||||||
|
info.setHelpLocation(help);
|
||||||
|
return info.show(parent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,26 +51,28 @@ public interface Program extends DataTypeManagerDomainObject {
|
||||||
public static final String ANALYSIS_PROPERTIES = "Analyzers";
|
public static final String ANALYSIS_PROPERTIES = "Analyzers";
|
||||||
public static final String DISASSEMBLER_PROPERTIES = "Disassembler";
|
public static final String DISASSEMBLER_PROPERTIES = "Disassembler";
|
||||||
|
|
||||||
/** Name of program information property list */
|
/** Options for storing program info */
|
||||||
public static final String PROGRAM_INFO = "Program Information";
|
public static final String PROGRAM_INFO = "Program Information";
|
||||||
/** Name of program settings property list */
|
|
||||||
public static final String PROGRAM_SETTINGS = "Program Settings";
|
|
||||||
/** Name of boolean analyzed property */
|
/** Name of boolean analyzed property */
|
||||||
public static final String ANALYZED = "Analyzed";
|
public static final String ANALYZED_OPTION_NAME = "Analyzed";
|
||||||
/** Name of date created property */
|
/** Property to control if user should be asked to analyze when unanalyzed program opened */
|
||||||
|
public static final String ASK_TO_ANALYZE_OPTION_NAME = "Should Ask To Analyze";
|
||||||
|
|
||||||
|
/** Date created property */
|
||||||
public static final String DATE_CREATED = "Date Created";
|
public static final String DATE_CREATED = "Date Created";
|
||||||
/** Name of ghidra version property */
|
/** Ghidra version property */
|
||||||
public static final String CREATED_WITH_GHIDRA_VERSION = "Created With Ghidra Version";
|
public static final String CREATED_WITH_GHIDRA_VERSION = "Created With Ghidra Version";
|
||||||
/** Name of ghidra preferred root namespace category property */
|
/** Ghidra preferred root namespace category property */
|
||||||
public static final String PREFERRED_ROOT_NAMESPACE_CATEGORY_PROPERTY =
|
public static final String PREFERRED_ROOT_NAMESPACE_CATEGORY_PROPERTY =
|
||||||
"Preferred Root Namespace Category";
|
"Preferred Root Namespace Category";
|
||||||
/** Creation date to ask for analysis */
|
|
||||||
|
/** Creation date for analysis */
|
||||||
public static final String ANALYSIS_START_DATE = "2007-Jan-01";
|
public static final String ANALYSIS_START_DATE = "2007-Jan-01";
|
||||||
/** Format string of analysis date */
|
/** Format string of analysis date */
|
||||||
public static final String ANALYSIS_START_DATE_FORMAT = "yyyy-MMM-dd";
|
public static final String ANALYSIS_START_DATE_FORMAT = "yyyy-MMM-dd";
|
||||||
/** A date from January 1, 1970 */
|
/** A date from January 1, 1970 */
|
||||||
public static final Date JANUARY_1_1970 = new Date(0);
|
public static final Date JANUARY_1_1970 = new Date(0);
|
||||||
|
|
||||||
/** The maximum number of operands for any assembly language */
|
/** The maximum number of operands for any assembly language */
|
||||||
public final static int MAX_OPERANDS = 16;
|
public final static int MAX_OPERANDS = 16;
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class PdbScreenShots extends GhidraScreenShotGenerator {
|
||||||
temporaryDir = createTempDirectory("example_pdb");
|
temporaryDir = createTempDirectory("example_pdb");
|
||||||
tx = program.startTransaction("set analyzed flag");
|
tx = program.startTransaction("set analyzed flag");
|
||||||
Options proplist = program.getOptions(Program.PROGRAM_INFO);
|
Options proplist = program.getOptions(Program.PROGRAM_INFO);
|
||||||
proplist.setBoolean(Program.ANALYZED, false);
|
proplist.setBoolean(Program.ANALYZED_OPTION_NAME, false);
|
||||||
PdbInfo pdbInfo = PdbInfoDotNet.fromValues("HelloWorld.pdb", 1, new GUID(GUID1_STR));
|
PdbInfo pdbInfo = PdbInfoDotNet.fromValues("HelloWorld.pdb", 1, new GUID(GUID1_STR));
|
||||||
pdbInfo.serializeToOptions(proplist);
|
pdbInfo.serializeToOptions(proplist);
|
||||||
proplist.setString("Executable Location",
|
proplist.setString("Executable Location",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue