From 60b9e00e2c602168d2160ebb1bc2c20e2e7f2dd4 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Wed, 6 Sep 2023 22:20:06 +0000 Subject: [PATCH] GP-2311 Added hasNoDescend method to Varnode interface --- .../Decompiler/src/decompile/cpp/typeop.cc | 4 +- .../ghidra/program/model/pcode/PcodeOp.java | 38 +++++++++++++ .../ghidra/program/model/pcode/Varnode.java | 7 +++ .../program/model/pcode/VarnodeAST.java | 55 +++++++++++-------- 4 files changed, 78 insertions(+), 26 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc index 21261db84b..0d3543d26d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc @@ -1266,7 +1266,7 @@ Datatype *TypeOpIntSub::getOutputToken(const PcodeOp *op,CastStrategy *castStrat TypeOpIntCarry::TypeOpIntCarry(TypeFactory *t) : TypeOpFunc(t,CPUI_INT_CARRY,"CARRY",TYPE_BOOL,TYPE_UINT) { - opflags = PcodeOp::binary; + opflags = PcodeOp::binary | PcodeOp::commutative; addlflags = arithmetic_op; behave = new OpBehaviorIntCarry(); } @@ -1282,7 +1282,7 @@ string TypeOpIntCarry::getOperatorName(const PcodeOp *op) const TypeOpIntScarry::TypeOpIntScarry(TypeFactory *t) : TypeOpFunc(t,CPUI_INT_SCARRY,"SCARRY",TYPE_BOOL,TYPE_INT) { - opflags = PcodeOp::binary; + opflags = PcodeOp::binary | PcodeOp::commutative; behave = new OpBehaviorIntScarry(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java index 0023ee7c06..8c993de27a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeOp.java @@ -293,6 +293,15 @@ public class PcodeOp { return (output != null); } + /** + * Return true if the PcodeOp is commutative. + * If true, the operation has exactly two inputs that can be switched without affecting the output. + * @return true if the operation is commutative + */ + public final boolean isCommutative() { + return isCommutative(opcode); + } + /** * @return the sequence number this pcode is within some number of pcode */ @@ -715,4 +724,33 @@ public class PcodeOp { } return i.intValue(); } + + /** + * Return true if the given opcode represents a commutative operation. + * If true, the operation has exactly two inputs that can be switched without affecting the output. + * @param opcode is the opcode + * @return true if the operation is commutative + */ + public static boolean isCommutative(int opcode) { + switch (opcode) { + case PcodeOp.INT_EQUAL: + case PcodeOp.INT_NOTEQUAL: + case PcodeOp.INT_ADD: + case PcodeOp.INT_XOR: + case PcodeOp.INT_AND: + case PcodeOp.INT_OR: + case PcodeOp.INT_MULT: + case PcodeOp.BOOL_XOR: + case PcodeOp.BOOL_AND: + case PcodeOp.BOOL_OR: + case PcodeOp.FLOAT_EQUAL: + case PcodeOp.FLOAT_NOTEQUAL: + case PcodeOp.FLOAT_ADD: + case PcodeOp.FLOAT_MULT: + case PcodeOp.INT_CARRY: + case PcodeOp.INT_SCARRY: + return true; + } + return false; + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java index d484e99257..c55af76589 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/Varnode.java @@ -304,6 +304,13 @@ public class Varnode { return null; } + /** + * @return false if the Varnode has a PcodeOp reading it that is part of function data-flow + */ + public boolean hasNoDescend() { + return true; + } + /** * @return the high level variable this varnode represents */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java index 5b04b74d3c..e1ad26d908 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/VarnodeAST.java @@ -21,9 +21,7 @@ */ package ghidra.program.model.pcode; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.ListIterator; +import java.util.*; import ghidra.program.model.address.Address; @@ -93,18 +91,18 @@ public class VarnodeAST extends Varnode { public Iterator getDescendants() { return descend.iterator(); } - + @Override public PcodeOp getLoneDescend() { - Iterator iter = getDescendants(); - if (!iter.hasNext()) { - return null; // If there are no descendants return null + if (descend.size() != 1) { + return null; } - PcodeOp op = iter.next(); - if (iter.hasNext()) { - return null; // If there is more than one descendant return null - } - return op; + return descend.peekFirst(); + } + + @Override + public boolean hasNoDescend() { + return descend.isEmpty(); } @Override @@ -194,10 +192,11 @@ public class VarnodeAST extends Varnode { ListIterator iter = vn.descend.listIterator(); while (iter.hasNext()) { PcodeOp op = iter.next(); - if (op.getOutput() == this) + if (op.getOutput() == this) { continue; // Cannot be input to your own definition + } int num = op.getNumInputs(); - for (int i = 0; i < num; ++i) + for (int i = 0; i < num; ++i) { // Find reference to vn if (op.getInput(i) == vn) { vn.removeDescendant(op); @@ -206,6 +205,7 @@ public class VarnodeAST extends Varnode { op.setInput(this, i); break; } + } } } @@ -217,28 +217,35 @@ public class VarnodeAST extends Varnode { @Override public boolean equals(Object o) { - if (o == this) + if (o == this) { return true; - if (!(o instanceof VarnodeAST)) + } + if (!(o instanceof VarnodeAST)) { return false; + } VarnodeAST vn = (VarnodeAST) o; if (getOffset() != vn.getOffset() || getSize() != vn.getSize() || - getSpace() != vn.getSpace()) - return false; - if (isFree()) { - if (vn.isFree()) - return (uniqId == vn.uniqId); + getSpace() != vn.getSpace()) { return false; } - else if (vn.isFree()) + if (isFree()) { + if (vn.isFree()) { + return (uniqId == vn.uniqId); + } return false; - if (isInput() != vn.isInput()) + } + else if (vn.isFree()) { return false; + } + if (isInput() != vn.isInput()) { + return false; + } if (def != null) { PcodeOp vnDef = vn.getDef(); - if (vnDef == null) + if (vnDef == null) { return false; + } return (def.getSeqnum().equals(vnDef.getSeqnum())); } return true;