mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/patch'
Conflicts: Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java
This commit is contained in:
commit
046623b1f7
6 changed files with 86 additions and 67 deletions
|
@ -255,7 +255,7 @@ public class DebuggerConsoleProvider extends ComponentProviderAdapter
|
||||||
if (renderer instanceof ConsoleActionsCellRenderer) {
|
if (renderer instanceof ConsoleActionsCellRenderer) {
|
||||||
ActionList actions =
|
ActionList actions =
|
||||||
(ActionList) getModel().getValueAt(r, convertColumnIndexToModel(c));
|
(ActionList) getModel().getValueAt(r, convertColumnIndexToModel(c));
|
||||||
if (!actions.isEmpty()) {
|
if (actions != null && !actions.isEmpty()) {
|
||||||
return ACTION_BUTTON_SIZE;
|
return ACTION_BUTTON_SIZE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -15,12 +15,8 @@
|
||||||
*/
|
*/
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.Language;
|
||||||
import ghidra.program.model.listing.IncompatibleLanguageException;
|
|
||||||
import ghidra.program.util.LanguageTranslator;
|
|
||||||
import ghidra.program.util.LanguageTranslatorAdapter;
|
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.AssertException;
|
|
||||||
|
|
||||||
public class ForceRedisassembly extends GhidraScript {
|
public class ForceRedisassembly extends GhidraScript {
|
||||||
|
|
||||||
|
@ -33,50 +29,8 @@ public class ForceRedisassembly extends GhidraScript {
|
||||||
}
|
}
|
||||||
ProgramDB program = (ProgramDB) currentProgram;
|
ProgramDB program = (ProgramDB) currentProgram;
|
||||||
|
|
||||||
Language lang = program.getLanguage();
|
Language lang = null;
|
||||||
|
|
||||||
LanguageTranslator translator =
|
program.setLanguage(lang, null, true, monitor);
|
||||||
new MyLanguageTranslator(lang.getLanguageID(), lang.getVersion());
|
|
||||||
if (!translator.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
program.setLanguage(translator, program.getCompilerSpec().getCompilerSpecID(), true,
|
|
||||||
monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MyLanguageTranslator extends LanguageTranslatorAdapter {
|
|
||||||
protected MyLanguageTranslator(LanguageID languageId, int version) {
|
|
||||||
super(languageId, version, languageId, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValid() {
|
|
||||||
if (super.isValid()) {
|
|
||||||
try {
|
|
||||||
validateDefaultSpaceMap();
|
|
||||||
}
|
|
||||||
catch (IncompatibleLanguageException e) {
|
|
||||||
throw new AssertException();
|
|
||||||
}
|
|
||||||
Register newContextReg = getNewLanguage().getContextBaseRegister();
|
|
||||||
if (newContextReg != Register.NO_CONTEXT) {
|
|
||||||
Register oldContextReg = getOldLanguage().getContextBaseRegister();
|
|
||||||
if (oldContextReg != Register.NO_CONTEXT ||
|
|
||||||
!isSameRegisterConstruction(oldContextReg, newContextReg)) {
|
|
||||||
throw new AssertException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "[" + getOldLanguageID() + " (Version " + getOldVersion() + ")] -> [" +
|
|
||||||
getNewLanguageID() + " (Version " + getNewVersion() +
|
|
||||||
")] {Forced Re-Disassembly Translator}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,9 @@ import ghidra.framework.options.Options;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
import ghidra.xml.XmlParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Program-specific version of the {@link CompilerSpec}.
|
* A Program-specific version of the {@link CompilerSpec}.
|
||||||
|
@ -119,20 +121,19 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
||||||
ArrayList<PrototypeModel> finalList = new ArrayList<>();
|
ArrayList<PrototypeModel> finalList = new ArrayList<>();
|
||||||
TreeSet<String> currentNames = new TreeSet<>();
|
TreeSet<String> currentNames = new TreeSet<>();
|
||||||
for (PrototypeModel model : allmodels) {
|
for (PrototypeModel model : allmodels) {
|
||||||
currentNames.add(model.getName());
|
|
||||||
if (usermodels.containsKey(model.getName())) {
|
if (usermodels.containsKey(model.getName())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
currentNames.add(model.getName());
|
||||||
finalList.add(model); // Add original non-userdef models
|
finalList.add(model); // Add original non-userdef models
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usermodels.clear();
|
||||||
for (PrototypeModel model : extensions) {
|
for (PrototypeModel model : extensions) {
|
||||||
if (currentNames.contains(model.getName())) {
|
if (currentNames.contains(model.getName())) {
|
||||||
if (!usermodels.containsKey(model.getName())) {
|
Msg.warn(this,
|
||||||
Msg.warn(this,
|
"Cannot override prototype model " + model.getName() + " with extension");
|
||||||
"Cannot override prototype model " + model.getName() + " with extension");
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
markPrototypeAsExtension(model);
|
markPrototypeAsExtension(model);
|
||||||
finalList.add(model);
|
finalList.add(model);
|
||||||
|
@ -150,7 +151,13 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
||||||
if (evalCalledModel != null) {
|
if (evalCalledModel != null) {
|
||||||
evalCalledName = evalCalledModel.getName();
|
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()) {
|
if (usermodels.isEmpty()) {
|
||||||
usermodels = null;
|
usermodels = null;
|
||||||
}
|
}
|
||||||
|
@ -335,7 +342,7 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
||||||
case EVAL_CALLED:
|
case EVAL_CALLED:
|
||||||
return evalCalledModel; // TODO: Currently no option
|
return evalCalledModel; // TODO: Currently no option
|
||||||
}
|
}
|
||||||
return null;
|
return defaultModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -370,6 +377,21 @@ public class ProgramCompilerSpec extends BasicCompilerSpec {
|
||||||
EVALUATION_MODEL_PROPERTY_NAME);
|
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
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
|
|
@ -2053,6 +2053,7 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
setEventsEnabled(false);
|
setEventsEnabled(false);
|
||||||
try {
|
try {
|
||||||
boolean redisassemblyRequired = true;
|
boolean redisassemblyRequired = true;
|
||||||
|
LanguageID oldLanguageId = languageID;
|
||||||
int oldLanguageVersion = languageVersion;
|
int oldLanguageVersion = languageVersion;
|
||||||
int oldLanguageMinorVersion = languageMinorVersion;
|
int oldLanguageMinorVersion = languageMinorVersion;
|
||||||
if (translator != null) {
|
if (translator != null) {
|
||||||
|
@ -2081,6 +2082,12 @@ public class ProgramDB extends DomainObjectAdapterDB implements Program, ChangeM
|
||||||
if (newCompilerSpecID != null) {
|
if (newCompilerSpecID != null) {
|
||||||
compilerSpec = ProgramCompilerSpec.getProgramCompilerSpec(this,
|
compilerSpec = ProgramCompilerSpec.getProgramCompilerSpec(this,
|
||||||
language.getCompilerSpecByID(newCompilerSpecID));
|
language.getCompilerSpecByID(newCompilerSpecID));
|
||||||
|
if (!oldLanguageId.equals(languageID) ||
|
||||||
|
!compilerSpecID.equals(newCompilerSpecID)) {
|
||||||
|
if (compilerSpec instanceof ProgramCompilerSpec) {
|
||||||
|
((ProgramCompilerSpec) compilerSpec).resetProgramOptions(monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
compilerSpecID = compilerSpec.getCompilerSpecID();
|
compilerSpecID = compilerSpec.getCompilerSpecID();
|
||||||
languageVersion = language.getVersion();
|
languageVersion = language.getVersion();
|
||||||
|
|
|
@ -513,6 +513,24 @@ public class SpecExtension {
|
||||||
throw new XmlParseException("Unknown compiler spec extension: " + elName);
|
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
|
* Check that the proposed callfixup extension does not collide with built-in fixups
|
||||||
* @param doc is info about the proposed extension
|
* @param doc is info about the proposed extension
|
||||||
|
|
|
@ -336,7 +336,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||||
case EVAL_CALLED:
|
case EVAL_CALLED:
|
||||||
return evalCalledModel;
|
return evalCalledModel;
|
||||||
}
|
}
|
||||||
return null;
|
return defaultModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -414,17 +414,35 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||||
* Build the model arrays given a complete list of models.
|
* Build the model arrays given a complete list of models.
|
||||||
* The array -models- contains all normal PrototypeModel objects
|
* The array -models- contains all normal PrototypeModel objects
|
||||||
* The array -allmodels- contains all models, including merge models.
|
* 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 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 fullcount = 0;
|
||||||
int resolvecount = 0;
|
int resolvecount = 0;
|
||||||
|
boolean foundDefault = false;
|
||||||
for (PrototypeModel model : modelList) {
|
for (PrototypeModel model : modelList) {
|
||||||
fullcount += 1;
|
fullcount += 1;
|
||||||
if (model.isMerged()) {
|
if (model.isMerged()) {
|
||||||
resolvecount += 1;
|
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];
|
models = new PrototypeModel[fullcount - resolvecount];
|
||||||
allmodels = new PrototypeModel[fullcount];
|
allmodels = new PrototypeModel[fullcount];
|
||||||
|
@ -449,17 +467,20 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||||
* All xrefs are regenerated from a single complete list of PrototypeModels.
|
* All xrefs are regenerated from a single complete list of PrototypeModels.
|
||||||
* If there are PrototypeModels with duplicate names, return an example name.
|
* If there are PrototypeModels with duplicate names, return an example name.
|
||||||
* Return null otherwise
|
* Return null otherwise
|
||||||
|
* 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 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 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)
|
* @param evalCalled is the name to use for evaluating called functions (or null)
|
||||||
* @return a PrototypeModel name that was duplicated or null
|
* @return a PrototypeModel name that was duplicated or null
|
||||||
|
* @throws XmlParseException if there is no model matching defaultName
|
||||||
*/
|
*/
|
||||||
protected String modelXrefs(List<PrototypeModel> modelList, String defaultName,
|
protected String modelXrefs(List<PrototypeModel> modelList, String defaultName,
|
||||||
String evalCurrent, String evalCalled) {
|
String evalCurrent, String evalCalled) throws XmlParseException {
|
||||||
String foundDuplicate = null;
|
String foundDuplicate = null;
|
||||||
buildModelArrays(modelList);
|
buildModelArrays(modelList, defaultName);
|
||||||
callingConventionMap = new HashMap<>();
|
callingConventionMap = new HashMap<>();
|
||||||
for (PrototypeModel model : models) {
|
for (PrototypeModel model : models) {
|
||||||
String name = model.getName();
|
String name = model.getName();
|
||||||
|
@ -471,10 +492,7 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultModel = null;
|
defaultModel = callingConventionMap.get(defaultName);
|
||||||
if (defaultName != null) {
|
|
||||||
defaultModel = callingConventionMap.get(defaultName);
|
|
||||||
}
|
|
||||||
evalCurrentModel = defaultModel; // The default evaluation is to assume default model
|
evalCurrentModel = defaultModel; // The default evaluation is to assume default model
|
||||||
evalCalledModel = defaultModel;
|
evalCalledModel = defaultModel;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue