GP-4369 Adjust switch variable path detection

This commit is contained in:
caheckman 2024-02-27 17:47:38 +00:00
parent 89c2d55b07
commit 8af47cc7b0
2 changed files with 30 additions and 2 deletions

View File

@ -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);

View File

@ -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: