mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 21:52:59 +00:00
GP-1715 Guarantee default and evaluation models exist
This commit is contained in:
parent
c3c20d9e0f
commit
3ac3694226
|
@ -25,7 +25,9 @@ import ghidra.framework.options.Options;
|
|||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.xml.XmlParseException;
|
||||
|
||||
/**
|
||||
* A Program-specific version of the {@link CompilerSpec}.
|
||||
|
@ -150,7 +152,13 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
|||
if (evalCalledModel != null) {
|
||||
evalCalledName = evalCalledModel.getName();
|
||||
}
|
||||
modelXrefs(finalList, defaultName, evalName, evalCalledName);
|
||||
try {
|
||||
modelXrefs(finalList, defaultName, evalName, evalCalledName);
|
||||
}
|
||||
catch (XmlParseException e) {
|
||||
Msg.warn(this, "Prototype model extensions NOT installed: " + e.getMessage());
|
||||
usermodels.clear();
|
||||
}
|
||||
if (usermodels.isEmpty()) {
|
||||
usermodels = null;
|
||||
}
|
||||
|
@ -335,7 +343,7 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
|||
case EVAL_CALLED:
|
||||
return evalCalledModel; // TODO: Currently no option
|
||||
}
|
||||
return null;
|
||||
return defaultModel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -370,6 +378,21 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
|||
EVALUATION_MODEL_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset options to default (for this CompilerSpec)
|
||||
* This is for setLanguage to clear out strings that might belong to the old language.
|
||||
* @param monitor is the monitor for checking cancellation
|
||||
* @throws CancelledException if operation is cancelled externally
|
||||
*/
|
||||
protected void resetProgramOptions(TaskMonitor monitor) throws CancelledException {
|
||||
Options decompilerPropertyList = program.getOptions(DECOMPILER_PROPERTY_LIST_NAME);
|
||||
decompilerPropertyList.restoreDefaultValue(EVALUATION_MODEL_PROPERTY_NAME);
|
||||
if (decompilerPropertyList.contains(DECOMPILER_OUTPUT_LANGUAGE)) {
|
||||
decompilerPropertyList.restoreDefaultValue(DECOMPILER_OUTPUT_LANGUAGE);
|
||||
}
|
||||
SpecExtension.clearAllExtensions(program, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
|
|
@ -2079,6 +2079,9 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
|||
if (newCompilerSpecID != null) {
|
||||
compilerSpec = ProgramCompilerSpec.getProgramCompilerSpec(this,
|
||||
language.getCompilerSpecByID(newCompilerSpecID));
|
||||
if (compilerSpec instanceof ProgramCompilerSpec) {
|
||||
((ProgramCompilerSpec) compilerSpec).resetProgramOptions(monitor);
|
||||
}
|
||||
}
|
||||
compilerSpecID = compilerSpec.getCompilerSpecID();
|
||||
languageVersion = language.getVersion();
|
||||
|
|
|
@ -513,6 +513,24 @@ public class SpecExtension {
|
|||
throw new XmlParseException("Unknown compiler spec extension: " + elName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all spec extension options for the given program.
|
||||
* This is intended for internal use. ProgramDB.installExtensions() must be called at
|
||||
* some later time to see the effect.
|
||||
* @param program is the given Program
|
||||
* @param monitor is a monitor for the operation
|
||||
* @throws CancelledException if something externally cancels the operation
|
||||
*/
|
||||
protected static void clearAllExtensions(Program program, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
Options specOptions = program.getOptions(SpecExtension.SPEC_EXTENSION);
|
||||
List<String> optionNames = specOptions.getOptionNames();
|
||||
for (String name : optionNames) {
|
||||
monitor.checkCanceled();
|
||||
specOptions.removeOption(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the proposed callfixup extension does not collide with built-in fixups
|
||||
* @param doc is info about the proposed extension
|
||||
|
|
|
@ -375,7 +375,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
case EVAL_CALLED:
|
||||
return evalCalledModel;
|
||||
}
|
||||
return null;
|
||||
return defaultModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -453,17 +453,35 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
* Build the model arrays given a complete list of models.
|
||||
* The array -models- contains all normal PrototypeModel objects
|
||||
* The array -allmodels- contains all models, including merge models.
|
||||
* We also check that a suitable model exists that matches a desired default name.
|
||||
* In principle, the XML schema should guarantee that the model exists, but if for some reason
|
||||
* it doesn't, an exception is thrown.
|
||||
*
|
||||
* @param modelList is the complete list of models
|
||||
* @param putativeDefaultName is the desired name of the default model
|
||||
* @throws XmlParseException if a suitable default model cannot be found
|
||||
*/
|
||||
private void buildModelArrays(List<PrototypeModel> modelList) {
|
||||
private void buildModelArrays(List<PrototypeModel> modelList, String putativeDefaultName)
|
||||
throws XmlParseException {
|
||||
if (putativeDefaultName == null) {
|
||||
throw new XmlParseException("Compiler Spec " + description.getCompilerSpecName() +
|
||||
" does not provide a default prototype");
|
||||
}
|
||||
int fullcount = 0;
|
||||
int resolvecount = 0;
|
||||
boolean foundDefault = false;
|
||||
for (PrototypeModel model : modelList) {
|
||||
fullcount += 1;
|
||||
if (model.isMerged()) {
|
||||
resolvecount += 1;
|
||||
}
|
||||
else if (putativeDefaultName.equals(model.getName())) {
|
||||
foundDefault = true; // Matching name AND not a merged model
|
||||
}
|
||||
}
|
||||
if (!foundDefault) {
|
||||
throw new XmlParseException("Could not find default model " + putativeDefaultName +
|
||||
"for Compiler Spec " + description.getCompilerSpecName());
|
||||
}
|
||||
models = new PrototypeModel[fullcount - resolvecount];
|
||||
allmodels = new PrototypeModel[fullcount];
|
||||
|
@ -485,16 +503,19 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
|
||||
/**
|
||||
* Establish cross referencing to prototype models.
|
||||
* All xrefs are regenerated from a single complete list of PrototypeModels
|
||||
* All xrefs are regenerated from a single complete list of PrototypeModels.
|
||||
* The modelList must provide a model with name matching defaultName or
|
||||
* an exception is thrown. (In theory the schema guarantees this model always exists)
|
||||
*
|
||||
* @param modelList is the complete list of models
|
||||
* @param defaultName is the name to use for the default model (or null)
|
||||
* @param defaultName is the name to use for the default model
|
||||
* @param evalCurrent is the name to use for evaluating the current function (or null)
|
||||
* @param evalCalled is the name to use for evaluating called functions (or null)
|
||||
* @throws XmlParseException if there is no model matching defaultName
|
||||
*/
|
||||
protected void modelXrefs(List<PrototypeModel> modelList, String defaultName,
|
||||
String evalCurrent, String evalCalled) {
|
||||
buildModelArrays(modelList);
|
||||
String evalCurrent, String evalCalled) throws XmlParseException {
|
||||
buildModelArrays(modelList, defaultName);
|
||||
callingConventionMap = new HashMap<>();
|
||||
for (PrototypeModel model : models) {
|
||||
String name = model.getName();
|
||||
|
@ -503,10 +524,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
|||
}
|
||||
}
|
||||
|
||||
defaultModel = null;
|
||||
if (defaultName != null) {
|
||||
defaultModel = callingConventionMap.get(defaultName);
|
||||
}
|
||||
defaultModel = callingConventionMap.get(defaultName);
|
||||
evalCurrentModel = defaultModel; // The default evaluation is to assume default model
|
||||
evalCalledModel = defaultModel;
|
||||
|
||||
|
|
Loading…
Reference in a new issue