Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2022-03-16 13:20:23 -04:00
commit d4160bd88c
6 changed files with 123 additions and 136 deletions

View file

@ -323,6 +323,7 @@ public class GraphClassesScript extends GhidraScript {
.defaultVertexColor(WebColors.PURPLE) .defaultVertexColor(WebColors.PURPLE)
.defaultEdgeColor(WebColors.PURPLE) .defaultEdgeColor(WebColors.PURPLE)
.defaultLayoutAlgorithm("Compact Hierarchical") .defaultLayoutAlgorithm("Compact Hierarchical")
.maxNodeCount(1000)
.build(); .build();
display.setGraph(graph, graphOptions, display.setGraph(graph, graphOptions,

View file

@ -57,7 +57,6 @@ import ghidra.test.TestEnv;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.table.GhidraProgramTableModel; import ghidra.util.table.GhidraProgramTableModel;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest { public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
@ -100,8 +99,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
env.dispose(); env.dispose();
} }
/*******************************************************/
@Test @Test
public void testStructures() throws Exception { public void testStructures() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -187,15 +184,7 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
for (int element : TYPES) { for (int element : TYPES) {
int txId = program.startTransaction("TEST"); tx(program, () -> program.getListing().setComment(addr, element, "Test" + element));
try {
program.getListing().setComment(addr, element, "Test" + element);
}
finally {
program.endTransaction(txId, true);
}
program.flushEvents();
sendProgramLocation(addr, element); sendProgramLocation(addr, element);
@ -368,8 +357,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(browser.goToField(addr, EolCommentFieldFactory.FIELD_NAME, 0, 0)); assertTrue(browser.goToField(addr, EolCommentFieldFactory.FIELD_NAME, 0, 0));
} }
/*******************************************************/
@Test @Test
public void testSetAll() throws Exception { public void testSetAll() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -405,8 +392,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(REPEAT, cu.getComment(CodeUnit.REPEATABLE_COMMENT)); assertEquals(REPEAT, cu.getComment(CodeUnit.REPEATABLE_COMMENT));
} }
/*******************************************************/
@Test @Test
public void testApplyButton() throws Exception { public void testApplyButton() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -421,8 +406,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(!commentsDialog.isVisible()); assertTrue(!commentsDialog.isVisible());
} }
/*******************************************************/
@Test @Test
public void testModify() throws Exception { public void testModify() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -436,8 +419,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(PRE_U, cu.getComment(CodeUnit.PRE_COMMENT)); assertEquals(PRE_U, cu.getComment(CodeUnit.PRE_COMMENT));
} }
/*******************************************************/
@Test @Test
public void testPromptForSaveChangesYes() throws Exception { public void testPromptForSaveChangesYes() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -544,8 +525,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
} }
} }
/*******************************************************/
@Test @Test
public void testReallyBigComment() throws Exception { public void testReallyBigComment() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -563,8 +542,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(comment, cu.getComment(CodeUnit.PRE_COMMENT)); assertEquals(comment, cu.getComment(CodeUnit.PRE_COMMENT));
} }
/*******************************************************/
@Test @Test
public void testNavigationFromSymbol() throws Exception { public void testNavigationFromSymbol() throws Exception {
openX86ProgramInTool(); openX86ProgramInTool();
@ -685,7 +662,7 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
Address destAddr = addr(0x01008394); Address destAddr = addr(0x01008394);
assertEquals(destAddr, browser.getCurrentLocation().getAddress()); assertEquals(destAddr, browser.getCurrentLocation().getAddress());
getProviders()[0].closeComponent(); runSwing(() -> getProviders()[0].closeComponent());
assertEquals(destAddr, browser.getCurrentLocation().getAddress()); assertEquals(destAddr, browser.getCurrentLocation().getAddress());
} }
@ -697,7 +674,6 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
open8051Program(); open8051Program();
AddressFactory af = program.getAddressFactory(); AddressFactory af = program.getAddressFactory();
AddressSpace codeSpace = af.getAddressSpace("CODE");
AddressSpace extmemSpace = af.getAddressSpace("EXTMEM"); AddressSpace extmemSpace = af.getAddressSpace("EXTMEM");
Address addr = extmemSpace.getAddress(0); Address addr = extmemSpace.getAddress(0);
@ -722,9 +698,7 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(spaceComment, cu.getComment(CodeUnit.PLATE_COMMENT)); assertEquals(spaceComment, cu.getComment(CodeUnit.PLATE_COMMENT));
} }
/*******************************************************/ /*
/**
* Test that when using the GoTo service the edit comments action * Test that when using the GoTo service the edit comments action
* is enabled. * is enabled.
* *
@ -837,13 +811,13 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
int transactionID = program.startTransaction("Test"); int transactionID = program.startTransaction("Test");
try { try {
memory.createInitializedBlock("test1", addr(0x1006000), 0x1000, (byte) 0, memory.createInitializedBlock("test1", addr(0x1006000), 0x1000, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false); TaskMonitor.DUMMY, false);
memory.createInitializedBlock("test2", addr(0x1008000), 0x1000, (byte) 0, memory.createInitializedBlock("test2", addr(0x1008000), 0x1000, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false); TaskMonitor.DUMMY, false);
memory.createInitializedBlock("test3", addr(0x100b000), 0x1000, (byte) 0, memory.createInitializedBlock("test3", addr(0x100b000), 0x1000, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false); TaskMonitor.DUMMY, false);
memory.createInitializedBlock("test4", addr(0xf0000000), 0x2000, (byte) 0, memory.createInitializedBlock("test4", addr(0xf0000000), 0x2000, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false); TaskMonitor.DUMMY, false);
SymbolTable st = program.getSymbolTable(); SymbolTable st = program.getSymbolTable();
Namespace ns = st.createNameSpace(null, "Deadpool", SourceType.USER_DEFINED); Namespace ns = st.createNameSpace(null, "Deadpool", SourceType.USER_DEFINED);
@ -854,8 +828,11 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
program.endTransaction(transactionID, true); program.endTransaction(transactionID, true);
} }
// write the file to the project to test external navigation for comment annotation // write the file to the project to test external navigation for comment annotation
env.getProject().getProjectData().getRootFolder().createFile("Test", program, env.getProject()
TaskMonitor.DUMMY); .getProjectData()
.getRootFolder()
.createFile("Test", program,
TaskMonitor.DUMMY);
env.showTool(program); env.showTool(program);
} }
@ -871,9 +848,9 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
int transactionID = program.startTransaction("Test"); int transactionID = program.startTransaction("Test");
try { try {
memory.createInitializedBlock("EEPROM", extmemSpace.getAddress(0), 0x100, (byte) 0, memory.createInitializedBlock("EEPROM", extmemSpace.getAddress(0), 0x100, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false); TaskMonitor.DUMMY, false);
memory.createInitializedBlock("CODE", codeSpace.getAddress(0), 0x100, (byte) 0, memory.createInitializedBlock("CODE", codeSpace.getAddress(0), 0x100, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false); TaskMonitor.DUMMY, false);
} }
finally { finally {
program.endTransaction(transactionID, true); program.endTransaction(transactionID, true);
@ -884,23 +861,23 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
} }
private Reference addReference(long fromOffset, long toOffset, RefType refType) { private Reference addReference(long fromOffset, long toOffset, RefType refType) {
int transactionID = program.startTransaction("Add Reference");
try { return modifyProgram(program, p -> {
return program.getReferenceManager().addMemoryReference(addr(fromOffset), return p.getReferenceManager()
addr(toOffset), refType, SourceType.USER_DEFINED, 0); .addMemoryReference(addr(fromOffset),
} addr(toOffset), refType, SourceType.USER_DEFINED, 0);
finally { });
program.endTransaction(transactionID, true);
}
} }
private Function addFunction(String name, long functionEntry, int size) throws Exception { private Function addFunction(String name, long functionEntry, int size) throws Exception {
int transactionID = program.startTransaction("Add Function");
try { return modifyProgram(program, p -> {
Function function = Function function =
program.getFunctionManager().createFunction(name, addr(functionEntry), p.getFunctionManager()
new AddressSet(addr(functionEntry), addr(functionEntry + size - 1)), .createFunction(name, addr(functionEntry),
SourceType.USER_DEFINED); new AddressSet(addr(functionEntry), addr(functionEntry + size - 1)),
SourceType.USER_DEFINED);
ReturnParameterImpl returnParam = ReturnParameterImpl returnParam =
new ReturnParameterImpl(IntegerDataType.dataType, program); new ReturnParameterImpl(IntegerDataType.dataType, program);
ParameterImpl param1 = new ParameterImpl("p1", ByteDataType.dataType, program); ParameterImpl param1 = new ParameterImpl("p1", ByteDataType.dataType, program);
@ -912,10 +889,7 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.USER_DEFINED, FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, true, SourceType.USER_DEFINED,
param1, param2); param1, param2);
return function; return function;
} });
finally {
program.endTransaction(transactionID, true);
}
} }
private void configureTool(PluginTool pluginTool) throws Exception { private void configureTool(PluginTool pluginTool) throws Exception {
@ -961,8 +935,7 @@ public class CommentsPluginTest extends AbstractGhidraHeadedIntegrationTest {
private void resetFormatOptions(CodeBrowserPlugin codeBrowserPlugin) { private void resetFormatOptions(CodeBrowserPlugin codeBrowserPlugin) {
Options fieldOptions = codeBrowserPlugin.getFormatManager().getFieldOptions(); Options fieldOptions = codeBrowserPlugin.getFormatManager().getFieldOptions();
List<String> names = fieldOptions.getOptionNames(); List<String> names = fieldOptions.getOptionNames();
for (int i = 0; i < names.size(); i++) { for (String name : names) {
String name = names.get(i);
if (!name.startsWith("Format Code")) { if (!name.startsWith("Format Code")) {
continue; continue;
} }

View file

@ -27,11 +27,9 @@ import ghidra.program.model.block.CodeBlock;
import ghidra.program.model.block.IsolatedEntrySubModel; import ghidra.program.model.block.IsolatedEntrySubModel;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.listing.Function.FunctionUpdateType; import ghidra.program.model.mem.*;
import ghidra.program.model.mem.DumbMemBufferImpl;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.util.exception.*; import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
public class ExtendedFlatProgramAPI extends FlatProgramAPI { public class ExtendedFlatProgramAPI extends FlatProgramAPI {
@ -279,34 +277,9 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
} }
/** /**
* Method to determine if the given instruction is a terminating instruction (it return, ...) * Method to create the first function after the last terminating function before the given
* @param instruction the given instruction * address which is in the middle of undefined bytes
* @return true if the given instruction is a terminating instruction, false otherwise * @param address the given address
*/
public boolean isTerminatingInstruction(Instruction instruction) {
FlowType flowType = instruction.getFlowType();
FlowType overrideType =
FlowOverride.getModifiedFlowType(flowType, instruction.getFlowOverride());
if (flowType.isTerminal() || overrideType.isTerminal()) {
return true;
}
Function functionContaining = getFunctionContaining(instruction.getAddress());
if (functionContaining != null) {
if (functionContaining.isThunk() && flowType.isJump()) {
return true;
}
if (flowType.isJump()) {
return true;
}
}
return false;
}
/**
* Method to create the first function after the last terminating function before the given address
* @param address the given addres
* @param expectedFiller the expected filler byte value * @param expectedFiller the expected filler byte value
* @return the created function or null if not created * @return the created function or null if not created
*/ */
@ -314,12 +287,33 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
PseudoDisassembler pseudoDisassembler = new PseudoDisassembler(currentProgram); PseudoDisassembler pseudoDisassembler = new PseudoDisassembler(currentProgram);
// skip any undefineds and get the defined instruction before the given address
Instruction instructionBefore = getInstructionBefore(address); Instruction instructionBefore = getInstructionBefore(address);
if (instructionBefore == null || !isTerminatingInstruction(instructionBefore)) { if (instructionBefore == null) {
return null; return null;
} }
Address instBeforeAddr = instructionBefore.getAddress();
Memory memory = currentProgram.getMemory();
if (!memory.getBlock(address).equals(memory.getBlock(instBeforeAddr))) {
return null;
}
// set some arbritrary limit on how far back to go
if (address.subtract(instBeforeAddr) > 2000) {
return null;
}
// if the instruction before all the undefines bytes doesn't indicate that it is the end
// of a function or an end of a range of a function then return
FlowType flowType = instructionBefore.getFlowType();
if (!flowType.isTerminal() && !flowType.isJump()) {
return null;
}
//get the last address in the instruction
Address maxAddress = instructionBefore.getMaxAddress(); Address maxAddress = instructionBefore.getMaxAddress();
int maxLen = (int) (address.getOffset() - maxAddress.getOffset()); int maxLen = (int) (address.getOffset() - maxAddress.getOffset());
if (maxLen <= 0) { if (maxLen <= 0) {
@ -328,6 +322,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
int offset = 1; int offset = 1;
// skip the filler
Byte filler; Byte filler;
try { try {
filler = getByte(maxAddress.add(offset)); filler = getByte(maxAddress.add(offset));
@ -345,6 +340,8 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
Address functionStart = maxAddress.add(offset); Address functionStart = maxAddress.add(offset);
// check to see if the address after the instruction and filler is the start of a valid
// subroutine
if (!pseudoDisassembler.isValidSubroutine(functionStart, true)) { if (!pseudoDisassembler.isValidSubroutine(functionStart, true)) {
return null; return null;
} }
@ -352,6 +349,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
disassemble(functionStart); disassemble(functionStart);
} }
// if so, create a function there
Function function = createFunction(functionStart, null); Function function = createFunction(functionStart, null);
return function; return function;
@ -451,7 +449,6 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
Byte filler = determineFillerByte(); Byte filler = determineFillerByte();
if (filler == null) { if (filler == null) {
// println("Can't determine filler byte so cannot create undefined functions");
return; return;
} }
@ -469,7 +466,6 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
Function newFunction = createFunctionBefore(address, filler); Function newFunction = createFunctionBefore(address, filler);
if (newFunction == null) { if (newFunction == null) {
//println("Can't find function containing " + address.toString());
continue; continue;
} }
@ -542,27 +538,6 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
return subroutineAddresses; return subroutineAddresses;
} }
/**
* Method to make the given function a thiscall
* @param function the given function
* @throws InvalidInputException if issues setting return type
* @throws DuplicateNameException if try to create same symbol name already in namespace
*/
public void makeFunctionThiscall(Function function)
throws InvalidInputException, DuplicateNameException {
if (function.getCallingConventionName().equals("__thiscall")) {
return;
}
// FIXME: if you pass a Function arg you should use its program not currentProgram
ReturnParameterImpl returnType =
new ReturnParameterImpl(function.getSignature().getReturnType(), currentProgram);
function.updateFunction("__thiscall", returnType,
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, function.getSignatureSource(),
function.getParameters());
}
/** /**
* Method to get a list of symbols either matching exactly (if exact flag is true) or containing (if exact flag is false) the given symbol name * Method to get a list of symbols either matching exactly (if exact flag is true) or containing (if exact flag is false) the given symbol name
@ -1009,7 +984,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
} }
/** /**
* Method to add the given comment to an existing plate comment unless it already exists in the comment * Method to add the given string to a plate comment unless the string already exists in it.
* @param address the given address * @param address the given address
* @param comment the comment to add to the plate comment at the given address * @param comment the comment to add to the plate comment at the given address
*/ */
@ -1018,6 +993,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
String plateComment = getPlateComment(address); String plateComment = getPlateComment(address);
if (plateComment == null) { if (plateComment == null) {
setPlateComment(address, comment);
return; return;
} }

View file

@ -1820,6 +1820,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
// findRealVBaseFunctions(recoveredClasses); // findRealVBaseFunctions(recoveredClasses);
// make constructors and destructors this calls
makeConstructorsAndDestructorsThiscalls(recoveredClasses);
} }
private StructureDataType createClassTypeInfoStructure() { private StructureDataType createClassTypeInfoStructure() {

View file

@ -1333,6 +1333,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
findRealVBaseFunctions(recoveredClasses); findRealVBaseFunctions(recoveredClasses);
// make constructors and destructors _thiscalls
makeConstructorsAndDestructorsThiscalls(recoveredClasses);
} }
/** /**

View file

@ -33,6 +33,7 @@ import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.flatapi.FlatProgramAPI;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.listing.Function.FunctionUpdateType; import ghidra.program.model.listing.Function.FunctionUpdateType;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
@ -110,8 +111,9 @@ public class RecoveredClassHelper {
List<Function> allDestructors = new ArrayList<Function>(); List<Function> allDestructors = new ArrayList<Function>();
List<Function> allInlinedConstructors = new ArrayList<Function>(); List<Function> allInlinedConstructors = new ArrayList<Function>();
List<Function> allInlinedDestructors = new ArrayList<Function>(); List<Function> allInlinedDestructors = new ArrayList<Function>();
List<Function> nonClassInlines = new ArrayList<Function>();
List<Namespace> badFIDNamespaces = new ArrayList<Namespace>(); Set<Namespace> badFIDNamespaces = new HashSet<Namespace>();
List<Structure> badFIDStructures = new ArrayList<Structure>(); List<Structure> badFIDStructures = new ArrayList<Structure>();
List<Function> badFIDFunctions = new ArrayList<Function>(); List<Function> badFIDFunctions = new ArrayList<Function>();
@ -1950,10 +1952,7 @@ public class RecoveredClassHelper {
if (recoveredClass.getOrderToVftableMap().size() == 0) { if (recoveredClass.getOrderToVftableMap().size() == 0) {
createVftableOrderMapping(recoveredClass); createVftableOrderMapping(recoveredClass);
} }
// If not already, make function a thiscall
extendedFlatAPI.makeFunctionThiscall(constructorFunction);
recoveredClass.addConstructor(constructorFunction); recoveredClass.addConstructor(constructorFunction);
addToAllConstructors(constructorFunction); addToAllConstructors(constructorFunction);
} }
@ -1969,9 +1968,6 @@ public class RecoveredClassHelper {
Function inlinedConstructorFunction) Function inlinedConstructorFunction)
throws InvalidInputException, DuplicateNameException { throws InvalidInputException, DuplicateNameException {
//If not already, make function a thiscall
extendedFlatAPI.makeFunctionThiscall(inlinedConstructorFunction);
recoveredClass.addInlinedConstructor(inlinedConstructorFunction); recoveredClass.addInlinedConstructor(inlinedConstructorFunction);
addToAllInlinedConstructors(inlinedConstructorFunction); addToAllInlinedConstructors(inlinedConstructorFunction);
} }
@ -1986,9 +1982,6 @@ public class RecoveredClassHelper {
public void addDestructorToClass(RecoveredClass recoveredClass, Function destructorFunction) public void addDestructorToClass(RecoveredClass recoveredClass, Function destructorFunction)
throws InvalidInputException, DuplicateNameException { throws InvalidInputException, DuplicateNameException {
//If not already, make function a thiscall
extendedFlatAPI.makeFunctionThiscall(destructorFunction);
recoveredClass.addDestructor(destructorFunction); recoveredClass.addDestructor(destructorFunction);
addToAllDestructors(destructorFunction); addToAllDestructors(destructorFunction);
} }
@ -2004,9 +1997,6 @@ public class RecoveredClassHelper {
Function inlinedDestructorFunction) Function inlinedDestructorFunction)
throws InvalidInputException, DuplicateNameException { throws InvalidInputException, DuplicateNameException {
//If not already, make function a thiscall
extendedFlatAPI.makeFunctionThiscall(inlinedDestructorFunction);
recoveredClass.addInlinedDestructor(inlinedDestructorFunction); recoveredClass.addInlinedDestructor(inlinedDestructorFunction);
addToAllInlinedDestructors(inlinedDestructorFunction); addToAllInlinedDestructors(inlinedDestructorFunction);
} }
@ -2255,14 +2245,14 @@ public class RecoveredClassHelper {
public void makeFunctionThiscall(Function function) public void makeFunctionThiscall(Function function)
throws InvalidInputException, DuplicateNameException { throws InvalidInputException, DuplicateNameException {
if (function.getCallingConventionName().equals("__thiscall")) { if (function.getCallingConventionName().equals(CompilerSpec.CALLING_CONVENTION_thiscall)) {
return; return;
} }
ReturnParameterImpl returnType = ReturnParameterImpl returnType =
new ReturnParameterImpl(function.getSignature().getReturnType(), program); new ReturnParameterImpl(function.getSignature().getReturnType(), program);
function.updateFunction("__thiscall", returnType, function.updateFunction(CompilerSpec.CALLING_CONVENTION_thiscall, returnType,
FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, function.getSignatureSource(), FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, function.getSignatureSource(),
function.getParameters()); function.getParameters());
} }
@ -3145,11 +3135,10 @@ public class RecoveredClassHelper {
notInFunctionVftableRefs.add(addr); notInFunctionVftableRefs.add(addr);
} }
else { else {
boolean functionCreated = boolean functionCreated = extendedFlatAPI.createFunction(program, addr);
extendedFlatAPI.createFunction(prog, addr); if (!functionCreated) {
if (!functionCreated) { notInFunctionVftableRefs.add(addr);
notInFunctionVftableRefs.add(addr); }
}
} }
} }
} }
@ -3806,11 +3795,13 @@ public class RecoveredClassHelper {
if (bookmarkComment.contains("Single Match")) { if (bookmarkComment.contains("Single Match")) {
Symbol symbol = symbolTable.getPrimarySymbol(functionAddress); Symbol symbol = symbolTable.getPrimarySymbol(functionAddress);
if (symbol != null && symbol.getSource() == SourceType.ANALYSIS && if (symbol != null && symbol.getSource() == SourceType.ANALYSIS &&
!symbol.getName().equals(name) && !symbol.getParentNamespace().equals(namespace)) { !symbol.getName().equals(name) && !symbol.getParentNamespace().equals(namespace)) {
// add to list of bad namespaces to be cleaned up later // add to list of bad namespaces to be cleaned up later
if (!badFIDNamespaces.contains(symbol.getParentNamespace())) { Namespace parentNamespace = symbol.getParentNamespace();
badFIDNamespaces.add(symbol.getParentNamespace()); if (!parentNamespace.isGlobal()) {
badFIDNamespaces.add(parentNamespace);
} }
extendedFlatAPI.addUniqueStringToPlateComment(functionAddress, extendedFlatAPI.addUniqueStringToPlateComment(functionAddress,
"***** Removed Bad FID Symbol *****"); "***** Removed Bad FID Symbol *****");
@ -4426,6 +4417,11 @@ public class RecoveredClassHelper {
monitor.checkCanceled(); monitor.checkCanceled();
Namespace badNamespace = badNamespaceIterator.next(); Namespace badNamespace = badNamespaceIterator.next();
// global namespace shouldn't be on list but check anyway
if (badNamespace.isGlobal()) {
continue;
}
// delete empty namespace and parent namespaces // delete empty namespace and parent namespaces
if (!extendedFlatAPI.hasSymbolsInNamespace(badNamespace)) { if (!extendedFlatAPI.hasSymbolsInNamespace(badNamespace)) {
removeEmptyNamespaces(badNamespace); removeEmptyNamespaces(badNamespace);
@ -5965,6 +5961,7 @@ public class RecoveredClassHelper {
// remove from the allConstructors too // remove from the allConstructors too
addInlinedConstructorToClass(recoveredClass, constructor); addInlinedConstructorToClass(recoveredClass, constructor);
nonClassInlines.add(constructor);
constructorIterator.remove(); constructorIterator.remove();
removeFromAllConstructors(constructor); removeFromAllConstructors(constructor);
@ -6966,6 +6963,40 @@ public class RecoveredClassHelper {
} }
} }
public void makeConstructorsAndDestructorsThiscalls(List<RecoveredClass> recoveredClasses)
throws CancelledException, InvalidInputException, DuplicateNameException {
if (recoveredClasses.isEmpty()) {
return;
}
List<Function> allConstructorDestructorFunctions = new ArrayList<Function>();
for (RecoveredClass recoveredClass : recoveredClasses) {
monitor.checkCanceled();
allConstructorDestructorFunctions.addAll(recoveredClass.getConstructorList());
allConstructorDestructorFunctions.addAll(recoveredClass.getDestructorList());
allConstructorDestructorFunctions.addAll(recoveredClass.getInlinedConstructorList());
allConstructorDestructorFunctions.addAll(recoveredClass.getInlinedDestructorList());
}
if (allConstructorDestructorFunctions.isEmpty()) {
return;
}
// remove the inlines that are not in their expected class -- still want the inline
// comments later in processing but don't make them this calls
allConstructorDestructorFunctions.removeAll(nonClassInlines);
for (Function function : allConstructorDestructorFunctions) {
monitor.checkCanceled();
makeFunctionThiscall(function);
}
}
/** /**
* Method to create <class_name>_data structure for given class * Method to create <class_name>_data structure for given class
* @param recoveredClass the class * @param recoveredClass the class