diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc index bad14186f0..bf0286ac55 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc @@ -4176,9 +4176,11 @@ int4 RuleSubCommute::applyOp(PcodeOp *op,Funcdata &data) break; } case CPUI_INT_ADD: + if (offset != 0) return 0; // Only commutes with least significant SUBPIECE + if (longform->getIn(0)->isSpacebase()) return 0; // Deconflict with RulePtrArith + break; case CPUI_INT_MULT: - // These only commute with least significant SUBPIECE - if (offset != 0) return 0; + if (offset != 0) return 0; // Only commutes with least significant SUBPIECE break; // Bitwise ops, type of subpiece doesnt matter case CPUI_INT_NEGATE: diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc index 3813489adb..5533eccf05 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc @@ -306,6 +306,33 @@ void ScopeLocal::collectNameRecs(void) } } +/// For any read of the input stack pointer by a non-additive p-code op, assume this constitutes a +/// a zero offset reference into the stack frame. Replace the raw Varnode with the standard +/// spacebase placeholder, PTRSUB(sp,#0), so that the data-type system can treat it as a reference. +void ScopeLocal::annotateRawStackPtr(void) + +{ + if (!fd->isTypeRecoveryOn()) return; + Varnode *spVn = fd->findSpacebaseInput(space); + if (spVn == (Varnode *)0) return; + list::const_iterator iter; + vector refOps; + for(iter=spVn->beginDescend();iter!=spVn->endDescend();++iter) { + PcodeOp *op = *iter; + if (op->getEvalType() == PcodeOp::special && !op->isCall()) continue; + OpCode opc = op->code(); + if (opc == CPUI_INT_ADD || opc == CPUI_PTRSUB || opc == CPUI_PTRADD) + continue; + refOps.push_back(op); + } + for(int4 i=0;igetSlot(spVn); + PcodeOp *ptrsub = fd->newOpBefore(op,CPUI_PTRSUB,spVn,fd->newConstant(spVn->getSize(),0)); + fd->opSetInput(op, ptrsub->getOut(), slot); + } +} + /// This resets the discovery process for new local variables mapped to the scope's address space. /// Any analysis removing specific ranges from the mapped set (via markNotMapped()) is cleared. void ScopeLocal::resetLocalWindow(void) @@ -1024,6 +1051,8 @@ void ScopeLocal::restructureVarnode(bool aliasyes) state.sortAlias(); if (aliasyes) markUnaliased(state.getAlias()); + if (!state.getAlias().empty() && state.getAlias()[0] == 0) // If a zero offset use of the stack pointer exists + annotateRawStackPtr(); // Add a special placeholder PTRSUB } /// Define stack Symbols based on HighVariables. diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.hh index 0944a3c975..b8e16c2f91 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/varmap.hh @@ -208,6 +208,7 @@ class ScopeLocal : public ScopeInternal { void fakeInputSymbols(void); ///< Make sure all stack inputs have an associated Symbol void addRecommendName(Symbol *sym); ///< Convert the given symbol to a name recommendation void collectNameRecs(void); ///< Collect names of unlocked Symbols on the stack + void annotateRawStackPtr(void); ///< Generate placeholder PTRSUB off of stack pointer public: ScopeLocal(uint8 id,AddrSpace *spc,Funcdata *fd,Architecture *g); ///< Constructor virtual ~ScopeLocal(void) {} ///< Destructor