Merge remote-tracking branch 'origin/GP-4886_ghidra1_UnassignedStorageForDefaultDatatype'

This commit is contained in:
Ryan Kurtz 2024-12-06 07:45:28 -05:00
commit 4f79536a50
20 changed files with 454 additions and 358 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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,

View file

@ -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) {

View file

@ -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;
}

View file

@ -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) {

View file

@ -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);

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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 {

View file

@ -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 {

View file

@ -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) {

View file

@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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();
}