Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5695,6 +5695,7 @@ void ActionDatabase::universalAction(Architecture *conf)
actcleanup->addRule( new RuleSubRight("cleanup") );
actcleanup->addRule( new RuleFloatSignCleanup("cleanup") );
actcleanup->addRule( new RuleExpandLoad("cleanup") );
actcleanup->addRule( new RuleImpliedBool("cleanup") );
actcleanup->addRule( new RulePtrsubCharConstant("cleanup") );
actcleanup->addRule( new RuleExtensionPush("cleanup") );
actcleanup->addRule( new RulePieceStructure("cleanup") );
Expand Down
63 changes: 63 additions & 0 deletions Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "coreaction.hh"
#include "rangeutil.hh"
#include "multiprecision.hh"
#include "type.hh"

namespace ghidra {

Expand Down Expand Up @@ -7288,6 +7289,68 @@ int4 RuleSubRight::applyOp(PcodeOp *op,Funcdata &data)
return 1;
}

/// \class RuleImpliedBool
/// \brief Cleanup: Convert boolean comparisons with INT_EQUAL and INT_NOTEQUAL.
/// `V == true ==> V`
/// `V != true ==> !V`
/// `V == false ==> !V`
/// `V != false ==> V`
void RuleImpliedBool::getOpList(vector<uint4> &oplist) const

{
oplist.push_back(CPUI_INT_EQUAL);
oplist.push_back(CPUI_INT_NOTEQUAL);
}

int4 RuleImpliedBool::applyOp(PcodeOp *op,Funcdata &data)

{
Varnode *var = op->getIn(0);
Varnode *value = op->getIn(1);

if (var->isConstant()) {
Varnode *tmp = var;
var = value;
value = tmp;
}

// Exactly one of the inputs needs to be a constant
if (!value->isConstant()) return 0;
if (var->isConstant()) return 0;

// The variable needs to have a boolean type
// Sadly, there is no direct boolean type, so this is a bit hacky
Datatype *ct = var->getType();
if (!(var->getNZMask() == 0xFF && ct->getSize() == 1 && ct->getDisplayName() == "bool")) return 0;

bool should_flip = (op->code() == CPUI_INT_EQUAL) != (value->constantMatch(1));

if (should_flip) {
// Let's make the CPUI_INT_EQUAL a CPUI_BOOL_NEGATE
data.opSetOpcode(op, CPUI_BOOL_NEGATE);
data.opRemoveInput(op, 1);
data.opSetInput(op, var, 0);
} else {
// The CPUI_INT_EQUAL becomes a NOP, so just connect the output directly
Varnode *out = op->getOut();

// TODO: Add support if the output of the equality is used in multiple
// places. This seems to be pretty uncommon though...
PcodeOp *res = out->loneDescend();
if (res == ((PcodeOp *)0)) return 0;

int4 slot_id = res->getSlot(out);
data.opUnsetInput(res, slot_id);
data.opSetInput(res, var, slot_id);

// We bypassed the INT_EQUAL, so it's time to remove it
data.opDestroy(op);
// data.opUnsetOutput(op);
}

return 1;
}

/// \brief Try to push constant pointer further
///
/// Given a PTRSUB has been collapsed to a constant COPY of a string address,
Expand Down
11 changes: 11 additions & 0 deletions Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,17 @@ public:
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};

class RuleImpliedBool : public Rule {
public:
RuleImpliedBool(const string &g) : Rule( g, 0, "impliedbool") {} ///< Constructor
virtual Rule *clone(const ActionGroupList &grouplist) const {
if (!grouplist.contains(getGroup())) return (Rule *)0;
return new RuleImpliedBool(getGroup());
}
virtual void getOpList(vector<uint4> &oplist) const;
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};

class RuleExpandLoad : public Rule {
static bool checkAndComparison(Varnode *vn);
static void modifyAndComparison(Funcdata &data,Varnode *oldVn,Varnode *newVn,Datatype *dt,int4 offset);
Expand Down