Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2025-08-19 14:56:22 -04:00
commit 4172e448dd
4 changed files with 42 additions and 13 deletions

View file

@ -2169,8 +2169,19 @@ int4 ActionLikelyTrash::apply(Funcdata &data)
return 0; return 0;
} }
/// \param vn is the given Varnode
/// \return \b true if it is a constant or a COPY of a constant
bool ActionRestructureVarnode::isCopyConstant(Varnode *vn)
{
if (vn->isConstant()) return true;
if (!vn->isWritten()) return false;
if (vn->getDef()->code() != CPUI_COPY) return false;
return vn->getDef()->getIn(0)->isConstant();
}
/// Return \b true if either the Varnode is a constant or if it is the not yet simplified /// Return \b true if either the Varnode is a constant or if it is the not yet simplified
/// INT_ADD of constants. /// COPY or INT_ADD of constants.
/// \param vn is the given Varnode to test /// \param vn is the given Varnode to test
/// \return \b true if the Varnode will be a constant /// \return \b true if the Varnode will be a constant
bool ActionRestructureVarnode::isDelayedConstant(Varnode *vn) bool ActionRestructureVarnode::isDelayedConstant(Varnode *vn)
@ -2179,14 +2190,13 @@ bool ActionRestructureVarnode::isDelayedConstant(Varnode *vn)
if (vn->isConstant()) return true; if (vn->isConstant()) return true;
if (!vn->isWritten()) return false; if (!vn->isWritten()) return false;
PcodeOp *op = vn->getDef(); PcodeOp *op = vn->getDef();
if (op->code() != CPUI_INT_ADD) return false; OpCode opc = op->code();
if (!op->getIn(1)->isConstant()) return false; if (opc == CPUI_COPY)
Varnode *cvn = op->getIn(0); return op->getIn(0)->isConstant();
if (cvn->isConstant()) return true; if (opc != CPUI_INT_ADD) return false;
if (!cvn->isWritten()) return false; if (!isCopyConstant(op->getIn(1))) return false;
PcodeOp *copy = cvn->getDef(); if (!isCopyConstant(op->getIn(0))) return false;
if (copy->code() != CPUI_COPY) return false; return true;
return copy->getIn(0)->isConstant();
} }
/// Test if the path to the given BRANCHIND originates from a constant but passes through INDIRECT operations. /// Test if the path to the given BRANCHIND originates from a constant but passes through INDIRECT operations.
@ -5374,7 +5384,7 @@ void ActionDatabase::buildDefaultGroups(void)
setGroup("decompile",members); setGroup("decompile",members);
const char *jumptab[] = { "base", "noproto", "localrecovery", "deadcode", "stackptrflow", const char *jumptab[] = { "base", "noproto", "localrecovery", "deadcode", "stackptrflow",
"stackvars", "analysis", "segment", "subvar", "conditionalexe", "" }; "stackvars", "analysis", "segment", "subvar", "normalizebranches", "conditionalexe", "" };
setGroup("jumptable",jumptab); setGroup("jumptable",jumptab);
const char *normali[] = { "base", "protorecovery", "protorecovery_b", "deindirect", "localrecovery", const char *normali[] = { "base", "protorecovery", "protorecovery_b", "deindirect", "localrecovery",

View file

@ -831,6 +831,7 @@ public:
/// This produces on intermediate view of symbols on the stack. /// This produces on intermediate view of symbols on the stack.
class ActionRestructureVarnode : public Action { class ActionRestructureVarnode : public Action {
int4 numpass; ///< Number of passes performed for this function int4 numpass; ///< Number of passes performed for this function
static bool isCopyConstant(Varnode *vn); ///< Is the given Varnode a constant or a COPY of a constant
static bool isDelayedConstant(Varnode *vn); ///< Determine if given Varnode is or will be a constant 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 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 static void protectSwitchPaths(Funcdata &data); ///< Look for switches and protect path of switch variable

View file

@ -1284,6 +1284,18 @@ bool JumpBasic::flowsOnlyToModel(Varnode *vn,PcodeOp *trailOp)
return true; return true;
} }
/// \param arr is the array of Varnodes
/// \return \b true if all elements are the same
bool JumpBasic::duplicateVarnodes(const vector<Varnode *> &arr)
{
Varnode *vn = arr[0];
for(int4 i=1;i<arr.size();++i) {
if (arr[i] != vn) return false;
}
return true;
}
/// All CBRANCHs in addition to flowing to the given block, must also flow to another common block, /// All CBRANCHs in addition to flowing to the given block, must also flow to another common block,
/// and each boolean value must select between the given block and the common block in the same way. /// and each boolean value must select between the given block and the common block in the same way.
/// If this flow exists, \b true is returned and the boolean Varnode inputs to each CBRANCH are passed back. /// If this flow exists, \b true is returned and the boolean Varnode inputs to each CBRANCH are passed back.
@ -1338,9 +1350,14 @@ void JumpBasic::checkUnrolledGuard(BlockBasic *bl,int4 maxpullback,bool usenzmas
int4 indpathstore = bl->getIn(0)->getFlipPath() ? 1-indpath : indpath; int4 indpathstore = bl->getIn(0)->getFlipPath() ? 1-indpath : indpath;
PcodeOp *readOp = cbranch; PcodeOp *readOp = cbranch;
for(int4 j=0;j<maxpullback;++j) { for(int4 j=0;j<maxpullback;++j) {
PcodeOp *multiOp = bl->findMultiequal(varArray); if (duplicateVarnodes(varArray)) {
if (multiOp != (PcodeOp *)0) { selectguards.push_back(GuardRecord(cbranch,readOp,indpathstore,rng,varArray[0],true));
selectguards.push_back(GuardRecord(cbranch,readOp,indpathstore,rng,multiOp->getOut(),true)); }
else {
PcodeOp *multiOp = bl->findMultiequal(varArray);
if (multiOp != (PcodeOp *)0) {
selectguards.push_back(GuardRecord(cbranch,readOp,indpathstore,rng,multiOp->getOut(),true));
}
} }
Varnode *markup; // Throw away markup information Varnode *markup; // Throw away markup information
Varnode *vn = varArray[0]; Varnode *vn = varArray[0];

View file

@ -382,6 +382,7 @@ protected:
static int4 getStride(Varnode *vn); ///< Get the step/stride associated with the Varnode static int4 getStride(Varnode *vn); ///< Get the step/stride associated with the Varnode
static uintb backup2Switch(Funcdata *fd,uintb output,Varnode *outvn,Varnode *invn); static uintb backup2Switch(Funcdata *fd,uintb output,Varnode *outvn,Varnode *invn);
static uintb getMaxValue(Varnode *vn); ///< Get maximum value associated with the given Varnode static uintb getMaxValue(Varnode *vn); ///< Get maximum value associated with the given Varnode
static bool duplicateVarnodes(const vector<Varnode *> &arr); ///< Return \b true if all array elements are the same Varnode
void findDeterminingVarnodes(PcodeOp *op,int4 slot); void findDeterminingVarnodes(PcodeOp *op,int4 slot);
void analyzeGuards(BlockBasic *bl,int4 pathout); void analyzeGuards(BlockBasic *bl,int4 pathout);
void calcRange(Varnode *vn,CircleRange &rng) const; void calcRange(Varnode *vn,CircleRange &rng) const;