mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +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 RuleTrivialBool("analysis") );
|
||||
actprop->addRule( new RuleTrivialShift("analysis") );
|
||||
actprop->addRule( new RuleSignShift("analysis") );
|
||||
actprop->addRule( new RuleTestSign("analysis") );
|
||||
actprop->addRule( new RuleIdentityEl("analysis") );
|
||||
actprop->addRule( new RuleOrMask("analysis") );
|
||||
actprop->addRule( new RuleAndMask("analysis") );
|
||||
|
|
|
@ -3095,6 +3095,98 @@ int4 RuleTrivialShift::applyOp(PcodeOp *op,Funcdata &data)
|
|||
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
|
||||
/// \brief Collapse operations using identity element: `V + 0 => V`
|
||||
///
|
||||
|
|
|
@ -545,6 +545,26 @@ public:
|
|||
virtual void getOpList(vector<uint4> &oplist) const;
|
||||
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 {
|
||||
public:
|
||||
RuleIdentityEl(const string &g) : Rule(g, 0, "identityel") {} ///< Constructor
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue