diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/ApplyFunctionDataTypesCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/ApplyFunctionDataTypesCmd.java index 883a5accdf..c6d5b54420 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/ApplyFunctionDataTypesCmd.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/ApplyFunctionDataTypesCmd.java @@ -21,8 +21,7 @@ import ghidra.app.cmd.disassemble.DisassembleCommand; import ghidra.app.util.PseudoDisassembler; import ghidra.framework.cmd.BackgroundCommand; import ghidra.framework.model.DomainObject; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryBlock; @@ -266,12 +265,11 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand { boolean isValidFunctionStart(TaskMonitor monitor, Address address) { // instruction above falls into this one // could be non-returning function, but we can't tell now - Instruction instructionBefore = - program.getListing().getInstructionContaining(address.subtract(1)); - if (instructionBefore != null && address.equals(instructionBefore.getFallThrough())) { + Instruction instrBefore = getInstructionBefore(address); + if (instrBefore != null && address.equals(instrBefore.getFallThrough())) { return false; } - + // check if part of a larger code-block ReferenceIterator referencesTo = program.getReferenceManager().getReferencesTo(address); for (Reference reference : referencesTo) { @@ -290,6 +288,30 @@ public class ApplyFunctionDataTypesCmd extends BackgroundCommand { return true; } + /** + * Get the instruction directly before this address, makeing sure it is the + * head instruction in a delayslot + * + * @param address to get instruction before + * @return instruction if found, null otherwise + */ + Instruction getInstructionBefore(Address address) { + Address addrBefore = address.previous(); + Instruction instrBefore = null; + + while (addrBefore != null) { + instrBefore = program.getListing().getInstructionContaining(addrBefore); + if (instrBefore == null) { + break; + } + if (!instrBefore.isInDelaySlot()) { + break; + } + addrBefore = instrBefore.getMinAddress().previous(); + } + return instrBefore; + } + private void applyFunction(Symbol sym, FunctionDefinition fdef) { if (fdef == null) { Msg.info(this, "Multiple function definitions for " + sym.getName() + " at " + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/exceptionhandlers/gcc/structures/ehFrame/FrameDescriptionEntry.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/exceptionhandlers/gcc/structures/ehFrame/FrameDescriptionEntry.java index fb4b3ab504..30ef373b2f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/exceptionhandlers/gcc/structures/ehFrame/FrameDescriptionEntry.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/exceptionhandlers/gcc/structures/ehFrame/FrameDescriptionEntry.java @@ -304,7 +304,13 @@ public class FrameDescriptionEntry extends GccAnalysisClass { String comment = "(FDE) PcRange"; intPcRange = (int) GccAnalysisUtils.readDWord(program, addr); + if (intPcRange < 0) { + return null; + } + if (intPcRange == 0) { + intPcRange = 1; + } pcEndAddr = pcBeginAddr.add(intPcRange - 1); DataType dataType = getAddressSizeDataType(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java index 7a160c2c9f..888e101975 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf4/DIEAggregate.java @@ -871,9 +871,14 @@ public class DIEAggregate { // else it was a DW_FORM_data value and is relative to the lowPC value DWARFNumericAttribute low = getAttribute(DWARFAttribute.DW_AT_low_pc, DWARFNumericAttribute.class); - if (low != null && highVal.getUnsignedValue() > 0) { + + long lhighVal = highVal.getUnsignedValue(); + if (lhighVal == 0) { + lhighVal = 1; + } + if (low != null && lhighVal > 0) { return low.getUnsignedValue() + getProgram().getProgramBaseAddressFixup() + - highVal.getUnsignedValue() - 1; + lhighVal - 1; } } throw new IOException("Bad/unsupported DW_AT_high_pc attribute value or type"); diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java index 81e44397fe..adec352a07 100644 --- a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java +++ b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/FunctionStartAnalyzer.java @@ -365,7 +365,11 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa // if this place is already in a function, we shouldn't start one if (name.startsWith("func")) { - if (checkAlreadyInFunctionAbove(program, addr)) { + Function funcAbove = getFunctionAbove(program, addr); + if (funcAbove == null) { + return false; + } + if (checkAlreadyInFunctionAbove(program, addr, funcAbove)) { return false; } } @@ -402,39 +406,77 @@ public class FunctionStartAnalyzer extends AbstractAnalyzer implements PatternFa return true; } + /* + * Check if address if addr is already part of a function just preceding this address. + * If the address is part of another function that is different than the function right + * above, then the pattern should be applied, because it is most likely a unique function + * that is being used by another function as a shared return. + */ private boolean checkAlreadyInFunctionAbove(Program program, Address addr) { - // make sure there is an end of function before this one, and if just an instruction, doesn't fall into this one. - Function func = null; + Function funcAbove = getFunctionAbove(program, addr); + return checkAlreadyInFunctionAbove(program, addr, funcAbove); + } + + /* + * Check if in a function above + * return true if already in function above, false otherwise even if in another function + */ + private boolean checkAlreadyInFunctionAbove(Program program, Address addr, Function funcAbove) { + // if no funcAbove, make sure an instruction, doesn't fall into this one. Address addrBefore = addr.previous(); - func = program.getFunctionManager().getFunctionContaining(addrBefore); - if (func == null) { - Instruction instr = program.getListing().getInstructionContaining(addrBefore); - if (instr != null && addr.equals(instr.getFallThrough())) { - return true; - } - // check for references to this function, address - ReferenceIterator referencesTo = - program.getReferenceManager().getReferencesTo(addr); - for (Reference reference : referencesTo) { - // someone flows to or reads/writes this location, shouldn't be a start - RefType referenceType = reference.getReferenceType(); - if (referenceType.isData() && - !(referenceType.isRead() || referenceType.isWrite())) { - continue; - } - // any other reference to here is bad, since a function or other flow should - // have created the location - return true; - } + if (addrBefore == null) { return false; } - // don't do it if I'm in a function - Function myfunc = program.getFunctionManager().getFunctionContaining(addr); - if (myfunc != null && myfunc.getEntryPoint().equals(func.getEntryPoint())) { + if (funcAbove != null) { + // check if in function right above + Function myfunc = program.getFunctionManager().getFunctionContaining(addr); + if (myfunc != null && myfunc.getEntryPoint().equals(funcAbove.getEntryPoint())) { + return true; + } + // I could be in a different function, just not one above + return false; + } + + // no function above, but check for references, that would make this a function + // or references that would imply it is part of another function. + Instruction instr = program.getListing().getInstructionContaining(addrBefore); + if (instr != null && addr.equals(instr.getFallThrough())) { return true; } + // check for references to this function, address + ReferenceIterator referencesTo = + program.getReferenceManager().getReferencesTo(addr); + for (Reference reference : referencesTo) { + // someone flows to or reads/writes this location, shouldn't be a start + RefType referenceType = reference.getReferenceType(); + if (referenceType.isData() && + !(referenceType.isRead() || referenceType.isWrite())) { + continue; + } + // any other reference to here is bad, since a function or other flow should + // have created the location + return true; + } + return false; } + + /** + * Get an existing function right above the addr. + * @param program program to check + * @param addr address to check + * @return true if there is an existing function above addr + */ + private Function getFunctionAbove(Program program, Address addr) { + // make sure there is an end of function before this one, and addr is not in the function + Function func = null; + Address addrBefore = addr.previous(); + if (addrBefore == null) { + return null; + } + func = program.getFunctionManager().getFunctionContaining(addrBefore); + return func; + } void bookmarkAction(Program program, Address addr, Match match) { if (setbookmark) {