diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc index 4cd948c50d..ca3e4c705f 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc @@ -4470,6 +4470,8 @@ void FuncCallSpecs::deindirect(Funcdata &data,Funcdata *newfd) Varnode *vn = data.newVarnodeCallSpecs(this); data.opSetInput(op,vn,0); data.opSetOpcode(op,CPUI_CALL); + if (isOverride()) // If we are overridden at the call-site + return; // Don't use the discovered function prototype // Try our best to merge existing prototype // with the one we have just been handed diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh index 1322980b56..460f652c90 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh @@ -1158,7 +1158,8 @@ class FuncProto { unknown_model = 512, ///< Set if the PrototypeModel isn't known is_constructor = 0x400, ///< Function is an (object-oriented) constructor is_destructor = 0x800, ///< Function is an (object-oriented) destructor - has_thisptr= 0x1000 ///< Function is a method with a 'this' pointer as an argument + has_thisptr= 0x1000, ///< Function is a method with a 'this' pointer as an argument + is_override = 0x2000 ///< Set if \b this prototype is created to override a single call site }; ProtoModel *model; ///< Model of for \b this prototype ProtoStore *store; ///< Storage interface for parameters @@ -1332,6 +1333,8 @@ public: bool isStackGrowsNegative(void) const { return model->isStackGrowsNegative(); } ///< Return \b true if the stack grows toward smaller addresses bool isDotdotdot(void) const { return ((flags&dotdotdot)!=0); } ///< Return \b true if \b this takes a variable number of arguments void setDotdotdot(bool val) { flags = val ? (flags|dotdotdot) : (flags & ~((uint4)dotdotdot)); } ///< Toggle whether \b this takes variable arguments + bool isOverride(void) const { return ((flags&is_override)!=0); } ///< Return \b true if \b this is a call site override + void setOverride(bool val) { flags = val ? (flags|is_override) : (flags & ~((uint4)is_override)); } ///< Toggle whether \b this is a call site override uint4 hasEffect(const Address &addr,int4 size) const; vector::const_iterator effectBegin(void) const; ///< Get iterator to front of EffectRecord list vector::const_iterator effectEnd(void) const; ///< Get iterator to end of EffectRecord list diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc index 71005f739b..48adb18329 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/override.cc @@ -117,7 +117,8 @@ void Override::insertProtoOverride(const Address &callpoint,FuncProto *p) if (iter != protoover.end()) // Check for pre-existing override delete (*iter).second; // and delete it - protoover[callpoint] = p; + p->setOverride(true); // Mark this as an override + protoover[callpoint] = p; // Take ownership of the object } /// \brief Flag an indirect jump for multistage analysis diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/OverridePrototypeAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/OverridePrototypeAction.java index 13dd530623..a4c906745e 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/OverridePrototypeAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/OverridePrototypeAction.java @@ -29,6 +29,7 @@ import ghidra.program.model.address.Address; import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.pcode.*; +import ghidra.program.model.symbol.Reference; import ghidra.util.Msg; import ghidra.util.UndefinedFunction; import ghidra.util.exception.CancelledException; @@ -140,7 +141,22 @@ public class OverridePrototypeAction extends AbstractDecompilerAction { } Address addr = op.getInput(0).getAddress(); Program program = controller.getProgram(); - return program.getFunctionManager().getFunctionAt(addr); + FunctionManager functionManager = program.getFunctionManager(); + Function function = functionManager.getFunctionAt(addr); + if (function != null) { + return function; + } + Address opAddr = op.getSeqnum().getTarget(); + Reference[] references = program.getReferenceManager().getFlowReferencesFrom(opAddr); + for (Reference ref : references) { + if (ref.getReferenceType().isCall()) { + function = functionManager.getFunctionAt(ref.getToAddress()); + if (function != null) { + return function; + } + } + } + return null; } private String generateSignature(PcodeOp op, String name) {