From 68747248f39931031bb346abcbbe83f9a8c94224 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Mon, 1 May 2023 19:39:08 -0400 Subject: [PATCH] GP-3378 Remove op when clearing placeholder --- .../src/decompile/cpp/coreaction.cc | 10 ++------ .../Decompiler/src/decompile/cpp/fspec.cc | 24 +++++++++++++++++-- .../Decompiler/src/decompile/cpp/fspec.hh | 9 +++---- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index cc6ce8f6bb..7efbd3e01a 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -1466,14 +1466,8 @@ void ActionFuncLink::funcLinkInput(FuncCallSpecs *fc,Funcdata &data) data.opInsertInput(op,data.newVarnode(param->getSize(),param->getAddress()),op->numInput()); } } - if (spacebase != (AddrSpace *)0) { // If we need it, create the stackplaceholder - PcodeOp *op = fc->getOp(); - int4 slot = op->numInput(); - Varnode *loadval = data.opStackLoad(spacebase,0,1,op,(Varnode *)0,false); - data.opInsertInput(op,loadval,slot); - fc->setStackPlaceholderSlot(slot); - loadval->setSpacebasePlaceholder(); - } + if (spacebase != (AddrSpace *)0) // If we need it, create the stackplaceholder + fc->createPlaceholder(data, spacebase); } /// \brief Set up the return value recovery process for a single sub-function call diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc index 5db66021af..b30e482988 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.cc @@ -4554,6 +4554,23 @@ void FuncProto::decode(Decoder &decoder,Architecture *glb) updateThisPointer(); } +/// \brief Add a an input parameter that will resolve to the current stack offset for \b this call site +/// +/// A LOAD from a free reference to the \e spacebase pointer of the given AddrSpace is created and +/// its output is added as a parameter to the call. Later the LOAD should resolve to a COPY from +/// a Varnode in the AddrSpace, whose offset is then the current offset. +/// \param data is the function where the LOAD is created +/// \param spacebase is the given (stack) AddrSpace +void FuncCallSpecs::createPlaceholder(Funcdata &data,AddrSpace *spacebase) + +{ + int4 slot = op->numInput(); + Varnode *loadval = data.opStackLoad(spacebase,0,1,op,(Varnode *)0,false); + data.opInsertInput(op,loadval,slot); + setStackPlaceholderSlot(slot); + loadval->setSpacebasePlaceholder(); +} + /// \brief Calculate the stack offset of \b this call site /// /// The given Varnode must be the input to the CALL in the \e placeholder slot @@ -4577,8 +4594,7 @@ void FuncCallSpecs::resolveSpacebaseRelative(Funcdata &data,Varnode *phvn) if (stackPlaceholderSlot >= 0) { if (op->getIn(stackPlaceholderSlot) == phvn) { - data.opRemoveInput(op,stackPlaceholderSlot); - clearStackPlaceholderSlot(); + abortSpacebaseRelative(data); return; } } @@ -4610,8 +4626,12 @@ void FuncCallSpecs::abortSpacebaseRelative(Funcdata &data) { if (stackPlaceholderSlot >= 0) { + Varnode *vn = op->getIn(stackPlaceholderSlot); data.opRemoveInput(op,stackPlaceholderSlot); clearStackPlaceholderSlot(); + // Remove the op producing the placeholder as well + if (vn->hasNoDescend() && vn->getSpace()->getType() == IPTR_INTERNAL && vn->isWritten()) + data.opDestroy(vn->getDef()); } } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh index 7d0136a0e8..439aaccf59 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/fspec.hh @@ -1610,6 +1610,10 @@ class FuncCallSpecs : public FuncProto { void commitNewInputs(Funcdata &data,vector &newinput); void commitNewOutputs(Funcdata &data,Varnode *newout); void collectOutputTrialVarnodes(vector &trialvn); + void setStackPlaceholderSlot(int4 slot) { stackPlaceholderSlot = slot; + if (isinputactive) activeinput.setPlaceholderSlot(); } ///< Set the slot of the stack-pointer placeholder + void clearStackPlaceholderSlot(void) { + stackPlaceholderSlot = -1; if (isinputactive) activeinput.freePlaceholderSlot(); } ///< Release the stack-pointer placeholder public: enum { offset_unknown = 0xBADBEEF ///< "Magic" stack offset indicating the offset is unknown @@ -1629,10 +1633,6 @@ public: int4 getParamshift(void) const { return paramshift; } ///< Get the parameter shift for this call site int4 getMatchCallCount(void) const { return matchCallCount; } ///< Get the number of calls the caller makes to \b this sub-function int4 getStackPlaceholderSlot(void) const { return stackPlaceholderSlot; } ///< Get the slot of the stack-pointer placeholder - void setStackPlaceholderSlot(int4 slot) { stackPlaceholderSlot = slot; - if (isinputactive) activeinput.setPlaceholderSlot(); } ///< Set the slot of the stack-pointer placeholder - void clearStackPlaceholderSlot(void) { - stackPlaceholderSlot = -1; if (isinputactive) activeinput.freePlaceholderSlot(); } ///< Release the stack-pointer placeholder void initActiveInput(void); ///< Turn on analysis recovering input parameters void clearActiveInput(void) { isinputactive = false; } ///< Turn off analysis recovering input parameters @@ -1651,6 +1651,7 @@ public: void deindirect(Funcdata &data,Funcdata *newfd); void forceSet(Funcdata &data,const FuncProto &fp); void insertPcode(Funcdata &data); + void createPlaceholder(Funcdata &data,AddrSpace *spacebase); void resolveSpacebaseRelative(Funcdata &data,Varnode *phvn); void abortSpacebaseRelative(Funcdata &data); void finalInputCheck(void);