GP-2281 RuleOrMultiBool

This commit is contained in:
caheckman 2022-07-05 14:12:23 -04:00
parent 0f2e518957
commit 7abd4cb2ec
5 changed files with 98 additions and 0 deletions

View File

@ -40,6 +40,7 @@ src/decompile/datatests/pointersub.xml||GHIDRA||||END|
src/decompile/datatests/promotecompare.xml||GHIDRA||||END|
src/decompile/datatests/readvolatile.xml||GHIDRA||||END|
src/decompile/datatests/sbyte.xml||GHIDRA||||END|
src/decompile/datatests/statuscmp.xml||GHIDRA||||END|
src/decompile/datatests/threedim.xml||GHIDRA||||END|
src/decompile/datatests/twodim.xml||GHIDRA||||END|
src/decompile/datatests/union_datatype.xml||GHIDRA||||END|

View File

@ -5062,6 +5062,7 @@ void ActionDatabase::universalAction(Architecture *conf)
actprop->addRule( new RulePiece2Zext("analysis") );
actprop->addRule( new RulePiece2Sext("analysis") );
actprop->addRule( new RulePopcountBoolXor("analysis") );
actprop->addRule( new RuleOrMultiBool("analysis") );
actprop->addRule( new RuleXorSwap("analysis") );
actprop->addRule( new RuleSubvarAnd("subvar") );
actprop->addRule( new RuleSubvarSubpiece("subvar") );

View File

@ -9189,6 +9189,66 @@ 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
///
/// \param vn is the given Varnode

View File

@ -1485,6 +1485,17 @@ public:
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 {
static bool isPathology(Varnode *vn,Funcdata &data);
static int4 tracePathologyForward(PcodeOp *op,Funcdata &data);

View File

@ -0,0 +1,25 @@
<decompilertest>
<binaryimage arch="x86:LE:32:default:windows">
<!--
Floating-point compare that extracts 2 boolean results directly from the status word.
Decompiler should be able be able to collapse to a normal less-than-or-equal operation.
-->
<bytechunk space="ram" offset="0x1001516" readonly="true">
d90500000200d81d0000
0100dfe0f6c441740ec7050050010003
00000066e8d5fec3
</bytechunk>
<symbol name="statuscmp" space="ram" offset="0x1001516"/>
</binaryimage>
<script>
<com>lo fu statuscmp</com>
<com>map addr r0x10000 float4 val1</com>
<com>map addr r0x20000 float4 val2</com>
<com>decompile</com>
<com>print C</com>
<com>quit</com>
</script>
<stringmatch name="Status Compare #1" min="1" max="1">if \(val2 &lt;= val1\)</stringmatch>
<stringmatch name="Status Compare #2" min="0" max="0">&lt;&lt;</stringmatch>
<stringmatch name="Status Compare #3" min="0" max="0">\|</stringmatch>
</decompilertest>