mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
Sign-bit comparisons through truncation
This commit is contained in:
parent
a85f140a53
commit
c372c05a20
2 changed files with 70 additions and 37 deletions
|
@ -3133,6 +3133,44 @@ void RuleTestSign::getOpList(vector<uint4> &oplist) const
|
||||||
oplist.push_back(CPUI_INT_SRIGHT);
|
oplist.push_back(CPUI_INT_SRIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Find INT_EQUAL or INT_NOTEQUAL taking the sign bit as input
|
||||||
|
///
|
||||||
|
/// Trace the given sign-bit varnode to any comparison operations and pass them
|
||||||
|
/// back in the given array. Allow the sign-bit to go through a SUBPIECE operation.
|
||||||
|
/// \param vn is the given sign-bit varnode
|
||||||
|
/// \param res is the array for holding the comparison op results
|
||||||
|
void RuleTestSign::findComparisons(Varnode *vn,vector<PcodeOp *> &res)
|
||||||
|
|
||||||
|
{
|
||||||
|
list<PcodeOp *>::const_iterator iter1;
|
||||||
|
iter1 = vn->beginDescend();
|
||||||
|
while(iter1 != vn->endDescend()) {
|
||||||
|
PcodeOp *op = *iter1;
|
||||||
|
++iter1;
|
||||||
|
OpCode opc = op->code();
|
||||||
|
if (opc == CPUI_INT_EQUAL || opc == CPUI_INT_NOTEQUAL) {
|
||||||
|
if (op->getIn(1)->isConstant())
|
||||||
|
res.push_back(op);
|
||||||
|
}
|
||||||
|
else if (opc == CPUI_SUBPIECE) {
|
||||||
|
// Note that it doesn't matter what the truncation is because the varnode is
|
||||||
|
// filled with the same bit everywhere.
|
||||||
|
Varnode *outVn = op->getOut();
|
||||||
|
list<PcodeOp *>::const_iterator iter2;
|
||||||
|
iter2 = outVn->beginDescend();
|
||||||
|
while(iter2 != outVn->endDescend()) {
|
||||||
|
PcodeOp *subOp = *iter2;
|
||||||
|
++iter2;
|
||||||
|
OpCode opc2 = subOp->code();
|
||||||
|
if (opc2 == CPUI_INT_EQUAL || opc2 == CPUI_INT_NOTEQUAL) {
|
||||||
|
if (subOp->getIn(1)->isConstant())
|
||||||
|
res.push_back(subOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int4 RuleTestSign::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RuleTestSign::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -3144,47 +3182,41 @@ int4 RuleTestSign::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
if (val != 8*inVn->getSize() -1) return 0;
|
if (val != 8*inVn->getSize() -1) return 0;
|
||||||
if (inVn->isFree()) return 0;
|
if (inVn->isFree()) return 0;
|
||||||
Varnode *outVn = op->getOut();
|
Varnode *outVn = op->getOut();
|
||||||
list<PcodeOp *>::const_iterator iter;
|
vector<PcodeOp *> compareOps;
|
||||||
iter = outVn->beginDescend();
|
findComparisons(outVn, compareOps);
|
||||||
while(iter != outVn->endDescend()) {
|
int4 resultCode = 0;
|
||||||
PcodeOp *compareOp = *iter;
|
for(int4 i=0;i<compareOps.size();++i) {
|
||||||
Varnode *otherVn;
|
PcodeOp *compareOp = compareOps[i];
|
||||||
++iter;
|
Varnode *compVn = compareOp->getIn(0);
|
||||||
|
int4 compSize = compVn->getSize();
|
||||||
|
if (compareOp->code() == CPUI_SUBPIECE)
|
||||||
|
compareOp = compVn->getDef();
|
||||||
|
|
||||||
|
uintb offset = compareOp->getIn(1)->getOffset();
|
||||||
int4 sgn;
|
int4 sgn;
|
||||||
switch(compareOp->code()) {
|
if (offset == 0)
|
||||||
default:
|
sgn = 1;
|
||||||
sgn = 0;
|
else if (offset == calc_mask(compSize))
|
||||||
break;
|
sgn = -1;
|
||||||
case CPUI_INT_EQUAL:
|
else
|
||||||
otherVn = compareOp->getIn(1);
|
continue;
|
||||||
if (otherVn->isConstant() && otherVn->getOffset() == 0)
|
if (compareOp->code() == CPUI_INT_NOTEQUAL)
|
||||||
sgn = 1;
|
sgn = -sgn; // Complement the domain
|
||||||
else
|
|
||||||
sgn = 0;
|
Varnode *zeroVn = data.newConstant(inVn->getSize(), 0);
|
||||||
break;
|
if (sgn == 1) {
|
||||||
case CPUI_INT_NOTEQUAL:
|
data.opSetInput(compareOp, inVn, 1);
|
||||||
otherVn = compareOp->getIn(1);
|
data.opSetInput(compareOp, zeroVn, 0);
|
||||||
if (otherVn->isConstant() && otherVn->getOffset() == 0)
|
data.opSetOpcode(compareOp, CPUI_INT_SLESSEQUAL);
|
||||||
sgn = -1;
|
|
||||||
else
|
|
||||||
sgn = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (sgn != 0) {
|
else {
|
||||||
if (sgn == 1) {
|
data.opSetInput(compareOp, inVn, 0);
|
||||||
data.opSetInput(compareOp, inVn, 1);
|
data.opSetInput(compareOp, zeroVn, 1);
|
||||||
data.opSetInput(compareOp, otherVn, 0);
|
data.opSetOpcode(compareOp, CPUI_INT_SLESS);
|
||||||
data.opSetOpcode(compareOp, CPUI_INT_SLESSEQUAL);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data.opSetInput(compareOp, inVn, 0);
|
|
||||||
data.opSetInput(compareOp, otherVn, 1);
|
|
||||||
data.opSetOpcode(compareOp, CPUI_INT_SLESS);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
resultCode = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return resultCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \class RuleIdentityEl
|
/// \class RuleIdentityEl
|
||||||
|
|
|
@ -556,6 +556,7 @@ public:
|
||||||
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
};
|
};
|
||||||
class RuleTestSign : public Rule {
|
class RuleTestSign : public Rule {
|
||||||
|
void findComparisons(Varnode *vn,vector<PcodeOp *> &res);
|
||||||
public:
|
public:
|
||||||
RuleTestSign(const string &g) : Rule(g, 0, "testsign") {} ///< Constructor
|
RuleTestSign(const string &g) : Rule(g, 0, "testsign") {} ///< Constructor
|
||||||
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue