mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Merge remote-tracking branch 'origin/GP-4859_RuleOrCompare'
(Closes #6578)
This commit is contained in:
commit
05c1e55647
8 changed files with 175 additions and 197 deletions
|
@ -51,6 +51,7 @@ src/decompile/datatests/noforloop_alias.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/noforloop_globcall.xml||GHIDRA||||END|
|
src/decompile/datatests/noforloop_globcall.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/noforloop_iterused.xml||GHIDRA||||END|
|
src/decompile/datatests/noforloop_iterused.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/offsetarray.xml||GHIDRA||||END|
|
src/decompile/datatests/offsetarray.xml||GHIDRA||||END|
|
||||||
|
src/decompile/datatests/orcompare.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/packstructaccess.xml||GHIDRA||||END|
|
src/decompile/datatests/packstructaccess.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/partialmerge.xml||GHIDRA||||END|
|
src/decompile/datatests/partialmerge.xml||GHIDRA||||END|
|
||||||
src/decompile/datatests/partialsplit.xml||GHIDRA||||END|
|
src/decompile/datatests/partialsplit.xml||GHIDRA||||END|
|
||||||
|
|
|
@ -5519,10 +5519,10 @@ void ActionDatabase::universalAction(Architecture *conf)
|
||||||
actprop->addRule( new RulePiece2Zext("analysis") );
|
actprop->addRule( new RulePiece2Zext("analysis") );
|
||||||
actprop->addRule( new RulePiece2Sext("analysis") );
|
actprop->addRule( new RulePiece2Sext("analysis") );
|
||||||
actprop->addRule( new RulePopcountBoolXor("analysis") );
|
actprop->addRule( new RulePopcountBoolXor("analysis") );
|
||||||
actprop->addRule( new RuleOrMultiBool("analysis") );
|
|
||||||
actprop->addRule( new RuleXorSwap("analysis") );
|
actprop->addRule( new RuleXorSwap("analysis") );
|
||||||
actprop->addRule( new RuleLzcountShiftBool("analysis") );
|
actprop->addRule( new RuleLzcountShiftBool("analysis") );
|
||||||
actprop->addRule( new RuleFloatSign("analysis") );
|
actprop->addRule( new RuleFloatSign("analysis") );
|
||||||
|
actprop->addRule( new RuleOrCompare("analysis") );
|
||||||
actprop->addRule( new RuleSubvarAnd("subvar") );
|
actprop->addRule( new RuleSubvarAnd("subvar") );
|
||||||
actprop->addRule( new RuleSubvarSubpiece("subvar") );
|
actprop->addRule( new RuleSubvarSubpiece("subvar") );
|
||||||
actprop->addRule( new RuleSplitFlow("subvar") );
|
actprop->addRule( new RuleSplitFlow("subvar") );
|
||||||
|
|
|
@ -1124,9 +1124,6 @@ int4 SplitVarnode::applyRuleIn(SplitVarnode &in,Funcdata &data)
|
||||||
break;
|
break;
|
||||||
case CPUI_INT_OR:
|
case CPUI_INT_OR:
|
||||||
{
|
{
|
||||||
Equal2Form equal2form;
|
|
||||||
if (equal2form.applyRule(in,workop,workishi,data))
|
|
||||||
return 1;
|
|
||||||
LogicalForm logicalform;
|
LogicalForm logicalform;
|
||||||
if (logicalform.applyRule(in,workop,workishi,data))
|
if (logicalform.applyRule(in,workop,workishi,data))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1134,9 +1131,6 @@ int4 SplitVarnode::applyRuleIn(SplitVarnode &in,Funcdata &data)
|
||||||
break;
|
break;
|
||||||
case CPUI_INT_XOR:
|
case CPUI_INT_XOR:
|
||||||
{
|
{
|
||||||
Equal2Form equal2form;
|
|
||||||
if (equal2form.applyRule(in,workop,workishi,data))
|
|
||||||
return 1;
|
|
||||||
LogicalForm logicalform;
|
LogicalForm logicalform;
|
||||||
if (logicalform.applyRule(in,workop,workishi,data))
|
if (logicalform.applyRule(in,workop,workishi,data))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1151,6 +1145,9 @@ int4 SplitVarnode::applyRuleIn(SplitVarnode &in,Funcdata &data)
|
||||||
Equal1Form equal1form;
|
Equal1Form equal1form;
|
||||||
if (equal1form.applyRule(in,workop,workishi,data))
|
if (equal1form.applyRule(in,workop,workishi,data))
|
||||||
return 1;
|
return 1;
|
||||||
|
Equal2Form equal2form;
|
||||||
|
if (equal2form.applyRule(in,workop,workishi,data))
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CPUI_INT_LESS:
|
case CPUI_INT_LESS:
|
||||||
|
@ -1918,95 +1915,30 @@ bool Equal1Form::applyRule(SplitVarnode &i,PcodeOp *hop,bool workishi,Funcdata &
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Equal2Form::checkLoForm(void)
|
|
||||||
|
|
||||||
{ // Assuming we have equal <- or <- xor <- hi1, verify if we have the full equal form
|
|
||||||
Varnode *orvnin = orop->getIn(1-orhislot);
|
|
||||||
if (orvnin == lo1) { // lo2 is an implied 0
|
|
||||||
loxor = (PcodeOp *)0;
|
|
||||||
lo2 = (Varnode *)0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!orvnin->isWritten()) return false;
|
|
||||||
loxor = orvnin->getDef();
|
|
||||||
if (loxor->code() != CPUI_INT_XOR) return false;
|
|
||||||
if (loxor->getIn(0) == lo1) {
|
|
||||||
lo2 = loxor->getIn(1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (loxor->getIn(1) == lo1) {
|
|
||||||
lo2 = loxor->getIn(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Equal2Form::fillOutFromOr(Funcdata &data)
|
|
||||||
|
|
||||||
{ // We have filled in either or <- xor <- hi1, OR, or <- hi1
|
|
||||||
// Now try to fill in the rest of the form
|
|
||||||
Varnode *outvn = orop->getOut();
|
|
||||||
list<PcodeOp *>::const_iterator iter,enditer;
|
|
||||||
iter = outvn->beginDescend();
|
|
||||||
enditer = outvn->endDescend();
|
|
||||||
while(iter != enditer) {
|
|
||||||
equalop = *iter;
|
|
||||||
++iter;
|
|
||||||
if ((equalop->code() != CPUI_INT_EQUAL)&&(equalop->code() != CPUI_INT_NOTEQUAL)) continue;
|
|
||||||
if (!equalop->getIn(1)->isConstant()) continue;
|
|
||||||
if (equalop->getIn(1)->getOffset() != 0) continue;
|
|
||||||
|
|
||||||
if (!checkLoForm()) continue;
|
|
||||||
if (!replace(data)) continue;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Equal2Form::replace(Funcdata &data)
|
bool Equal2Form::replace(Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
if ((hi2==(Varnode *)0)&&(lo2==(Varnode *)0)) {
|
|
||||||
param2.initPartial(in.getSize(),0); // Double precis zero constant
|
|
||||||
return SplitVarnode::prepareBoolOp(in,param2,equalop);
|
|
||||||
}
|
|
||||||
if ((hi2==(Varnode *)0)&&(lo2->isConstant())) {
|
|
||||||
param2.initPartial(in.getSize(),lo2->getOffset());
|
|
||||||
return SplitVarnode::prepareBoolOp(in,param2,equalop);
|
|
||||||
}
|
|
||||||
if ((lo2==(Varnode *)0)&&(hi2->isConstant())) {
|
|
||||||
param2.initPartial(in.getSize(),hi2->getOffset() << 8*lo1->getSize());
|
|
||||||
return SplitVarnode::prepareBoolOp(in,param2,equalop);
|
|
||||||
}
|
|
||||||
if (lo2 == (Varnode *)0) {
|
|
||||||
// Equal to a zero extended and shifted var
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hi2 == (Varnode *)0) {
|
|
||||||
// Equal to a zero extended var
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hi2->isConstant()&&lo2->isConstant()) {
|
if (hi2->isConstant()&&lo2->isConstant()) {
|
||||||
uintb val = hi2->getOffset();
|
uintb val = hi2->getOffset();
|
||||||
val <<= 8*lo1->getSize();
|
val <<= 8*lo1->getSize();
|
||||||
val |= lo2->getOffset();
|
val |= lo2->getOffset();
|
||||||
param2.initPartial(in.getSize(),val);
|
param2.initPartial(in.getSize(),val);
|
||||||
return SplitVarnode::prepareBoolOp(in,param2,equalop);
|
return SplitVarnode::prepareBoolOp(in,param2,boolAndOr);
|
||||||
}
|
}
|
||||||
if (hi2->isConstant()||lo2->isConstant()) {
|
if (hi2->isConstant()||lo2->isConstant()) {
|
||||||
// Some kind of mixed form
|
// Some kind of mixed form
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
param2.initPartial(in.getSize(),lo2,hi2);
|
param2.initPartial(in.getSize(),lo2,hi2);
|
||||||
return SplitVarnode::prepareBoolOp(in,param2,equalop);
|
return SplitVarnode::prepareBoolOp(in,param2,boolAndOr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a known double precis input, look for double precision compares of the form
|
// Given a known double precis input, look for double precision compares of the form
|
||||||
// a == b, a != b
|
// a == b, a != b
|
||||||
//
|
//
|
||||||
// We look for
|
// We look for
|
||||||
// res = ((hi1 ^ hi2) | (lo1 ^ lo2) == 0)
|
// res = (hi1 == hi2) && (lo1 == lo2) or
|
||||||
// where hi2 or lo2 may be zero, and optimized out
|
// res = (hi1 != hi2) || (lo1 != lo2)
|
||||||
bool Equal2Form::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &data)
|
bool Equal2Form::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -2015,41 +1947,37 @@ bool Equal2Form::applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &d
|
||||||
in = i;
|
in = i;
|
||||||
hi1 = in.getHi();
|
hi1 = in.getHi();
|
||||||
lo1 = in.getLo();
|
lo1 = in.getLo();
|
||||||
|
OpCode eqCode = op->code();
|
||||||
if (op->code() == CPUI_INT_OR) {
|
int4 hi1slot = op->getSlot(hi1);
|
||||||
orop = op;
|
hi2 = op->getIn(1-hi1slot);
|
||||||
orhislot = op->getSlot(hi1);
|
Varnode *outvn = op->getOut();
|
||||||
hixor = (PcodeOp *)0;
|
|
||||||
hi2 = (Varnode *)0;
|
|
||||||
if (fillOutFromOr(data)) {
|
|
||||||
if (!param2.exceedsConstPrecision()) {
|
|
||||||
SplitVarnode::replaceBoolOp(data,equalop,in,param2,equalop->code());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // We see an XOR
|
|
||||||
hixor = op;
|
|
||||||
xorhislot = hixor->getSlot(hi1);
|
|
||||||
hi2 = hixor->getIn(1-xorhislot);
|
|
||||||
Varnode *vn = op->getOut();
|
|
||||||
list<PcodeOp *>::const_iterator iter,enditer;
|
list<PcodeOp *>::const_iterator iter,enditer;
|
||||||
iter = vn->beginDescend();
|
iter = outvn->beginDescend();
|
||||||
enditer = vn->endDescend();
|
enditer = outvn->endDescend();
|
||||||
while(iter != enditer) {
|
while(iter != enditer) {
|
||||||
orop = *iter;
|
boolAndOr = *iter;
|
||||||
++iter;
|
++iter;
|
||||||
if (orop->code() != CPUI_INT_OR) continue;
|
if (eqCode == CPUI_INT_EQUAL && boolAndOr->code() != CPUI_BOOL_AND) continue;
|
||||||
orhislot = orop->getSlot(vn);
|
if (eqCode == CPUI_INT_NOTEQUAL && boolAndOr->code() != CPUI_BOOL_OR) continue;
|
||||||
if (fillOutFromOr(data)) {
|
int4 slot = boolAndOr->getSlot(outvn);
|
||||||
if (!param2.exceedsConstPrecision()) {
|
Varnode *othervn = boolAndOr->getIn(1-slot);
|
||||||
SplitVarnode::replaceBoolOp(data,equalop,in,param2,equalop->code());
|
if (!othervn->isWritten()) continue;
|
||||||
|
PcodeOp *equalLo = othervn->getDef();
|
||||||
|
if (equalLo->code() != eqCode) continue;
|
||||||
|
if (equalLo->getIn(0) == lo1) {
|
||||||
|
lo2 = equalLo->getIn(1);
|
||||||
|
}
|
||||||
|
else if (equalLo->getIn(1) == lo1) {
|
||||||
|
lo2 = equalLo->getIn(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!replace(data)) continue;
|
||||||
|
if (param2.exceedsConstPrecision()) continue;
|
||||||
|
SplitVarnode::replaceBoolOp(data,boolAndOr,in,param2,eqCode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,12 +161,8 @@ public:
|
||||||
class Equal2Form {
|
class Equal2Form {
|
||||||
SplitVarnode in;
|
SplitVarnode in;
|
||||||
Varnode *hi1,*hi2,*lo1,*lo2;
|
Varnode *hi1,*hi2,*lo1,*lo2;
|
||||||
PcodeOp *equalop,*orop;
|
PcodeOp *boolAndOr;
|
||||||
PcodeOp *hixor,*loxor;
|
|
||||||
int4 orhislot,xorhislot;
|
|
||||||
SplitVarnode param2;
|
SplitVarnode param2;
|
||||||
bool checkLoForm(void);
|
|
||||||
bool fillOutFromOr(Funcdata &data);
|
|
||||||
bool replace(Funcdata &data);
|
bool replace(Funcdata &data);
|
||||||
public:
|
public:
|
||||||
bool applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &data);
|
bool applyRule(SplitVarnode &i,PcodeOp *op,bool workishi,Funcdata &data);
|
||||||
|
|
|
@ -672,20 +672,33 @@ uintb PcodeOp::getNZMaskLocal(bool cliploop) const
|
||||||
case CPUI_INT_MULT:
|
case CPUI_INT_MULT:
|
||||||
val = getIn(0)->getNZMask();
|
val = getIn(0)->getNZMask();
|
||||||
resmask = getIn(1)->getNZMask();
|
resmask = getIn(1)->getNZMask();
|
||||||
sz1 = (size > sizeof(uintb)) ? 8*size-1 : mostsigbit_set(val);
|
if (size > sizeof(uintb)) {
|
||||||
if (sz1 == -1)
|
resmask = fullmask;
|
||||||
resmask = 0;
|
}
|
||||||
else {
|
else {
|
||||||
sz2 = (size > sizeof(uintb)) ? 8*size-1 : mostsigbit_set(resmask);
|
sz1 = mostsigbit_set(val);
|
||||||
if (sz2 == -1)
|
sz2 = mostsigbit_set(resmask);
|
||||||
|
if (sz1 == -1 || sz2 == -1) {
|
||||||
resmask = 0;
|
resmask = 0;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (sz1 + sz2 < 8*size-2)
|
int4 l1 = leastsigbit_set(val);
|
||||||
fullmask >>= (8*size-2-sz1-sz2);
|
int4 l2 = leastsigbit_set(resmask);
|
||||||
sz1 = leastsigbit_set(val);
|
sa = l1 + l2;
|
||||||
sz2 = leastsigbit_set(resmask);
|
if (sa >= 8*size) {
|
||||||
resmask = (~((uintb)0))<<(sz1+sz2);
|
resmask = 0;
|
||||||
resmask &= fullmask;
|
}
|
||||||
|
else {
|
||||||
|
sz1 = sz1 - l1 + 1;
|
||||||
|
sz2 = sz2 - l2 + 1;
|
||||||
|
int4 total = sz1 + sz2;
|
||||||
|
if (sz1 == 1 || sz2 == 1)
|
||||||
|
total -= 1;
|
||||||
|
resmask = fullmask;
|
||||||
|
if (total < 8 * size)
|
||||||
|
resmask >>= (8*size - total);
|
||||||
|
resmask = (resmask << sa) & fullmask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -10309,66 +10309,6 @@ Varnode *RulePopcountBoolXor::getBooleanResult(Varnode *vn,int4 bitPos,int4 &con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \class RuleOrMultiBool
|
|
||||||
/// \brief Simplify boolean expressions that are combined through INT_OR
|
|
||||||
///
|
|
||||||
/// Convert expressions involving boolean values b1 and b2:
|
|
||||||
/// - `(b1 << 6) | (b2 << 2) != 0 => b1 || b2
|
|
||||||
void RuleOrMultiBool::getOpList(vector<uint4> &oplist) const
|
|
||||||
|
|
||||||
{
|
|
||||||
oplist.push_back(CPUI_INT_OR);
|
|
||||||
}
|
|
||||||
|
|
||||||
int4 RuleOrMultiBool::applyOp(PcodeOp *op,Funcdata &data)
|
|
||||||
|
|
||||||
{
|
|
||||||
Varnode *outVn = op->getOut();
|
|
||||||
list<PcodeOp *>::const_iterator iter;
|
|
||||||
|
|
||||||
if (popcount(outVn->getNZMask()) != 2) return 0;
|
|
||||||
for(iter=outVn->beginDescend();iter!=outVn->endDescend();++iter) {
|
|
||||||
PcodeOp *baseOp = *iter;
|
|
||||||
OpCode opc = baseOp->code();
|
|
||||||
// Result of INT_OR must be compared with zero
|
|
||||||
if (opc != CPUI_INT_EQUAL && opc != CPUI_INT_NOTEQUAL) continue;
|
|
||||||
Varnode *zerovn = baseOp->getIn(1);
|
|
||||||
if (!zerovn->isConstant()) continue;
|
|
||||||
if (zerovn->getOffset() != 0) continue;
|
|
||||||
int4 pos0 = leastsigbit_set(outVn->getNZMask());
|
|
||||||
int4 pos1 = mostsigbit_set(outVn->getNZMask());
|
|
||||||
int4 constRes0,constRes1;
|
|
||||||
Varnode *b1 = RulePopcountBoolXor::getBooleanResult(outVn, pos0, constRes0);
|
|
||||||
if (b1 == (Varnode *)0 && constRes0 != 1) continue;
|
|
||||||
Varnode *b2 = RulePopcountBoolXor::getBooleanResult(outVn, pos1, constRes1);
|
|
||||||
if (b2 == (Varnode *)0 && constRes1 != 1) continue;
|
|
||||||
if (b1 == (Varnode *)0 && b2 == (Varnode *)0) continue;
|
|
||||||
|
|
||||||
if (b1 == (Varnode *)0)
|
|
||||||
b1 = data.newConstant(1, 1);
|
|
||||||
if (b2 == (Varnode *)0)
|
|
||||||
b2 = data.newConstant(1, 1);
|
|
||||||
if (opc == CPUI_INT_EQUAL) {
|
|
||||||
PcodeOp *newOp = data.newOp(2,baseOp->getAddr());
|
|
||||||
Varnode *notIn = data.newUniqueOut(1, newOp);
|
|
||||||
data.opSetOpcode(newOp, CPUI_BOOL_OR);
|
|
||||||
data.opSetInput(newOp, b1, 0);
|
|
||||||
data.opSetInput(newOp, b2, 1);
|
|
||||||
data.opInsertBefore(newOp, baseOp);
|
|
||||||
data.opRemoveInput(baseOp, 1);
|
|
||||||
data.opSetInput(baseOp, notIn, 0);
|
|
||||||
data.opSetOpcode(baseOp, CPUI_BOOL_NEGATE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data.opSetOpcode(baseOp, CPUI_BOOL_OR);
|
|
||||||
data.opSetInput(baseOp, b1, 0);
|
|
||||||
data.opSetInput(baseOp, b2, 1);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Return \b true if concatenating with a SUBPIECE of the given Varnode is unusual
|
/// \brief Return \b true if concatenating with a SUBPIECE of the given Varnode is unusual
|
||||||
///
|
///
|
||||||
/// \param vn is the given Varnode
|
/// \param vn is the given Varnode
|
||||||
|
@ -10750,4 +10690,75 @@ int4 RuleFloatSignCleanup::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \class RuleOrCompare
|
||||||
|
/// \brief Simplify INT_OR in comparisons with 0.
|
||||||
|
///
|
||||||
|
/// `(V | W) == 0` => '(V == 0) && (W == 0)'
|
||||||
|
/// `(V | W) != 0` => '(V != 0) || (W != 0)'
|
||||||
|
void RuleOrCompare::getOpList(vector<uint4> &oplist) const
|
||||||
|
|
||||||
|
{
|
||||||
|
oplist.push_back(CPUI_INT_OR);
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 RuleOrCompare::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
Varnode *outvn = op->getOut();
|
||||||
|
list<PcodeOp *>::const_iterator iter;
|
||||||
|
bool hasCompares = false;
|
||||||
|
for(iter=outvn->beginDescend();iter!=outvn->endDescend();++iter) {
|
||||||
|
PcodeOp *compOp = *iter;
|
||||||
|
OpCode opc = compOp->code();
|
||||||
|
if (opc != CPUI_INT_EQUAL && opc != CPUI_INT_NOTEQUAL)
|
||||||
|
return 0;
|
||||||
|
if (!compOp->getIn(1)->constantMatch(0))
|
||||||
|
return 0;
|
||||||
|
hasCompares = true;
|
||||||
|
}
|
||||||
|
if (!hasCompares)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Varnode* V = op->getIn(0);
|
||||||
|
Varnode* W = op->getIn(1);
|
||||||
|
|
||||||
|
// make sure V and W are in SSA form
|
||||||
|
if (V->isFree()) return 0;
|
||||||
|
if (W->isFree()) return 0;
|
||||||
|
|
||||||
|
iter = outvn->beginDescend();
|
||||||
|
while(iter!=outvn->endDescend()) {
|
||||||
|
PcodeOp *equalOp = *iter;
|
||||||
|
OpCode opc = equalOp->code();
|
||||||
|
++iter; // Advance iterator immediately as equalOp gets modified
|
||||||
|
// construct the new segment:
|
||||||
|
// if the original condition was INT_EQUAL: BOOL_AND(INT_EQUAL(V, 0:|V|), INT_EQUAL(W, 0:|W|))
|
||||||
|
// if the original condition was INT_NOTEQUAL: BOOL_OR(INT_NOTEQUAL(V, 0:|V|), INT_NOTEQUAL(W, 0:|W|))
|
||||||
|
Varnode* zero_V = data.newConstant(V->getSize(), 0);
|
||||||
|
Varnode* zero_W = data.newConstant(W->getSize(), 0);
|
||||||
|
PcodeOp* eq_V = data.newOp(2, equalOp->getAddr());
|
||||||
|
data.opSetOpcode(eq_V, opc);
|
||||||
|
data.opSetInput(eq_V, V, 0);
|
||||||
|
data.opSetInput(eq_V, zero_V, 1);
|
||||||
|
PcodeOp* eq_W = data.newOp(2, equalOp->getAddr());
|
||||||
|
data.opSetOpcode(eq_W, opc);
|
||||||
|
data.opSetInput(eq_W, W, 0);
|
||||||
|
data.opSetInput(eq_W, zero_W, 1);
|
||||||
|
|
||||||
|
Varnode* eq_V_out = data.newUniqueOut(1, eq_V);
|
||||||
|
Varnode* eq_W_out = data.newUniqueOut(1, eq_W);
|
||||||
|
|
||||||
|
// make sure the comparisons' output is already defined
|
||||||
|
data.opInsertBefore(eq_V, equalOp);
|
||||||
|
data.opInsertBefore(eq_W, equalOp);
|
||||||
|
|
||||||
|
// change the original INT_EQUAL into a BOOL_AND, and INT_NOTEQUAL becomes BOOL_OR
|
||||||
|
data.opSetOpcode(equalOp, opc == CPUI_INT_EQUAL ? CPUI_BOOL_AND : CPUI_BOOL_OR);
|
||||||
|
data.opSetInput(equalOp, eq_V_out, 0);
|
||||||
|
data.opSetInput(equalOp, eq_W_out, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // End namespace ghidra
|
} // End namespace ghidra
|
||||||
|
|
|
@ -1604,17 +1604,6 @@ public:
|
||||||
static Varnode *getBooleanResult(Varnode *vn,int4 bitPos,int4 &constRes);
|
static Varnode *getBooleanResult(Varnode *vn,int4 bitPos,int4 &constRes);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RuleOrMultiBool : public Rule {
|
|
||||||
public:
|
|
||||||
RuleOrMultiBool(const string &g) : Rule( g, 0, "ormultibool") {} ///< Constructor
|
|
||||||
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
|
||||||
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
|
||||||
return new RuleOrMultiBool(getGroup());
|
|
||||||
}
|
|
||||||
virtual void getOpList(vector<uint4> &oplist) const;
|
|
||||||
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
|
||||||
};
|
|
||||||
|
|
||||||
class RulePiecePathology : public Rule {
|
class RulePiecePathology : public Rule {
|
||||||
static bool isPathology(Varnode *vn,Funcdata &data);
|
static bool isPathology(Varnode *vn,Funcdata &data);
|
||||||
static int4 tracePathologyForward(PcodeOp *op,Funcdata &data);
|
static int4 tracePathologyForward(PcodeOp *op,Funcdata &data);
|
||||||
|
@ -1672,5 +1661,16 @@ public:
|
||||||
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RuleOrCompare : public Rule {
|
||||||
|
public:
|
||||||
|
RuleOrCompare(const string &g) : Rule( g, 0, "orcompare") {} ///< Constructor
|
||||||
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
if (!grouplist.contains(getGroup())) return (Rule *)0;
|
||||||
|
return new RuleOrCompare(getGroup());
|
||||||
|
}
|
||||||
|
virtual void getOpList(vector<uint4> &oplist) const;
|
||||||
|
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
|
||||||
|
};
|
||||||
|
|
||||||
} // End namespace ghidra
|
} // End namespace ghidra
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<decompilertest>
|
||||||
|
<binaryimage arch="x86:LE:64:default:gcc">
|
||||||
|
<bytechunk space="ram" offset="0x100000" readonly="true">
|
||||||
|
f30f1efa83ff0a0f94c20fb6d201d283
|
||||||
|
fe140f94c00fb6c0c1e007b901000000
|
||||||
|
09c2740f833dd50f0000000f94c10fb6
|
||||||
|
c901c989c8c3f30f1efa81fec8000000
|
||||||
|
0f94c00fb6c0c1e00283ff640f94c10f
|
||||||
|
b6c909c881fa2c0100000f94c20fb6d2
|
||||||
|
c1e20409d07510833d920f000007ba02
|
||||||
|
0000000f44c2c3b801000000c3
|
||||||
|
</bytechunk>
|
||||||
|
<symbol space="ram" offset="0x100000" name="comp2"/>
|
||||||
|
<symbol space="ram" offset="0x100036" name="comp3"/>
|
||||||
|
</binaryimage>
|
||||||
|
<script>
|
||||||
|
<com>parse line extern int4 comp2(int4 a,int4 b);</com>
|
||||||
|
<com>parse line extern int4 comp3(int4 x,int4 y,int4 z);</com>
|
||||||
|
<com>lo fu comp2</com>
|
||||||
|
<com>dec</com>
|
||||||
|
<com>print C</com>
|
||||||
|
<com>lo fu comp3</com>
|
||||||
|
<com>dec</com>
|
||||||
|
<com>print C</com>
|
||||||
|
<com>quit</com>
|
||||||
|
</script>
|
||||||
|
<stringmatch name="Compare INT_OR #1" min="1" max="1">if \(a == 10 \|\| b == 0x14\)</stringmatch>
|
||||||
|
<stringmatch name="Compare INT_OR #2" min="1" max="1">if \(\(y != 200 && x != 100\) && z != 300\)</stringmatch>
|
||||||
|
</decompilertest>
|
Loading…
Add table
Add a link
Reference in a new issue