mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/GP-4886_ghidra1_UnassignedStorageForDefaultDatatype'
This commit is contained in:
commit
4f79536a50
20 changed files with 454 additions and 358 deletions
|
@ -35,12 +35,15 @@ import ghidra.util.task.TaskMonitor;
|
|||
* NOTE: referenced thunk-functions should be created prior to this command
|
||||
*/
|
||||
public class FunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
||||
|
||||
private boolean dontCreateNewVariables = false;
|
||||
|
||||
private final boolean forceProcessing;
|
||||
private final boolean createStackParams;
|
||||
private final boolean createLocalStackVars;
|
||||
|
||||
private AddressSet entryPoints = new AddressSet();
|
||||
private Program program;
|
||||
private boolean forceProcessing = false;
|
||||
private boolean dontCreateNewVariables = false;
|
||||
private boolean doParams = false;
|
||||
private boolean doLocals = false;
|
||||
|
||||
static String DEFAULT_FUNCTION_COMMENT = " FUNCTION";
|
||||
|
||||
|
@ -52,7 +55,7 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
* has already been defined.
|
||||
*/
|
||||
public FunctionStackAnalysisCmd(AddressSetView entries, boolean forceProcessing) {
|
||||
this(entries, true, true, forceProcessing);
|
||||
this(entries, false, true, forceProcessing);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,7 +66,7 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
* has already been defined.
|
||||
*/
|
||||
public FunctionStackAnalysisCmd(Address entry, boolean forceProcessing) {
|
||||
this(new AddressSet(entry, entry), true, true, forceProcessing);
|
||||
this(new AddressSet(entry, entry), false, true, forceProcessing);
|
||||
}
|
||||
|
||||
public FunctionStackAnalysisCmd(AddressSetView entries, boolean doParameterAnalysis,
|
||||
|
@ -71,8 +74,8 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
super("Create Function Stack Variables", true, true, false);
|
||||
entryPoints.add(entries);
|
||||
this.forceProcessing = forceProcessing;
|
||||
doParams = doParameterAnalysis;
|
||||
doLocals = doLocalAnalysis;
|
||||
createStackParams = doParameterAnalysis;
|
||||
createLocalStackVars = doLocalAnalysis;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -354,10 +357,10 @@ public class FunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
Variable var = frame.getVariableContaining(frameLoc);
|
||||
if (var == null) {
|
||||
try {
|
||||
if (!doLocals && frameLoc <= 0) {
|
||||
if (!createLocalStackVars && frameLoc <= 0) {
|
||||
return null;
|
||||
}
|
||||
if (!doParams && frameLoc > 0) {
|
||||
if (!createStackParams && frameLoc > 0) {
|
||||
return null;
|
||||
}
|
||||
// only create variables at locations where a variable doesn't exist
|
||||
|
|
|
@ -43,46 +43,59 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
private static final int MAX_PARAM_OFFSET = 2048; // max size of param reference space
|
||||
private static final int MAX_LOCAL_OFFSET = -(64 * 1024); // max size of local reference space
|
||||
|
||||
private boolean dontCreateNewVariables = false;
|
||||
|
||||
private final boolean forceProcessing;
|
||||
private final boolean createStackParams;
|
||||
private final boolean createLocalStackVars;
|
||||
|
||||
private AddressSet entryPoints = new AddressSet();
|
||||
private Program program;
|
||||
private boolean forceProcessing = false;
|
||||
private boolean dontCreateNewVariables = false;
|
||||
private boolean doParams = false;
|
||||
private boolean doLocals = false;
|
||||
private Register stackReg;
|
||||
private int purge = 0;
|
||||
|
||||
static String DEFAULT_FUNCTION_COMMENT = " FUNCTION";
|
||||
|
||||
/**
|
||||
* Constructs a new command for analyzing the Stack.
|
||||
* Constructs a new command for analyzing the Stack. All stack references will be
|
||||
* marked-up and local stack variables created. Stack parameters are not created
|
||||
* by default to avoid setting an incomplete function signature.
|
||||
* @param entries and address set indicating the entry points of functions that have
|
||||
* stacks to be analyzed.
|
||||
* @param forceProcessing flag to force processing of stack references even if the stack
|
||||
* has already been defined.
|
||||
*/
|
||||
public NewFunctionStackAnalysisCmd(AddressSetView entries, boolean forceProcessing) {
|
||||
this(entries, true, true, forceProcessing);
|
||||
this(entries, false, true, forceProcessing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new command for analyzing the Stack.
|
||||
* Constructs a new command for analyzing the Stack. All stack references will be
|
||||
* marked-up and local stack variables created. Stack parameters are not created
|
||||
* by default to avoid setting an incomplete function signature.
|
||||
* @param entry the entry point of the function that contains the stack to
|
||||
* be analyzed.
|
||||
* @param forceProcessing flag to force processing of stack references even if the stack
|
||||
* has already been defined.
|
||||
*/
|
||||
public NewFunctionStackAnalysisCmd(Address entry, boolean forceProcessing) {
|
||||
this(new AddressSet(entry, entry), true, true, forceProcessing);
|
||||
this(new AddressSet(entry, entry), false, true, forceProcessing);
|
||||
}
|
||||
|
||||
public NewFunctionStackAnalysisCmd(AddressSetView entries, boolean doParameterAnalysis,
|
||||
boolean doLocalAnalysis, boolean forceProcessing) {
|
||||
/**
|
||||
*
|
||||
* @param entries
|
||||
* @param createStackParams
|
||||
* @param createLocalStackVars
|
||||
* @param forceProcessing
|
||||
*/
|
||||
public NewFunctionStackAnalysisCmd(AddressSetView entries, boolean createStackParams,
|
||||
boolean createLocalStackVars, boolean forceProcessing) {
|
||||
super("Create Function Stack Variables", true, true, false);
|
||||
entryPoints.add(entries);
|
||||
this.forceProcessing = forceProcessing;
|
||||
doParams = doParameterAnalysis;
|
||||
doLocals = doLocalAnalysis;
|
||||
this.createStackParams = createStackParams;
|
||||
this.createLocalStackVars = createLocalStackVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -479,8 +492,6 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
|
||||
}
|
||||
|
||||
private static final int MAX_PARAM_FILLIN_COUNT = 10;
|
||||
|
||||
private int addMissingParameters(Variable stackVar, int nextCopyParamIndex,
|
||||
Parameter[] oldParamList, List<Variable> newParamList, PrototypeModel callingConvention,
|
||||
boolean hasStackParams) {
|
||||
|
@ -516,37 +527,6 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
++nextCopyParamIndex;
|
||||
}
|
||||
|
||||
// fill-in missing params - don't bother if we already have
|
||||
// too many or no stack param block defined
|
||||
int nextOrdinal = newParamList.size();
|
||||
if ((!hasStackParams) || nextOrdinal >= MAX_PARAM_FILLIN_COUNT) {
|
||||
return nextCopyParamIndex;
|
||||
}
|
||||
|
||||
VariableStorage argLocation;
|
||||
try {
|
||||
Parameter[] params = new Parameter[nextOrdinal];
|
||||
argLocation = callingConvention.getArgLocation(nextOrdinal,
|
||||
newParamList.toArray(params), DataType.DEFAULT, program);
|
||||
while (!argLocation.intersects(stackVar.getVariableStorage()) &&
|
||||
nextOrdinal < MAX_PARAM_FILLIN_COUNT) {
|
||||
// TODO: it feels bad to add a bunch of register variables
|
||||
Parameter p = new ParameterImpl(null, DataType.DEFAULT, argLocation, program);
|
||||
newParamList.add(p);
|
||||
++nextOrdinal;
|
||||
params = new Parameter[nextOrdinal];
|
||||
argLocation = callingConvention.getArgLocation(nextOrdinal,
|
||||
newParamList.toArray(params), DataType.DEFAULT, program);
|
||||
}
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new RuntimeException(e); // unexpected
|
||||
}
|
||||
|
||||
if (!argLocation.isStackStorage()) {
|
||||
return nextCopyParamIndex;
|
||||
}
|
||||
|
||||
return nextCopyParamIndex;
|
||||
}
|
||||
|
||||
|
@ -792,10 +772,10 @@ public class NewFunctionStackAnalysisCmd extends BackgroundCommand<Program> {
|
|||
(growsNegative && offset >= paramOffset) || (!growsNegative && offset <= paramOffset);
|
||||
|
||||
// Check exclusion options
|
||||
if (!doLocals && !isParam) {
|
||||
if (!createLocalStackVars && !isParam) {
|
||||
return;
|
||||
}
|
||||
if (!doParams && isParam) {
|
||||
if (!createStackParams && isParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ public class StackVariableAnalyzer extends AbstractAnalyzer {
|
|||
private static final String DESCRIPTION = "Creates stack variables for a function.";
|
||||
|
||||
private boolean doNewStackAnalysis = true;
|
||||
private boolean doLocalAnalysis = true;
|
||||
private boolean doParameterAnalysis = true;
|
||||
private boolean doCreateLocalStackVars = true;
|
||||
private boolean doCreateStackParams = false;
|
||||
|
||||
public StackVariableAnalyzer() {
|
||||
super(NAME, DESCRIPTION, AnalyzerType.FUNCTION_ANALYZER);
|
||||
|
@ -43,13 +43,15 @@ public class StackVariableAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) {
|
||||
BackgroundCommand cmd;
|
||||
BackgroundCommand<Program> cmd;
|
||||
|
||||
if (doNewStackAnalysis) {
|
||||
cmd = new NewFunctionStackAnalysisCmd(set, doParameterAnalysis, doLocalAnalysis, false);
|
||||
cmd = new NewFunctionStackAnalysisCmd(set, doCreateStackParams, doCreateLocalStackVars,
|
||||
false);
|
||||
}
|
||||
else {
|
||||
cmd = new FunctionStackAnalysisCmd(set, doParameterAnalysis, doLocalAnalysis, false);
|
||||
cmd = new FunctionStackAnalysisCmd(set, doCreateStackParams, doCreateLocalStackVars,
|
||||
false);
|
||||
}
|
||||
|
||||
cmd.applyTo(program, monitor);
|
||||
|
@ -73,10 +75,10 @@ public class StackVariableAnalyzer extends AbstractAnalyzer {
|
|||
!useOldStackAnalysisByDefault(program), null,
|
||||
"Use General Stack Reference Propogator (This works best on most processors)");
|
||||
|
||||
options.registerOption("Create Local Variables", doLocalAnalysis, null,
|
||||
options.registerOption("Create Local Variables", doCreateLocalStackVars, null,
|
||||
"Create Function Local stack variables and references");
|
||||
|
||||
options.registerOption("Create Param Variables", doParameterAnalysis, null,
|
||||
options.registerOption("Create Param Variables", doCreateStackParams, null,
|
||||
"Create Function Parameter stack variables and references");
|
||||
}
|
||||
|
||||
|
@ -86,9 +88,10 @@ public class StackVariableAnalyzer extends AbstractAnalyzer {
|
|||
options.getBoolean(GhidraLanguagePropertyKeys.USE_NEW_FUNCTION_STACK_ANALYSIS,
|
||||
!useOldStackAnalysisByDefault(program));
|
||||
|
||||
doLocalAnalysis = options.getBoolean("Create Local Variables", doLocalAnalysis);
|
||||
doCreateLocalStackVars =
|
||||
options.getBoolean("Create Local Variables", doCreateLocalStackVars);
|
||||
|
||||
doParameterAnalysis = options.getBoolean("Create Param Variables", doParameterAnalysis);
|
||||
doCreateStackParams = options.getBoolean("Create Param Variables", doCreateStackParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -95,8 +95,8 @@ public class DemangledDataType extends DemangledType {
|
|||
private static final String UNSIGNED_LONG = "unsigned long";
|
||||
|
||||
public final static String[] PRIMITIVES =
|
||||
{ VOID, BOOL, CHAR, WCHAR_T, WCHAR16, WCHAR32, CHAR8_T, SHORT, INT, INT0_T, LONG,
|
||||
LONG_LONG, FLOAT, FLOAT2, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, };
|
||||
{ VOID, BOOL, CHAR, WCHAR_T, WCHAR16, WCHAR32, CHAR8_T, SHORT, INT, INT0_T, LONG, LONG_LONG,
|
||||
FLOAT, FLOAT2, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, };
|
||||
|
||||
private int arrayDimensions = 0;
|
||||
private boolean isClass;
|
||||
|
@ -200,10 +200,10 @@ public class DemangledDataType extends DemangledType {
|
|||
else if (dt == null) {
|
||||
|
||||
// I don't know what this is
|
||||
// If it isn't pointed to, or isn't a referent, then assume typedef.
|
||||
// If it isn't pointed to, or isn't a referent, then assume undefined typedef.
|
||||
if (!(isReference() || isPointer())) { // Unknown type
|
||||
dt = new TypedefDataType(getDemanglerCategoryPath(getNamespace()), name,
|
||||
new DWordDataType());
|
||||
DataType.DEFAULT);
|
||||
}
|
||||
else {
|
||||
// try creating empty structures for unknown types instead.
|
||||
|
|
|
@ -92,9 +92,13 @@ public class ClassicSampleX86ProgramBuilder extends ProgramBuilder {
|
|||
TestUtils.setInstanceField("isEnabled", analysisMgr, Boolean.FALSE);
|
||||
}
|
||||
else {
|
||||
// enable stack analysis
|
||||
// enable full stack analysis with variable/param creation
|
||||
startTransaction();
|
||||
p.getOptions(Program.ANALYSIS_PROPERTIES).setBoolean("Stack", true);
|
||||
p.getOptions(Program.ANALYSIS_PROPERTIES)
|
||||
.setBoolean("Stack.Create Local Variables", true);
|
||||
p.getOptions(Program.ANALYSIS_PROPERTIES)
|
||||
.setBoolean("Stack.Create Param Variables", true);
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
|
@ -472,11 +476,11 @@ public class ClassicSampleX86ProgramBuilder extends ProgramBuilder {
|
|||
|
||||
startTransaction();
|
||||
StringDataType string = new StringDataType();
|
||||
DataType pointer = new Pointer32DataType(string);
|
||||
Parameter p0 = new ParameterImpl("destStr", pointer, getProgram());
|
||||
Parameter p3 = new ParameterImpl("parm_3", DataType.DEFAULT, getProgram());
|
||||
Parameter p4 = new ParameterImpl("parm_4", DataType.DEFAULT, getProgram());
|
||||
createEmptyFunction("sscanf", "0x0100415a", 78, new Undefined1DataType(), p0, p3, p4);
|
||||
DataType stringPtr = new Pointer32DataType(string);
|
||||
Parameter p0 = new ParameterImpl("destStr", stringPtr, getProgram());
|
||||
Parameter p3 = new ParameterImpl("parm_3", Pointer32DataType.dataType, getProgram());
|
||||
Parameter p4 = new ParameterImpl("parm_4", Pointer32DataType.dataType, getProgram());
|
||||
createEmptyFunction("sscanf", "0x0100415a", 78, IntegerDataType.dataType, p0, p3, p4);
|
||||
|
||||
ReferenceManager referenceManager = getProgram().getReferenceManager();
|
||||
referenceManager.addStackReference(addr("0x0100416c"), 0, 0x4, RefType.READ,
|
||||
|
|
|
@ -834,7 +834,7 @@ public class TestEnv {
|
|||
AbstractGuiTest.runSwing(() -> {
|
||||
tool = launchDefaultTool();
|
||||
ProgramManager pm = tool.getService(ProgramManager.class);
|
||||
pm.openProgram(program.getDomainFile());
|
||||
pm.openProgram(program);
|
||||
});
|
||||
|
||||
if (tool == null) {
|
||||
|
|
|
@ -45,6 +45,7 @@ import ghidra.framework.plugintool.PluginTool;
|
|||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Undefined4DataType;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
|
@ -73,7 +74,7 @@ public class CopyPasteFunctionInfoTest extends AbstractGhidraHeadedIntegrationTe
|
|||
ToyProgramBuilder builder = new ToyProgramBuilder(name, true, ProgramBuilder._TOY);
|
||||
builder.createMemory("test1", "0x01001000", 0x8000);
|
||||
builder.createEntryPoint("0x1006420", "entry");
|
||||
DataType dt = DataType.DEFAULT;
|
||||
DataType dt = Undefined4DataType.dataType;
|
||||
Parameter p = new ParameterImpl(null, dt, builder.getProgram());
|
||||
builder.createEmptyFunction("ghidra", "0x1004600", 1, dt, p, p, p, p, p, p, p, p, p, p, p,
|
||||
p, p);
|
||||
|
@ -87,7 +88,7 @@ public class CopyPasteFunctionInfoTest extends AbstractGhidraHeadedIntegrationTe
|
|||
builder.createEntryPoint("0x1006420", "entry");
|
||||
builder.createFunction("0x1004700");
|
||||
builder.createComment("0x1006420", "FUNCTION", CodeUnit.PLATE_COMMENT);
|
||||
DataType dt = DataType.DEFAULT;
|
||||
DataType dt = Undefined4DataType.dataType;
|
||||
Parameter p = new ParameterImpl(null, dt, builder.getProgram());
|
||||
builder.createEmptyFunction("BOB", "0x1004260", 1, dt, p, p, p, p, p, p, p, p, p, p, p, p,
|
||||
p);
|
||||
|
@ -481,8 +482,7 @@ public class CopyPasteFunctionInfoTest extends AbstractGhidraHeadedIntegrationTe
|
|||
|
||||
private void resetOptions() {
|
||||
List<String> names = fieldOptions2.getOptionNames();
|
||||
for (int i = 0; i < names.size(); i++) {
|
||||
String name = names.get(i);
|
||||
for (String name : names) {
|
||||
if (!name.startsWith("Format Code")) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -358,7 +358,9 @@ public abstract class AbstractEditorTest extends AbstractGhidraHeadedIntegration
|
|||
}
|
||||
|
||||
protected DataTypeComponent getComponent(int index) {
|
||||
return runSwing(() -> model.getComponent(index));
|
||||
return runSwing(() ->
|
||||
model.getComponent(index));
|
||||
|
||||
}
|
||||
|
||||
protected int getOffset(int index) {
|
||||
|
|
|
@ -39,6 +39,7 @@ import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
|||
import ghidra.app.plugin.core.data.DataPlugin;
|
||||
import ghidra.app.plugin.core.disassembler.DisassemblerPlugin;
|
||||
import ghidra.app.plugin.core.highlight.SetHighlightPlugin;
|
||||
import ghidra.app.plugin.core.instructionsearch.model.InstructionSearchData.UpdateType;
|
||||
import ghidra.app.plugin.core.navigation.*;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
import ghidra.app.util.AddEditDialog;
|
||||
|
@ -52,6 +53,7 @@ import ghidra.program.model.address.Address;
|
|||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.listing.Function.FunctionUpdateType;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.test.*;
|
||||
|
@ -1286,9 +1288,19 @@ public class Function1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
env.showTool();
|
||||
loadProgram("notepad");
|
||||
Function f = createFunctionAtEntry();
|
||||
// Test requires a size-constrained register variable edit
|
||||
program.withTransaction("Update Signature",
|
||||
() -> f.updateFunction(null, null, FunctionUpdateType.CUSTOM_STORAGE, true,
|
||||
SourceType.ANALYSIS, new ParameterImpl("test", Undefined4DataType.dataType,
|
||||
program.getRegister("EBX"), program)));
|
||||
setCustomParameterStorage(f, true);
|
||||
|
||||
assertTrue(cb.goToField(addr("0x1006420"), "Variable Type", 0, 0));
|
||||
waitForSwing();
|
||||
|
||||
// Set location to param_1 datatype field
|
||||
assertTrue(cb.goToField(addr("0x1006420"), "Variable Type", 1, 0, 0));
|
||||
|
||||
waitForSwing();
|
||||
|
||||
performAction(chooseDataType, cb.getProvider(), false);
|
||||
DataTypeSelectionDialog dialog = waitForDialogComponent(DataTypeSelectionDialog.class);
|
||||
|
|
|
@ -106,7 +106,7 @@ public class LocationReferencesPlugin3Test extends AbstractLocationReferencesTes
|
|||
|
||||
// 0100415a - sscanf
|
||||
Address address = addr(0x0100415a);
|
||||
int parameterColumn = 28; // param 0's name
|
||||
int parameterColumn = 24; // param 0's name
|
||||
goTo(address, "Function Signature", parameterColumn);
|
||||
|
||||
search();
|
||||
|
@ -142,7 +142,7 @@ public class LocationReferencesPlugin3Test extends AbstractLocationReferencesTes
|
|||
|
||||
// 0100415a - sscanf
|
||||
Address address = addr(0x0100415a);
|
||||
int parameterColumn = 11;
|
||||
int parameterColumn = 7;
|
||||
goTo(address, "Function Signature", parameterColumn);
|
||||
|
||||
search();
|
||||
|
|
|
@ -142,7 +142,7 @@ public class ListingDisplaySearcherTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
// example
|
||||
// dword ptr param, EAX
|
||||
String searchText = "param";
|
||||
String searchText = "local_";
|
||||
SearchOptions options = new SearchOptions(searchText, false, true, false);
|
||||
searcher =
|
||||
new ListingDisplaySearcher(tool, program, startLoc, null, options, TaskMonitor.DUMMY);
|
||||
|
@ -163,7 +163,7 @@ public class ListingDisplaySearcherTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
// example
|
||||
// dword ptr param, EAX
|
||||
String searchText = "param";
|
||||
String searchText = "local_";
|
||||
SearchOptions options = new SearchOptions(searchText, false, false, false);
|
||||
|
||||
searcher =
|
||||
|
@ -187,17 +187,21 @@ public class ListingDisplaySearcherTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
// example
|
||||
// dword ptr param, EAX
|
||||
SearchOptions options = new SearchOptions("param", false, false, false, false, true, true,
|
||||
SearchOptions options = new SearchOptions("local_", false, false, false, false, true, true,
|
||||
false, false, false, true, false, false);
|
||||
searcher =
|
||||
new ListingDisplaySearcher(tool, program, startLoc, null, options, TaskMonitor.DUMMY);
|
||||
|
||||
//set up list of answers
|
||||
ArrayList<Address> startList = new ArrayList<>();
|
||||
startList.add(addr(0x0100416c));
|
||||
startList.add(addr(0x01004186));
|
||||
startList.add(addr(0x01004189));
|
||||
startList.add(addr(0x0100419c));
|
||||
startList.add(addr(0x01004162));
|
||||
startList.add(addr(0x01004169));
|
||||
startList.add(addr(0x0100416f));
|
||||
startList.add(addr(0x01004178));
|
||||
startList.add(addr(0x0100417c));
|
||||
startList.add(addr(0x01004180));
|
||||
startList.add(addr(0x01004196));
|
||||
startList.add(addr(0x010041a1));
|
||||
|
||||
//check that the text is found there in the correct field
|
||||
checkTextFound(startList, OperandFieldLocation.class);
|
||||
|
@ -268,11 +272,9 @@ public class ListingDisplaySearcherTest extends AbstractGhidraHeadedIntegrationT
|
|||
int transactionID = program.startTransaction("test");
|
||||
try {
|
||||
DataType dt = program.getDataTypeManager()
|
||||
.addDataType(struct,
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
floatDt = program.getDataTypeManager()
|
||||
.addDataType(new FloatDataType(),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
.addDataType(new FloatDataType(), DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
listing.createData(addr(0x0100689b), dt);
|
||||
listing.createData(addr(0x0100688c), floatDt);
|
||||
listing.createData(addr(0x01006890), floatDt);
|
||||
|
@ -347,11 +349,9 @@ public class ListingDisplaySearcherTest extends AbstractGhidraHeadedIntegrationT
|
|||
int transactionID = program.startTransaction("test");
|
||||
try {
|
||||
DataType dt = program.getDataTypeManager()
|
||||
.addDataType(struct,
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
floatDt = program.getDataTypeManager()
|
||||
.addDataType(new FloatDataType(),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
.addDataType(new FloatDataType(), DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
listing.createData(addr(0x0100689b), dt);
|
||||
listing.createData(addr(0x0100688c), floatDt);
|
||||
listing.createData(addr(0x01006890), floatDt);
|
||||
|
@ -437,11 +437,9 @@ public class ListingDisplaySearcherTest extends AbstractGhidraHeadedIntegrationT
|
|||
int transactionID = program.startTransaction("test");
|
||||
try {
|
||||
DataType dt = program.getDataTypeManager()
|
||||
.addDataType(struct,
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
floatDt = program.getDataTypeManager()
|
||||
.addDataType(new FloatDataType(),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
.addDataType(new FloatDataType(), DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
listing.createData(addr(0x0100689b), dt);
|
||||
listing.createData(addr(0x0100688c), floatDt);
|
||||
listing.createData(addr(0x01006890), floatDt);
|
||||
|
|
|
@ -492,9 +492,10 @@ public class FunctionEditorModelTest extends AbstractGuiTest {
|
|||
public void testAutoStorageFix() {
|
||||
model.addParameter();
|
||||
ParamInfo paramInfo = model.getParameters().get(0);// param_0@Stack[0x4]:4
|
||||
model.setParameterFormalDataType(paramInfo, IntegerDataType.dataType);
|
||||
model.setUseCustomizeStorage(true);
|
||||
Varnode v = paramInfo.getStorage().getFirstVarnode();
|
||||
assertEquals(1, v.getSize());
|
||||
assertEquals(4, v.getSize());
|
||||
assertEquals(4, v.getOffset());
|
||||
model.setParameterFormalDataType(paramInfo, new Undefined8DataType());
|
||||
assertTrue(model.isValid());
|
||||
|
@ -507,9 +508,9 @@ public class FunctionEditorModelTest extends AbstractGuiTest {
|
|||
public void testAutoStorageFixReg() throws Exception {
|
||||
model.addParameter();
|
||||
ParamInfo paramInfo = model.getParameters().get(0);
|
||||
model.setParameterFormalDataType(paramInfo, new Undefined2DataType());
|
||||
model.setUseCustomizeStorage(true);
|
||||
|
||||
model.setParameterFormalDataType(paramInfo, new Undefined2DataType());
|
||||
assertTrue(model.getStatusText(), model.isValid());
|
||||
Varnode v = paramInfo.getStorage().getFirstVarnode();
|
||||
assertEquals(2, v.getSize());
|
||||
|
@ -1046,7 +1047,7 @@ public class FunctionEditorModelTest extends AbstractGuiTest {
|
|||
param = model.getParameters().get(3);
|
||||
assertEquals("param_2", param.getName());
|
||||
assertTrue(DefaultDataType.dataType.isEquivalent(param.getDataType()));
|
||||
assertEquals("Stack[0xc]:1", param.getStorage().toString());
|
||||
assertEquals("<UNASSIGNED>", param.getStorage().toString());
|
||||
|
||||
model.setParameterFormalDataType(param, struct);
|
||||
|
||||
|
@ -1156,7 +1157,7 @@ public class FunctionEditorModelTest extends AbstractGuiTest {
|
|||
param = model.getParameters().get(3);
|
||||
assertEquals("param_2", param.getName());
|
||||
assertTrue(DefaultDataType.dataType.isEquivalent(param.getDataType()));
|
||||
assertEquals("R9B:1", param.getStorage().toString());
|
||||
assertEquals("<UNASSIGNED>", param.getStorage().toString());
|
||||
|
||||
model.setParameterFormalDataType(param, struct);
|
||||
|
||||
|
|
|
@ -24,19 +24,17 @@ import org.junit.Test;
|
|||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
||||
import ghidra.app.plugin.core.analysis.ConstantPropagationContextEvaluator;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.mem.MemoryConflictException;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.program.util.SymbolicPropogator.Value;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
|
@ -99,7 +97,8 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
|
||||
builder = new ProgramBuilder("thunk", ProgramBuilder._MIPS);
|
||||
|
||||
builder.setBytes("0x1000", "3c 1c 00 14 27 9c b3 34 03 99 e0 21 27 bd ff e0" +
|
||||
builder.setBytes("0x1000",
|
||||
"3c 1c 00 14 27 9c b3 34 03 99 e0 21 27 bd ff e0" +
|
||||
"af bc 00 10 3c 07 12 34 24 e7 45 67 ac a7 00 10" +
|
||||
"3c 06 0a 0b 24 c6 0c 0d ae 06 00 10 8e 11 00 10" +
|
||||
"8c b1 00 10 8f b1 00 10 8e 51 00 10 ae 53 00 10" +
|
||||
|
@ -165,65 +164,68 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
String loc = instr.getMinAddress().toString();
|
||||
Varnode registerVarnode;
|
||||
|
||||
switch(loc) {
|
||||
switch (loc) {
|
||||
case "00001010":
|
||||
// gp should be 0x14 + t9 offset space
|
||||
registerVarnode = regValue(context,"gp");
|
||||
registerVarnode = regValue(context, "gp");
|
||||
assertTrue("symbolic value", context.isSymbol(registerVarnode));
|
||||
assertEquals("(t9, 0x13b334, 4)", registerVarnode.toString());
|
||||
// S3 should be S3 at entry
|
||||
registerVarnode = regValue(context,"s3");
|
||||
registerVarnode = regValue(context, "s3");
|
||||
assertTrue("register s3", context.isRegister(registerVarnode));
|
||||
assertEquals("s3", context.getRegister(registerVarnode).getName());
|
||||
break;
|
||||
case "0000102c":
|
||||
// s1 restored from space 0x10(s0) space
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
assertTrue("constant value", registerVarnode.isConstant());
|
||||
assertEquals("(const, 0xa0b0c0d, 4)", registerVarnode.toString());
|
||||
break;
|
||||
case "00001030":
|
||||
// s1 restored from space 0x10(a1) space
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
assertTrue("symbolic value", registerVarnode.isConstant());
|
||||
assertEquals("(const, 0x12344567, 4)", registerVarnode.toString());
|
||||
break;
|
||||
case "00001034":
|
||||
// s1 restored from space 0x10(sp) space
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
assertTrue("symbolic value", context.isSymbol(registerVarnode));
|
||||
assertEquals("(t9, 0x13b334, 4)", registerVarnode.toString());
|
||||
break;
|
||||
case "00001038":
|
||||
// s1 restored from space 0x10(s2) space
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
//assertTrue("Still s1", registerVarnode.isRegister());
|
||||
boolean isBad = false;
|
||||
try {
|
||||
context.getConstant(registerVarnode, null);
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
isBad = true;
|
||||
}
|
||||
assertTrue("Can get constant value", isBad);
|
||||
break;
|
||||
case "00001040":
|
||||
// s1 restored from space 0x10(s2) space - stored a3
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
assertTrue("register s3", registerVarnode.isRegister());
|
||||
assertEquals("s3", context.getRegister(registerVarnode).getName());
|
||||
|
||||
Address lastSetLocation = context.getLastSetLocation(context.getRegisterVarnode(context.getRegister("s2")), null);
|
||||
Address lastSetLocation = context.getLastSetLocation(
|
||||
context.getRegisterVarnode(context.getRegister("s2")), null);
|
||||
assertEquals("s2 last set", null, lastSetLocation);
|
||||
break;
|
||||
case "00001048":
|
||||
// s1 restored from space 0x10(s2) after s2 has been set again
|
||||
// it should no longer be s3 that was stored in another s2 relative space
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
//assertTrue("Still s1", registerVarnode.isRegister());
|
||||
isBad = false;
|
||||
try {
|
||||
context.getConstant(registerVarnode, null);
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
isBad = true;
|
||||
}
|
||||
assertTrue("Can get constant value", isBad);
|
||||
|
@ -231,28 +233,31 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
case "0000104c":
|
||||
// s1 restored from space 0x10(s2) after s2 has been set again
|
||||
// it should no longer be s3 that was stored in another s2 relative space
|
||||
registerVarnode = regValue(context,"s2");
|
||||
registerVarnode = regValue(context, "s2");
|
||||
//assertTrue("Still s2", registerVarnode.isRegister());
|
||||
isBad = false;
|
||||
try {
|
||||
context.getConstant(registerVarnode, null);
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
isBad = true;
|
||||
}
|
||||
assertTrue("Can get constant value", isBad);
|
||||
lastSetLocation = context.getLastSetLocation(context.getRegisterVarnode(context.getRegister("s2")), null);
|
||||
lastSetLocation = context.getLastSetLocation(
|
||||
context.getRegisterVarnode(context.getRegister("s2")), null);
|
||||
assertEquals("s2 last set", 0x104fL, lastSetLocation.getOffset());
|
||||
break;
|
||||
case "00001054":
|
||||
// s1 restored from space 0x10(s2) after s2 has been set again
|
||||
// it should no longer be s3 that was stored in another s2 relative space
|
||||
registerVarnode = regValue(context,"s1");
|
||||
registerVarnode = regValue(context, "s1");
|
||||
//assertTrue("Still s1", registerVarnode.isRegister());
|
||||
//assertEquals(context.getRegister(registerVarnode).getName(),"s1");
|
||||
isBad = false;
|
||||
try {
|
||||
context.getConstant(registerVarnode, null);
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
isBad = true;
|
||||
}
|
||||
assertTrue("Can get constant value", isBad);
|
||||
|
@ -288,8 +293,7 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
builder.setBytes("0x00040000",
|
||||
"55 48 89 e5 bf 00 01 04 00 b8 00 00 00 00 66 67 e8 2a 00 c9 c3");
|
||||
|
||||
builder.setBytes("0x00040100",
|
||||
"53 54 52 49 4e 47 20 25 73 20 25 73 0a 00 00");
|
||||
builder.setBytes("0x00040100", "53 54 52 49 4e 47 20 25 73 20 25 73 0a 00 00");
|
||||
|
||||
builder.disassemble("0x00040000", 21);
|
||||
|
||||
|
@ -346,35 +350,35 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
|
||||
String ovBlockName = "textov";
|
||||
|
||||
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName,"0x400000",0x10000);
|
||||
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName, "0x400000", 0x10000);
|
||||
|
||||
builder.setBytes(textBlock.getStart().toString(),
|
||||
"fd 7b bf a9 fd 03 00 91 60 00 00 d0 01 00 24 91 60 00 00 d0 00 40 24 91 e2 03 01 aa e1 15 80 52 05 00 00 94 21 00 80 d2 40 00 80 d2 02 00 00 94 c0 03 5f d6 c0 03 5f d6");
|
||||
|
||||
builder.setBytes(ovBlockName+":"+"0x0040e900",
|
||||
builder.setBytes(ovBlockName + ":" + "0x0040e900",
|
||||
"53 74 72 69 6e 67 50 61 72 61 6d 31 00 00 00 00 53 74 72 69 6e 67 50 61 72 61 6d 32 00 00 00 00");
|
||||
|
||||
builder.disassemble(textBlock.getStart().toString(), 16*4);
|
||||
builder.disassemble(textBlock.getStart().toString(), 16 * 4);
|
||||
|
||||
analyzer = new ConstantPropagationAnalyzer();
|
||||
|
||||
program = builder.getProgram();
|
||||
program.startTransaction("Test");
|
||||
Address codeStart = addr(ovBlockName+":"+"0x00400000");
|
||||
Address codeStart = addr(ovBlockName + ":" + "0x00400000");
|
||||
Listing listing = program.getListing();
|
||||
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16*4));
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16 * 4));
|
||||
analyze(addressSet);
|
||||
|
||||
Instruction instr;
|
||||
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(20));
|
||||
instr = listing.getInstructionAt(addr(ovBlockName + ":" + "0x00400000").add(20));
|
||||
assertNoOperandReference(1, instr);
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e910"));
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName + ":" + "0x0040e910"));
|
||||
|
||||
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(24));
|
||||
instr = listing.getInstructionAt(addr(ovBlockName + ":" + "0x00400000").add(24));
|
||||
assertNoOperandReference(1, instr);
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e900"));
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName + ":" + "0x0040e900"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -386,7 +390,7 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
|
||||
// Same as above test
|
||||
|
||||
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName,"0x400000",0x1000);
|
||||
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName, "0x400000", 0x1000);
|
||||
|
||||
builder.setBytes(textBlock.getStart().toString(),
|
||||
"fd 7b bf a9 fd 03 00 91 60 00 00 d0 01 00 24 91 60 00 00 d0 00 40 24 91 e2 03 01 aa e1 15 80 52 05 00 00 94 21 00 80 d2 40 00 80 d2 02 00 00 94 c0 03 5f d6 c0 03 5f d6");
|
||||
|
@ -394,30 +398,29 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
builder.setBytes("0x0040e900",
|
||||
"53 74 72 69 6e 67 50 61 72 61 6d 31 00 00 00 00 53 74 72 69 6e 67 50 61 72 61 6d 32 00 00 00 00");
|
||||
|
||||
builder.disassemble(textBlock.getStart().toString(), 16*4);
|
||||
builder.disassemble(textBlock.getStart().toString(), 16 * 4);
|
||||
|
||||
analyzer = new ConstantPropagationAnalyzer();
|
||||
|
||||
program = builder.getProgram();
|
||||
program.startTransaction("Test");
|
||||
Address codeStart = addr(ovBlockName+":"+"0x00400000");
|
||||
Address codeStart = addr(ovBlockName + ":" + "0x00400000");
|
||||
Listing listing = program.getListing();
|
||||
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16*4));
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16 * 4));
|
||||
analyze(addressSet);
|
||||
|
||||
Instruction instr;
|
||||
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(20));
|
||||
instr = listing.getInstructionAt(addr(ovBlockName + ":" + "0x00400000").add(20));
|
||||
assertNoOperandReference(1, instr);
|
||||
assertOperandReferenceTo(0, instr, addr("0x0040e910"));
|
||||
|
||||
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(24));
|
||||
instr = listing.getInstructionAt(addr(ovBlockName + ":" + "0x00400000").add(24));
|
||||
assertNoOperandReference(1, instr);
|
||||
assertOperandReferenceTo(0, instr, addr("0x0040e900"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOverlayReferencesToSplit_AARCH64() throws Exception {
|
||||
|
||||
|
@ -427,16 +430,20 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
|
||||
// Same as above test
|
||||
|
||||
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName,"0x400000",0x1000);
|
||||
MemoryBlock textBlock = builder.createOverlayMemory(ovBlockName, "0x400000", 0x1000);
|
||||
|
||||
builder.setBytes(textBlock.getStart().toString(),
|
||||
"fd 7b bf a9 fd 03 00 91 60 00 00 d0 01 00 24 91 60 00 00 d0 00 40 24 91 e2 03 01 aa e1 15 80 52 05 00 00 94 21 00 80 d2 40 00 80 d2 02 00 00 94 c0 03 5f d6 c0 03 5f d6");
|
||||
|
||||
|
||||
builder.withTransaction(() -> {
|
||||
try {
|
||||
MemoryBlock dataBlock = builder.getProgram().getMemory().createInitializedBlock(ovBlockName, textBlock.getStart().getAddressSpace().getAddressInThisSpaceOnly(0x0040e900), 0x100L, (byte) 0, TaskMonitor.DUMMY,
|
||||
false);
|
||||
MemoryBlock dataBlock = builder.getProgram()
|
||||
.getMemory()
|
||||
.createInitializedBlock(ovBlockName,
|
||||
textBlock.getStart()
|
||||
.getAddressSpace()
|
||||
.getAddressInThisSpaceOnly(0x0040e900),
|
||||
0x100L, (byte) 0, TaskMonitor.DUMMY, false);
|
||||
|
||||
builder.setBytes(dataBlock.getStart().toString(),
|
||||
"53 74 72 69 6e 67 50 61 72 61 6d 31 00 00 00 00 53 74 72 69 6e 67 50 61 72 61 6d 32 00 00 00 00");
|
||||
|
@ -446,31 +453,29 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
}
|
||||
});
|
||||
|
||||
builder.disassemble(textBlock.getStart().toString(), 16*4);
|
||||
builder.disassemble(textBlock.getStart().toString(), 16 * 4);
|
||||
|
||||
analyzer = new ConstantPropagationAnalyzer();
|
||||
|
||||
program = builder.getProgram();
|
||||
program.startTransaction("Test");
|
||||
Address codeStart = addr(ovBlockName+":"+"0x00400000");
|
||||
Address codeStart = addr(ovBlockName + ":" + "0x00400000");
|
||||
Listing listing = program.getListing();
|
||||
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16*4));
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(16 * 4));
|
||||
analyze(addressSet);
|
||||
|
||||
Instruction instr;
|
||||
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(20));
|
||||
instr = listing.getInstructionAt(addr(ovBlockName + ":" + "0x00400000").add(20));
|
||||
assertNoOperandReference(1, instr);
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e910"));
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName + ":" + "0x0040e910"));
|
||||
|
||||
instr = listing.getInstructionAt(addr(ovBlockName+":"+"0x00400000").add(24));
|
||||
instr = listing.getInstructionAt(addr(ovBlockName + ":" + "0x00400000").add(24));
|
||||
assertNoOperandReference(1, instr);
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName+":"+"0x0040e900"));
|
||||
assertOperandReferenceTo(0, instr, addr(ovBlockName + ":" + "0x0040e900"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testPIC_Call_X86_64() throws Exception {
|
||||
|
||||
|
@ -489,8 +494,7 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
builder.setBytes("0x140020110",
|
||||
"48 83 ec 28 e8 00 00 00 00 8f c3 48 8d 43 e0 ff d0 48 83 c4 28 c3");
|
||||
|
||||
builder.setBytes("0x1400200f9",
|
||||
"15 02 2f 00 00 89 05 e8 b9 00 00 48 83 c4 38");
|
||||
builder.setBytes("0x1400200f9", "15 02 2f 00 00 89 05 e8 b9 00 00 48 83 c4 38");
|
||||
|
||||
builder.disassemble("0x140020110", 21);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import generic.test.AbstractGenericTest;
|
|||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.TerminatedStringDataType;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Data;
|
||||
|
@ -132,6 +133,60 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
|||
fullSignature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUseStandardReplacements2() throws Exception {
|
||||
|
||||
//
|
||||
// Mangled: _ZN7Greeter5greetENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
|
||||
//
|
||||
// Demangled: undefined Greeter::greet(std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>)
|
||||
//
|
||||
// Replaced: undefined Greeter::greet(std::string)
|
||||
//
|
||||
String mangled = "_ZN7Greeter5greetENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||
options.setUseStandardReplacements(true);
|
||||
DemangledFunction dobj = (DemangledFunction) demangler.demangle(mangled, options);
|
||||
assertNotNull(dobj);
|
||||
|
||||
String signature = dobj.getSignature();
|
||||
assertEquals("undefined Greeter::greet(std::string)", signature);
|
||||
|
||||
DemangledParameter demangledParameter = dobj.getParameters().get(0);
|
||||
DemangledDataType type = demangledParameter.getType();
|
||||
DataType dt = type.getDataType(program.getDataTypeManager());
|
||||
assertTrue(dt.isNotYetDefined());
|
||||
//@formatter:off
|
||||
assertEquals("/Demangler/std/string\n" +
|
||||
"pack(disabled)\n" +
|
||||
"Structure string {\n" +
|
||||
"}\n" +
|
||||
"Length: 0 Alignment: 1\n", dt.toString());
|
||||
//@formatter:on
|
||||
|
||||
//
|
||||
// Now disable demangled string replacement
|
||||
//
|
||||
options.setUseStandardReplacements(false);
|
||||
dobj = (DemangledFunction) demangler.demangle(mangled, options);
|
||||
assertNotNull(dobj);
|
||||
|
||||
String fullSignature = dobj.getSignature();
|
||||
assertEquals(
|
||||
"undefined Greeter::greet(std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>)",
|
||||
fullSignature);
|
||||
|
||||
demangledParameter = dobj.getParameters().get(0);
|
||||
type = demangledParameter.getType();
|
||||
dt = type.getDataType(program.getDataTypeManager());
|
||||
assertEquals("typedef basic_string undefined", dt.toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangleOnlyKnownPatterns_True() throws Exception {
|
||||
|
||||
|
|
|
@ -2470,16 +2470,6 @@ public class FunctionDB extends DatabaseObject implements Function {
|
|||
return thunkedFunction.getSignatureSource();
|
||||
}
|
||||
|
||||
// Force DEFAULT source if any param has unassigned storage
|
||||
if (!getReturn().isValid()) {
|
||||
return SourceType.DEFAULT;
|
||||
}
|
||||
for (Parameter param : getParameters()) {
|
||||
if (!param.isValid()) {
|
||||
return SourceType.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return getStoredSignatureSource();
|
||||
}
|
||||
finally {
|
||||
|
|
|
@ -23,8 +23,7 @@ import java.util.ArrayList;
|
|||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.protorules.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
|
@ -85,6 +84,7 @@ public class ParamListStandard implements ParamList {
|
|||
*/
|
||||
public int assignAddressFallback(StorageClass resource, DataType tp, boolean matchExact,
|
||||
int[] status, ParameterPieces param) {
|
||||
|
||||
for (ParamEntry element : entry) {
|
||||
int grp = element.getGroup();
|
||||
if (status[grp] < 0) {
|
||||
|
@ -133,6 +133,12 @@ public class ParamListStandard implements ParamList {
|
|||
if (dt.isZeroLength()) {
|
||||
return AssignAction.NO_ASSIGNMENT;
|
||||
}
|
||||
if (dt == DataType.DEFAULT) {
|
||||
return AssignAction.NO_ASSIGNMENT;
|
||||
}
|
||||
if (dt instanceof TypeDef td && td.getBaseDataType() == DataType.DEFAULT) {
|
||||
return AssignAction.NO_ASSIGNMENT;
|
||||
}
|
||||
for (ModelRule modelRule : modelRules) {
|
||||
int responseCode = modelRule.assignAddress(dt, proto, pos, dtManager, status, res);
|
||||
if (responseCode != AssignAction.FAIL) {
|
||||
|
|
|
@ -239,6 +239,10 @@ public class PrototypeModel {
|
|||
* i.e. {@link AutoParameterType#RETURN_STORAGE_PTR}, this routine will not pass back
|
||||
* the storage location of the pointer, but will typically pass
|
||||
* back the location of the normal return register which holds a copy of the pointer.
|
||||
* <br>
|
||||
* Note: storage will not be assigned to the {@link DataType#DEFAULT default undefined} datatype
|
||||
* or zero-length datatype.
|
||||
*
|
||||
* @param dataType first parameter dataType or null for an undefined type.
|
||||
* @param program is the Program
|
||||
* @return return location or {@link VariableStorage#UNASSIGNED_STORAGE} if
|
||||
|
@ -259,10 +263,22 @@ public class PrototypeModel {
|
|||
* Get the preferred parameter location for a new parameter which will appended
|
||||
* to the end of an existing set of params. If existing parameters use custom
|
||||
* storage, this method should not be used.
|
||||
* <br>
|
||||
* Note: storage will not be assigned to the {@link DataType#DEFAULT default undefined} datatype,
|
||||
* zero-length datatype, or any subsequent parameter following such a parameter.
|
||||
* <br>
|
||||
* Warning: The use of this method with a null {@code params} argument, or incorrect
|
||||
* datatypes, is highly discouraged since it will produce inaccurate results.
|
||||
* It is recommended that a complete function signature be used in
|
||||
* conjunction with the {@link #getStorageLocations(Program, DataType[], boolean)}
|
||||
* method. Parameter storage allocation may be affected by the return datatype
|
||||
* specified (e.g., hidden return storage parameter).
|
||||
*
|
||||
* @param params existing set parameters to which the next parameter will
|
||||
* be appended. (may be null)
|
||||
* be appended (may be null). Element-0 corresponds to the return datatype.
|
||||
* @param dataType dataType associated with next parameter location or null
|
||||
* for a default undefined type.
|
||||
* for a default undefined type. If null the speculative first parameter storage
|
||||
* is returned.
|
||||
* @param program is the Program
|
||||
* @return next parameter location or {@link VariableStorage#UNASSIGNED_STORAGE} if
|
||||
* unable to determine suitable location
|
||||
|
@ -276,9 +292,24 @@ public class PrototypeModel {
|
|||
* Get the preferred parameter location for a specified index,
|
||||
* which will be added/inserted within the set of existing function params.
|
||||
* If existing parameters use custom storage, this method should not be used.
|
||||
* @param argIndex is the index
|
||||
* <br>
|
||||
* Note: storage will not be assigned to the {@link DataType#DEFAULT default undefined} datatype,
|
||||
* zero-length datatype, or any subsequent parameter following such a parameter.
|
||||
* <br>
|
||||
* Warning: The use of this method with a null {@code params} argument, or incorrect
|
||||
* datatypes, is highly discouraged since it will produce inaccurate results.
|
||||
* It is recommended that a complete function signature be used in
|
||||
* conjunction with the {@link #getStorageLocations(Program, DataType[], boolean)}
|
||||
* method. Parameter storage allocation may be affected by the return datatype
|
||||
* specified (e.g., hidden return storage parameter).
|
||||
*
|
||||
* @param argIndex is the index (0: return storage, 1..n: parameter storage)
|
||||
* @param params existing set parameters to which the parameter specified by
|
||||
* argIndex will be added/inserted be appended (may be null).
|
||||
* argIndex will be added/inserted be appended. Element-0 corresponds to the return
|
||||
* datatype. Parameter elements prior to the argIndex are required for an accurate
|
||||
* storage determination to be made. Any preceeding parameters not specified will be assumed
|
||||
* as a 1-byte integer type which could cause an erroneous storage result to be returned.
|
||||
* A null params list will cause all preceeding params to be assumed in a similar fashion.
|
||||
* @param dataType dataType associated with next parameter location or null
|
||||
* for a default undefined type.
|
||||
* @param program is the Program
|
||||
|
@ -302,7 +333,7 @@ public class PrototypeModel {
|
|||
arr[i + 1] = params[i].getDataType(); // Copy in current types if we have them
|
||||
}
|
||||
else {
|
||||
arr[i + 1] = DataType.DEFAULT; // Otherwise assume default (integer) type
|
||||
arr[i + 1] = Undefined1DataType.dataType; // Otherwise assume 1-byte (integer) type
|
||||
}
|
||||
}
|
||||
arr[argIndex + 1] = dataType;
|
||||
|
@ -353,6 +384,10 @@ public class PrototypeModel {
|
|||
* input parameters, if needed. In this case, the dataTypes array should not include explicit entries for
|
||||
* these parameters. If addAutoParams is false, the dataTypes array is assumed to already contain explicit
|
||||
* entries for any of these parameters.
|
||||
* <br>
|
||||
* Note: storage will not be assigned to the {@link DataType#DEFAULT default undefined} datatype
|
||||
* or zero-length datatypes or any subsequent parameter following such a parameter.
|
||||
*
|
||||
* @param program is the Program
|
||||
* @param dataTypes return/parameter datatypes (first element is always the return datatype,
|
||||
* i.e., minimum array length is 1)
|
||||
|
|
|
@ -210,11 +210,12 @@ public class LocalSymbolMap {
|
|||
pcaddr = pcaddr.subtractWrap(1);
|
||||
|
||||
List<HighSymbol> paramList = new ArrayList<>();
|
||||
boolean internalInvalid = false;
|
||||
for (int i = 0; i < p.length; ++i) {
|
||||
Parameter var = p[i];
|
||||
if (!var.isValid()) {
|
||||
// TODO: exclude parameters which don't have valid storage ??
|
||||
continue;
|
||||
internalInvalid = true;
|
||||
break;
|
||||
}
|
||||
DataType dt = var.getDataType();
|
||||
String name = var.getName();
|
||||
|
@ -243,6 +244,12 @@ public class LocalSymbolMap {
|
|||
paramSymbol.setNameLock(namelock);
|
||||
paramSymbol.setTypeLock(lock);
|
||||
}
|
||||
if (internalInvalid) {
|
||||
// Can only send down a partial prototype. Let decompiler try to recover the whole.
|
||||
for (HighSymbol paramSymbol : paramList) {
|
||||
paramSymbol.setTypeLock(false);
|
||||
}
|
||||
}
|
||||
|
||||
paramSymbols = new HighSymbol[paramList.size()];
|
||||
paramList.toArray(paramSymbols);
|
||||
|
|
|
@ -1153,10 +1153,7 @@ public class PcodeDataTypeManager {
|
|||
private void generateCoreTypes() {
|
||||
voidDt = new VoidDataType(progDataTypes);
|
||||
coreBuiltin = new HashMap<Long, TypeMap>();
|
||||
TypeMap type = new TypeMap(DataType.DEFAULT, "undefined", "unknown", false, false,
|
||||
DEFAULT_DECOMPILER_ID);
|
||||
coreBuiltin.put(type.id, type);
|
||||
type = new TypeMap(displayLanguage, VoidDataType.dataType, "void", false, false,
|
||||
TypeMap type = new TypeMap(displayLanguage, VoidDataType.dataType, "void", false, false,
|
||||
builtInDataTypes);
|
||||
coreBuiltin.put(type.id, type);
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ public class CompareFunctionsDecompilerViewTest extends AbstractGhidraHeadedInte
|
|||
FunctionManager functionManager = program1.getFunctionManager();
|
||||
fun1 = functionManager.getFunctionAt(addr(0x01002cf5));
|
||||
fun2 = functionManager.getFunctionAt(addr(0x0100415a));
|
||||
|
||||
}
|
||||
|
||||
private Address addr(long offset) {
|
||||
|
@ -69,6 +68,8 @@ public class CompareFunctionsDecompilerViewTest extends AbstractGhidraHeadedInte
|
|||
|
||||
@Test
|
||||
public void testDecompDifView() throws Exception {
|
||||
assertFalse(program1.isClosed());
|
||||
|
||||
Set<Function> functions = Set.of(fun1, fun2);
|
||||
compareFunctions(functions);
|
||||
|
||||
|
@ -76,13 +77,12 @@ public class CompareFunctionsDecompilerViewTest extends AbstractGhidraHeadedInte
|
|||
waitForComponentProvider(FunctionComparisonProvider.class);
|
||||
|
||||
checkFunctions(provider, LEFT, fun1, fun1, fun2);
|
||||
DecompilerCodeComparisonPanel panel =
|
||||
(DecompilerCodeComparisonPanel) provider
|
||||
DecompilerCodeComparisonPanel panel = (DecompilerCodeComparisonPanel) provider
|
||||
.getCodeComparisonPanelByName(DecompilerCodeComparisonPanel.NAME);
|
||||
|
||||
waitForDecompiler(panel);
|
||||
assertHasLines(panel.getLeftPanel(), 28);
|
||||
assertHasLines(panel.getRightPanel(), 23);
|
||||
assertHasLines(panel.getRightPanel(), 22);
|
||||
}
|
||||
|
||||
private void checkFunctions(FunctionComparisonProvider provider, Side side,
|
||||
|
@ -113,8 +113,7 @@ public class CompareFunctionsDecompilerViewTest extends AbstractGhidraHeadedInte
|
|||
}
|
||||
|
||||
private Program buildTestProgram() throws Exception {
|
||||
ClassicSampleX86ProgramBuilder builder =
|
||||
new ClassicSampleX86ProgramBuilder("Test", false);
|
||||
ClassicSampleX86ProgramBuilder builder = new ClassicSampleX86ProgramBuilder("Test", false);
|
||||
return builder.getProgram();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue