mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Rules for sign bit extraction
This commit is contained in:
parent
c7f934c9d1
commit
a85f140a53
3 changed files with 114 additions and 0 deletions
|
@ -4464,6 +4464,8 @@ void universal_action(Architecture *conf)
|
||||||
actprop->addRule( new RuleTrivialArith("analysis") );
|
actprop->addRule( new RuleTrivialArith("analysis") );
|
||||||
actprop->addRule( new RuleTrivialBool("analysis") );
|
actprop->addRule( new RuleTrivialBool("analysis") );
|
||||||
actprop->addRule( new RuleTrivialShift("analysis") );
|
actprop->addRule( new RuleTrivialShift("analysis") );
|
||||||
|
actprop->addRule( new RuleSignShift("analysis") );
|
||||||
|
actprop->addRule( new RuleTestSign("analysis") );
|
||||||
actprop->addRule( new RuleIdentityEl("analysis") );
|
actprop->addRule( new RuleIdentityEl("analysis") );
|
||||||
actprop->addRule( new RuleOrMask("analysis") );
|
actprop->addRule( new RuleOrMask("analysis") );
|
||||||
actprop->addRule( new RuleAndMask("analysis") );
|
actprop->addRule( new RuleAndMask("analysis") );
|
||||||
|
|
|
@ -3095,6 +3095,98 @@ int4 RuleTrivialShift::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \class RuleSignShift
|
||||||
|
/// \brief Normalize sign-bit extraction: `V >> 0x1f => (V s>> 0x1f) * -1`
|
||||||
|
void RuleSignShift::getOpList(vector<uint4> &oplist) const
|
||||||
|
|
||||||
|
{
|
||||||
|
oplist.push_back(CPUI_INT_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 RuleSignShift::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
uintb val;
|
||||||
|
Varnode *constVn = op->getIn(1);
|
||||||
|
if (!constVn->isConstant()) return 0;
|
||||||
|
val = constVn->getOffset();
|
||||||
|
Varnode *inVn = op->getIn(0);
|
||||||
|
if (val != 8*inVn->getSize() -1) return 0;
|
||||||
|
if (inVn->isFree()) return 0;
|
||||||
|
PcodeOp *shiftOp = data.newOp(2,op->getAddr());
|
||||||
|
data.opSetOpcode(shiftOp, CPUI_INT_SRIGHT);
|
||||||
|
Varnode *outVn = data.newUniqueOut(inVn->getSize(), shiftOp);
|
||||||
|
data.opSetInput(op,outVn,0);
|
||||||
|
data.opSetInput(op,data.newConstant(inVn->getSize(),calc_mask(inVn->getSize())),1);
|
||||||
|
data.opSetOpcode(op, CPUI_INT_MULT);
|
||||||
|
data.opSetInput(shiftOp,inVn,0);
|
||||||
|
data.opSetInput(shiftOp,constVn,1);
|
||||||
|
data.opInsertBefore(shiftOp, op);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \class RuleSignShift
|
||||||
|
/// \brief Convert sign-bit test to signed comparison: `(V s>> 0x1f) != 0 => V s< 0`
|
||||||
|
void RuleTestSign::getOpList(vector<uint4> &oplist) const
|
||||||
|
|
||||||
|
{
|
||||||
|
oplist.push_back(CPUI_INT_SRIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 RuleTestSign::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
uintb val;
|
||||||
|
Varnode *constVn = op->getIn(1);
|
||||||
|
if (!constVn->isConstant()) return 0;
|
||||||
|
val = constVn->getOffset();
|
||||||
|
Varnode *inVn = op->getIn(0);
|
||||||
|
if (val != 8*inVn->getSize() -1) return 0;
|
||||||
|
if (inVn->isFree()) return 0;
|
||||||
|
Varnode *outVn = op->getOut();
|
||||||
|
list<PcodeOp *>::const_iterator iter;
|
||||||
|
iter = outVn->beginDescend();
|
||||||
|
while(iter != outVn->endDescend()) {
|
||||||
|
PcodeOp *compareOp = *iter;
|
||||||
|
Varnode *otherVn;
|
||||||
|
++iter;
|
||||||
|
int4 sgn;
|
||||||
|
switch(compareOp->code()) {
|
||||||
|
default:
|
||||||
|
sgn = 0;
|
||||||
|
break;
|
||||||
|
case CPUI_INT_EQUAL:
|
||||||
|
otherVn = compareOp->getIn(1);
|
||||||
|
if (otherVn->isConstant() && otherVn->getOffset() == 0)
|
||||||
|
sgn = 1;
|
||||||
|
else
|
||||||
|
sgn = 0;
|
||||||
|
break;
|
||||||
|
case CPUI_INT_NOTEQUAL:
|
||||||
|
otherVn = compareOp->getIn(1);
|
||||||
|
if (otherVn->isConstant() && otherVn->getOffset() == 0)
|
||||||
|
sgn = -1;
|
||||||
|
else
|
||||||
|
sgn = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sgn != 0) {
|
||||||
|
if (sgn == 1) {
|
||||||
|
data.opSetInput(compareOp, inVn, 1);
|
||||||
|
data.opSetInput(compareOp, otherVn, 0);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// \class RuleIdentityEl
|
/// \class RuleIdentityEl
|
||||||
/// \brief Collapse operations using identity element: `V + 0 => V`
|
/// \brief Collapse operations using identity element: `V + 0 => V`
|
||||||
///
|
///
|
||||||
|
|
|
@ -545,6 +545,26 @@ public:
|
||||||
virtual void getOpList(vector<uint4> &oplist) const;
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
};
|
};
|
||||||
|
class RuleSignShift : public Rule {
|
||||||
|
public:
|
||||||
|
RuleSignShift(const string &g) : Rule(g, 0, "signshift") {} ///< Constructor
|
||||||
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
||||||
|
return new RuleSignShift(getGroup());
|
||||||
|
}
|
||||||
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
|
};
|
||||||
|
class RuleTestSign : public Rule {
|
||||||
|
public:
|
||||||
|
RuleTestSign(const string &g) : Rule(g, 0, "testsign") {} ///< Constructor
|
||||||
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
||||||
|
return new RuleTestSign(getGroup());
|
||||||
|
}
|
||||||
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
|
};
|
||||||
class RuleIdentityEl : public Rule {
|
class RuleIdentityEl : public Rule {
|
||||||
public:
|
public:
|
||||||
RuleIdentityEl(const string &g) : Rule(g, 0, "identityel") {} ///< Constructor
|
RuleIdentityEl(const string &g) : Rule(g, 0, "identityel") {} ///< Constructor
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue