mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 05:32:14 +00:00
GP-2281 RuleOrMultiBool
This commit is contained in:
parent
0f2e518957
commit
7abd4cb2ec
@ -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|
|
||||
|
@ -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") );
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 <= val1\)</stringmatch>
|
||||
<stringmatch name="Status Compare #2" min="0" max="0"><<</stringmatch>
|
||||
<stringmatch name="Status Compare #3" min="0" max="0">\|</stringmatch>
|
||||
</decompilertest>
|
Loading…
Reference in New Issue
Block a user