From 7abd4cb2ec393f29ad109b3a7f75b6d00edce833 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Tue, 5 Jul 2022 14:12:23 -0400 Subject: [PATCH] GP-2281 RuleOrMultiBool --- .../Decompiler/certification.manifest | 1 + .../src/decompile/cpp/coreaction.cc | 1 + .../src/decompile/cpp/ruleaction.cc | 60 +++++++++++++++++++ .../src/decompile/cpp/ruleaction.hh | 11 ++++ .../src/decompile/datatests/statuscmp.xml | 25 ++++++++ 5 files changed, 98 insertions(+) create mode 100644 Ghidra/Features/Decompiler/src/decompile/datatests/statuscmp.xml diff --git a/Ghidra/Features/Decompiler/certification.manifest b/Ghidra/Features/Decompiler/certification.manifest index cb980440f1..2784b37674 100644 --- a/Ghidra/Features/Decompiler/certification.manifest +++ b/Ghidra/Features/Decompiler/certification.manifest @@ -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| diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc index 2513d3cb02..b6099ff4d0 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc @@ -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") ); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc index b5bdb4700f..042ac782bf 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc @@ -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 &oplist) const + +{ + oplist.push_back(CPUI_INT_OR); +} + +int4 RuleOrMultiBool::applyOp(PcodeOp *op,Funcdata &data) + +{ + Varnode *outVn = op->getOut(); + list::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 diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh index 17ede9725a..baf91c1f47 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh @@ -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 &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); diff --git a/Ghidra/Features/Decompiler/src/decompile/datatests/statuscmp.xml b/Ghidra/Features/Decompiler/src/decompile/datatests/statuscmp.xml new file mode 100644 index 0000000000..7c3ea30d91 --- /dev/null +++ b/Ghidra/Features/Decompiler/src/decompile/datatests/statuscmp.xml @@ -0,0 +1,25 @@ + + + + + d90500000200d81d0000 +0100dfe0f6c441740ec7050050010003 +00000066e8d5fec3 + + + + +if \(val2 <= val1\) +<< +\| +