mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
Added PIECE and INT_AND to RuleSLess2Zero. Added RuleRightShiftAnd
This commit is contained in:
parent
b0a54473df
commit
d18f09101c
3 changed files with 120 additions and 24 deletions
|
@ -4472,6 +4472,7 @@ void universal_action(Architecture *conf)
|
||||||
actprop->addRule( new RuleOrCollapse("analysis") );
|
actprop->addRule( new RuleOrCollapse("analysis") );
|
||||||
actprop->addRule( new RuleAndOrLump("analysis") );
|
actprop->addRule( new RuleAndOrLump("analysis") );
|
||||||
actprop->addRule( new RuleShiftBitops("analysis") );
|
actprop->addRule( new RuleShiftBitops("analysis") );
|
||||||
|
actprop->addRule( new RuleRightShiftAnd("analysis") );
|
||||||
actprop->addRule( new RuleNotDistribute("analysis") );
|
actprop->addRule( new RuleNotDistribute("analysis") );
|
||||||
actprop->addRule( new RuleHighOrderAnd("analysis") );
|
actprop->addRule( new RuleHighOrderAnd("analysis") );
|
||||||
actprop->addRule( new RuleAndDistribute("analysis") );
|
actprop->addRule( new RuleAndDistribute("analysis") );
|
||||||
|
|
|
@ -584,6 +584,35 @@ int4 RuleShiftBitops::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RuleRightShiftAnd::getOpList(vector<uint4> &oplist) const
|
||||||
|
|
||||||
|
{
|
||||||
|
oplist.push_back(CPUI_INT_RIGHT);
|
||||||
|
oplist.push_back(CPUI_INT_SRIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 RuleRightShiftAnd::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
Varnode *constVn = op->getIn(1);
|
||||||
|
if (!constVn->isConstant()) return 0;
|
||||||
|
Varnode *inVn = op->getIn(0);
|
||||||
|
if (!inVn->isWritten()) return 0;
|
||||||
|
PcodeOp *andOp = inVn->getDef();
|
||||||
|
if (andOp->code() != CPUI_INT_AND) return 0;
|
||||||
|
Varnode *maskVn = andOp->getIn(1);
|
||||||
|
if (!maskVn->isConstant()) return 0;
|
||||||
|
|
||||||
|
int4 sa = (int4)constVn->getOffset();
|
||||||
|
uintb mask = maskVn->getOffset() >> sa;
|
||||||
|
Varnode *rootVn = andOp->getIn(0);
|
||||||
|
uintb full = calc_mask(rootVn->getSize()) >> sa;
|
||||||
|
if (full != mask) return 0;
|
||||||
|
if (rootVn->isFree()) return 0;
|
||||||
|
data.opSetInput(op, rootVn, 0); // Bypass the INT_AND
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// \class RuleIntLessEqual
|
/// \class RuleIntLessEqual
|
||||||
/// \brief Convert LESSEQUAL to LESS: `V <= c => V < (c+1)`
|
/// \brief Convert LESSEQUAL to LESS: `V <= c => V < (c+1)`
|
||||||
void RuleIntLessEqual::getOpList(vector<uint4> &oplist) const
|
void RuleIntLessEqual::getOpList(vector<uint4> &oplist) const
|
||||||
|
@ -3124,10 +3153,13 @@ int4 RuleSignShift::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
PcodeOp *arithOp = *iter;
|
PcodeOp *arithOp = *iter;
|
||||||
++iter;
|
++iter;
|
||||||
switch(arithOp->code()) {
|
switch(arithOp->code()) {
|
||||||
case CPUI_INT_ADD:
|
|
||||||
case CPUI_INT_MULT:
|
|
||||||
case CPUI_INT_EQUAL:
|
case CPUI_INT_EQUAL:
|
||||||
case CPUI_INT_NOTEQUAL:
|
case CPUI_INT_NOTEQUAL:
|
||||||
|
if (arithOp->getIn(1)->isConstant())
|
||||||
|
doConversion = true;
|
||||||
|
break;
|
||||||
|
case CPUI_INT_ADD:
|
||||||
|
case CPUI_INT_MULT:
|
||||||
doConversion = true;
|
doConversion = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -5260,19 +5292,21 @@ int4 RuleSLess2Zero::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
Varnode *lvn,*rvn,*coeff,*avn;
|
Varnode *lvn,*rvn,*coeff,*avn;
|
||||||
PcodeOp *multop;
|
PcodeOp *feedOp;
|
||||||
|
OpCode feedOpCode;
|
||||||
lvn = op->getIn(0);
|
lvn = op->getIn(0);
|
||||||
rvn = op->getIn(1);
|
rvn = op->getIn(1);
|
||||||
|
|
||||||
if (lvn->isConstant()) {
|
if (lvn->isConstant()) {
|
||||||
if (!rvn->isWritten()) return 0;
|
if (!rvn->isWritten()) return 0;
|
||||||
if (lvn->getOffset() == 0) {
|
if (lvn->getOffset() == 0) {
|
||||||
multop = rvn->getDef();
|
feedOp = rvn->getDef();
|
||||||
if (multop->code() == CPUI_INT_MULT) {
|
feedOpCode = feedOp->code();
|
||||||
coeff = multop->getIn(1);
|
if (feedOpCode == CPUI_INT_MULT) {
|
||||||
|
coeff = feedOp->getIn(1);
|
||||||
if (!coeff->isConstant()) return 0;
|
if (!coeff->isConstant()) return 0;
|
||||||
if (coeff->getOffset() != calc_mask(coeff->getSize())) return 0;
|
if (coeff->getOffset() != calc_mask(coeff->getSize())) return 0;
|
||||||
avn = multop->getIn(0);
|
avn = feedOp->getIn(0);
|
||||||
if (avn->isFree()) return 0;
|
if (avn->isFree()) return 0;
|
||||||
data.opSetInput(op,avn,0);
|
data.opSetInput(op,avn,0);
|
||||||
data.opSetInput(op,lvn,1);
|
data.opSetInput(op,lvn,1);
|
||||||
|
@ -5280,8 +5314,9 @@ int4 RuleSLess2Zero::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lvn->getOffset() == calc_mask(lvn->getSize())) {
|
else if (lvn->getOffset() == calc_mask(lvn->getSize())) {
|
||||||
multop = rvn->getDef();
|
feedOp = rvn->getDef();
|
||||||
Varnode *hibit = getHiBit(multop);
|
feedOpCode = feedOp->code();
|
||||||
|
Varnode *hibit = getHiBit(feedOp);
|
||||||
if (hibit != (Varnode *) 0) { // Test for -1 s< (hi ^ lo)
|
if (hibit != (Varnode *) 0) { // Test for -1 s< (hi ^ lo)
|
||||||
if (hibit->isConstant())
|
if (hibit->isConstant())
|
||||||
data.opSetInput(op, data.newConstant(hibit->getSize(), hibit->getOffset()), 1);
|
data.opSetInput(op, data.newConstant(hibit->getSize(), hibit->getOffset()), 1);
|
||||||
|
@ -5291,44 +5326,70 @@ int4 RuleSLess2Zero::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
data.opSetInput(op, data.newConstant(hibit->getSize(), 0), 0);
|
data.opSetInput(op, data.newConstant(hibit->getSize(), 0), 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (multop->code() == CPUI_SUBPIECE) {
|
else if (feedOpCode == CPUI_SUBPIECE) {
|
||||||
avn = multop->getIn(0);
|
avn = feedOp->getIn(0);
|
||||||
if (avn->isFree())
|
if (avn->isFree())
|
||||||
return 0;
|
return 0;
|
||||||
if (rvn->getSize() + (int4) multop->getIn(1)->getOffset() == avn->getSize()) {
|
if (rvn->getSize() + (int4) feedOp->getIn(1)->getOffset() == avn->getSize()) {
|
||||||
// We have -1 s< SUB( avn, #hi )
|
// We have -1 s< SUB( avn, #hi )
|
||||||
data.opSetInput(op, avn, 1);
|
data.opSetInput(op, avn, 1);
|
||||||
data.opSetInput(op, data.newConstant(avn->getSize(), calc_mask(avn->getSize())), 0);
|
data.opSetInput(op, data.newConstant(avn->getSize(), calc_mask(avn->getSize())), 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (multop->code() == CPUI_INT_NEGATE) {
|
else if (feedOpCode == CPUI_INT_NEGATE) {
|
||||||
// We have -1 s< ~avn
|
// We have -1 s< ~avn
|
||||||
avn = multop->getIn(0);
|
avn = feedOp->getIn(0);
|
||||||
if (avn->isFree())
|
if (avn->isFree())
|
||||||
return 0;
|
return 0;
|
||||||
data.opSetInput(op, avn, 0);
|
data.opSetInput(op, avn, 0);
|
||||||
data.opSetInput(op, data.newConstant(avn->getSize(), 0), 1);
|
data.opSetInput(op, data.newConstant(avn->getSize(), 0), 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if (feedOpCode == CPUI_INT_AND) {
|
||||||
|
avn = feedOp->getIn(0);
|
||||||
|
if (avn->isFree() || rvn->loneDescend() == (PcodeOp *)0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Varnode *maskVn = feedOp->getIn(1);
|
||||||
|
if (maskVn->isConstant()) {
|
||||||
|
uintb mask = maskVn->getOffset();
|
||||||
|
mask >>= (8 * avn->getSize() - 1); // Fetch sign-bit
|
||||||
|
if ((mask & 1) != 0) {
|
||||||
|
// We have -1 s< avn & 0x8...
|
||||||
|
data.opSetInput(op, avn, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (feedOpCode == CPUI_PIECE) {
|
||||||
|
// We have -1 s< CONCAT(V,W)
|
||||||
|
avn = feedOp->getIn(0); // Most significant piece
|
||||||
|
if (avn->isFree())
|
||||||
|
return 0;
|
||||||
|
data.opSetInput(op, avn, 1);
|
||||||
|
data.opSetInput(op, data.newConstant(avn->getSize(),calc_mask(avn->getSize())), 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rvn->isConstant()) {
|
else if (rvn->isConstant()) {
|
||||||
if (!lvn->isWritten()) return 0;
|
if (!lvn->isWritten()) return 0;
|
||||||
if (rvn->getOffset() == 0) {
|
if (rvn->getOffset() == 0) {
|
||||||
multop = lvn->getDef();
|
feedOp = lvn->getDef();
|
||||||
if (multop->code() == CPUI_INT_MULT) {
|
feedOpCode = feedOp->code();
|
||||||
coeff = multop->getIn(1);
|
if (feedOpCode == CPUI_INT_MULT) {
|
||||||
|
coeff = feedOp->getIn(1);
|
||||||
if (!coeff->isConstant()) return 0;
|
if (!coeff->isConstant()) return 0;
|
||||||
if (coeff->getOffset() != calc_mask(coeff->getSize())) return 0;
|
if (coeff->getOffset() != calc_mask(coeff->getSize())) return 0;
|
||||||
avn = multop->getIn(0);
|
avn = feedOp->getIn(0);
|
||||||
if (avn->isFree()) return 0;
|
if (avn->isFree()) return 0;
|
||||||
data.opSetInput(op,avn,1);
|
data.opSetInput(op,avn,1);
|
||||||
data.opSetInput(op,rvn,0);
|
data.opSetInput(op,rvn,0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Varnode *hibit = getHiBit(multop);
|
Varnode *hibit = getHiBit(feedOp);
|
||||||
if (hibit != (Varnode *)0) { // Test for (hi ^ lo) s< 0
|
if (hibit != (Varnode *)0) { // Test for (hi ^ lo) s< 0
|
||||||
if (hibit->isConstant())
|
if (hibit->isConstant())
|
||||||
data.opSetInput(op,data.newConstant(hibit->getSize(),hibit->getOffset()),0);
|
data.opSetInput(op,data.newConstant(hibit->getSize(),hibit->getOffset()),0);
|
||||||
|
@ -5337,24 +5398,48 @@ int4 RuleSLess2Zero::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
data.opSetOpcode(op,CPUI_INT_NOTEQUAL);
|
data.opSetOpcode(op,CPUI_INT_NOTEQUAL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (multop->code() == CPUI_SUBPIECE) {
|
else if (feedOpCode == CPUI_SUBPIECE) {
|
||||||
avn = multop->getIn(0);
|
avn = feedOp->getIn(0);
|
||||||
if (avn->isFree()) return 0;
|
if (avn->isFree()) return 0;
|
||||||
if (lvn->getSize() + (int4)multop->getIn(1)->getOffset() == avn->getSize()) {
|
if (lvn->getSize() + (int4)feedOp->getIn(1)->getOffset() == avn->getSize()) {
|
||||||
// We have SUB( avn, #hi ) s< 0
|
// We have SUB( avn, #hi ) s< 0
|
||||||
data.opSetInput(op,avn,0);
|
data.opSetInput(op,avn,0);
|
||||||
data.opSetInput(op,data.newConstant(avn->getSize(),0),1);
|
data.opSetInput(op,data.newConstant(avn->getSize(),0),1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (multop->code() == CPUI_INT_NEGATE) {
|
else if (feedOpCode == CPUI_INT_NEGATE) {
|
||||||
// We have ~avn s< 0
|
// We have ~avn s< 0
|
||||||
avn = multop->getIn(0);
|
avn = feedOp->getIn(0);
|
||||||
if (avn->isFree()) return 0;
|
if (avn->isFree()) return 0;
|
||||||
data.opSetInput(op,avn,1);
|
data.opSetInput(op,avn,1);
|
||||||
data.opSetInput(op,data.newConstant(avn->getSize(),calc_mask(avn->getSize())),0);
|
data.opSetInput(op,data.newConstant(avn->getSize(),calc_mask(avn->getSize())),0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if (feedOpCode == CPUI_INT_AND) {
|
||||||
|
avn = feedOp->getIn(0);
|
||||||
|
if (avn->isFree() || lvn->loneDescend() == (PcodeOp *)0)
|
||||||
|
return 0;
|
||||||
|
Varnode *maskVn = feedOp->getIn(1);
|
||||||
|
if (maskVn->isConstant()) {
|
||||||
|
uintb mask = maskVn->getOffset();
|
||||||
|
mask >>= (8 * avn->getSize() - 1); // Fetch sign-bit
|
||||||
|
if ((mask & 1) != 0) {
|
||||||
|
// We have avn & 0x8... s< 0
|
||||||
|
data.opSetInput(op, avn, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (feedOpCode == CPUI_PIECE) {
|
||||||
|
// We have CONCAT(V,W) s< 0
|
||||||
|
avn = feedOp->getIn(0); // Most significant piece
|
||||||
|
if (avn->isFree())
|
||||||
|
return 0;
|
||||||
|
data.opSetInput(op, avn, 0);
|
||||||
|
data.opSetInput(op, data.newConstant(avn->getSize(), 0), 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,16 @@ 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 RuleRightShiftAnd : public Rule {
|
||||||
|
public:
|
||||||
|
RuleRightShiftAnd(const string &g) : Rule(g, 0, "rightshiftand") {} ///< Constructor
|
||||||
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
||||||
|
return new RuleRightShiftAnd(getGroup());
|
||||||
|
}
|
||||||
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
|
};
|
||||||
class RuleIntLessEqual : public Rule {
|
class RuleIntLessEqual : public Rule {
|
||||||
public:
|
public:
|
||||||
RuleIntLessEqual(const string &g) : Rule(g, 0, "intlessequal") {} ///< Constructor
|
RuleIntLessEqual(const string &g) : Rule(g, 0, "intlessequal") {} ///< Constructor
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue