From 8af47cc7b0e8a01abeba520cf86dc73c28bf20d7 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:47:38 +0000 Subject: [PATCH] GP-4369 Adjust switch variable path detection --- .../src/decompile/cpp/coreaction.cc | 31 +++++++++++++++++-- .../src/decompile/cpp/coreaction.hh | 1 + 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 9dfd874934..adfb835e98 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -2162,6 +2162,26 @@ int4 ActionLikelyTrash::apply(Funcdata &data) return 0; } +/// Return \b true if either the Varnode is a constant or if it is the not yet simplified +/// INT_ADD of constants. +/// \param vn is the given Varnode to test +/// \return \b true if the Varnode will be a constant +bool ActionRestructureVarnode::isDelayedConstant(Varnode *vn) + +{ + if (vn->isConstant()) return true; + if (!vn->isWritten()) return false; + PcodeOp *op = vn->getDef(); + if (op->code() != CPUI_INT_ADD) return false; + if (!op->getIn(1)->isConstant()) return false; + Varnode *cvn = op->getIn(0); + if (cvn->isConstant()) return true; + if (!cvn->isWritten()) return false; + PcodeOp *copy = cvn->getDef(); + if (copy->code() != CPUI_COPY) return false; + return copy->getIn(0)->isConstant(); +} + /// Test if the path to the given BRANCHIND originates from a constant but passes through INDIRECT operations. /// This indicates that the switch value is produced indirectly, so we mark these INDIRECT /// operations as \e not \e collapsible, to guarantee that the indirect value is not lost during analysis. @@ -2176,9 +2196,16 @@ void ActionRestructureVarnode::protectSwitchPathIndirects(PcodeOp *op) uint4 evalType = curOp->getEvalType(); if ((evalType & (PcodeOp::binary | PcodeOp::ternary)) != 0) { if (curOp->numInput() > 1) { - if (!curOp->getIn(1)->isConstant()) return; // Multiple paths + if (isDelayedConstant(curOp->getIn(1))) + curVn = curOp->getIn(0); + else if (isDelayedConstant(curOp->getIn(0))) + curVn = curOp->getIn(1); + else + return; // Multiple paths + } + else { + curVn = curOp->getIn(0); } - curVn = curOp->getIn(0); } else if ((evalType & PcodeOp::unary) != 0) curVn = curOp->getIn(0); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh index eefa3a8176..71a281c6b8 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh @@ -832,6 +832,7 @@ public: /// This produces on intermediate view of symbols on the stack. class ActionRestructureVarnode : public Action { int4 numpass; ///< Number of passes performed for this function + static bool isDelayedConstant(Varnode *vn); ///< Determine if given Varnode is or will be a constant static void protectSwitchPathIndirects(PcodeOp *op); ///< Protect path to the given switch from INDIRECT collapse static void protectSwitchPaths(Funcdata &data); ///< Look for switches and protect path of switch variable public: