diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc index 9d8b080530..3656c0df58 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.cc @@ -364,7 +364,7 @@ void DynamicHash::pieceTogetherHash(const Varnode *root,uint4 method) hash <<= 4; hash |= method; // 4-bits hash <<= 7; - hash |= (uint8)op->code(); // 7-bits + hash |= (uint8)transtable[op->code()]; // 7-bits hash <<= 5; hash |= (uint8)(slot & 0x1f); // 5-bits @@ -607,6 +607,25 @@ PcodeOp *DynamicHash::findOp(const Funcdata *fd,const Address &addr,uint8 h) return oplist2[pos]; } +/// Otherwise preserve the order of the list. +/// \param varlist is the given list of Varnodes to check +void DynamicHash::dedupVarnodes(vector &varlist) + +{ + if (varlist.size() < 2) return; + vector resList; + for(int4 i=0;iisMark()) { + vn->setMark(); + resList.push_back(vn); + } + } + for(int4 i=0;iclearMark(); + varlist.swap(resList); +} + /// \brief Get the Varnodes immediately attached to PcodeOps at the given address /// /// Varnodes can be either inputs or outputs to the PcodeOps. The op-code, slot, and @@ -619,7 +638,7 @@ PcodeOp *DynamicHash::findOp(const Funcdata *fd,const Address &addr,uint8 h) void DynamicHash::gatherFirstLevelVars(vector &varlist,const Funcdata *fd,const Address &addr,uint8 h) { - OpCode opc = getOpCodeFromHash(h); + uint4 opcVal = getOpCodeFromHash(h); int4 slot = getSlotFromHash(h); bool isnotattached = getIsNotAttached(h); PcodeOpTree::const_iterator iter = fd->beginOp(addr); @@ -629,7 +648,7 @@ void DynamicHash::gatherFirstLevelVars(vector &varlist,const Funcdata PcodeOp *op = (*iter).second; ++iter; if (op->isDead()) continue; - if (op->code() != opc) continue; + if (transtable[op->code()] != opcVal) continue; if (slot <0) { Varnode *vn = op->getOut(); if (vn != (Varnode *)0) { @@ -655,6 +674,7 @@ void DynamicHash::gatherFirstLevelVars(vector &varlist,const Funcdata varlist.push_back(vn); } } + dedupVarnodes(varlist); } /// \brief Place all PcodeOps at the given address in the provided container @@ -697,11 +717,11 @@ uint4 DynamicHash::getMethodFromHash(uint8 h) /// The hash encodes the op-code of the p-code op attached to the root Varnode /// \param h is the hash value -/// \return the op-code -OpCode DynamicHash::getOpCodeFromHash(uint8 h) +/// \return the op-code as an integer +uint4 DynamicHash::getOpCodeFromHash(uint8 h) { - return (OpCode)((h>>37)&0x7f); + return (h>>37)&0x7f; } /// The hash encodes the position of the root Varnode within the list of hash collisions diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh index 2a500d56b2..1355f9fe11 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/dynamic.hh @@ -77,6 +77,7 @@ class DynamicHash { void gatherUnmarkedOp(void); ///< Mark any new PcodeOps in the sub-graph void pieceTogetherHash(const Varnode *root,uint4 method); ///< Clean-up and piece together formal hash value static void moveOffSkip(const PcodeOp *&op,int4 &slot); ///< Convert given PcodeOp to a non-skip op by following data-flow + static void dedupVarnodes(vector &varlist); ///< Remove any duplicate Varnodes in given list public: void clear(void); ///< Called for each additional hash (after the first) void calcHash(const Varnode *root,uint4 method); ///< Calculate the hash for given Varnode and method @@ -92,7 +93,7 @@ public: static void gatherOpsAtAddress(vector &opList,const Funcdata *fd,const Address &addr); static int4 getSlotFromHash(uint8 h); ///< Retrieve the encoded slot from a hash static uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash - static OpCode getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash + static uint4 getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash static uint4 getPositionFromHash(uint8 h); ///< Retrieve the encoded position from a hash static uint4 getTotalFromHash(uint8 h); ///< Retrieve the encoded collision total from a hash static bool getIsNotAttached(uint8 h); ///< Retrieve the attachment boolean from a hash diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicHash.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicHash.java index 5cf5d08333..17642fef21 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicHash.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/DynamicHash.java @@ -415,7 +415,7 @@ public class DynamicHash { hash <<= 4; hash |= method; // 4-bits hash <<= 7; - hash |= op.getOpcode(); // 7-bits + hash |= transtable[op.getOpcode()]; // 7-bits hash <<= 5; hash |= slot & 0x1f; // 5-bits @@ -705,6 +705,21 @@ public class DynamicHash { } } + private static void dedupVarnodes(ArrayList varlist) { + if (varlist.size() < 2) { + return; + } + ArrayList resList = new ArrayList<>(); + HashSet hashSet = new HashSet<>(); + for (Varnode vn : varlist) { + if (hashSet.add(vn)) { + resList.add(vn); + } + } + varlist.clear(); + varlist.addAll(resList); + } + public static void gatherFirstLevelVars(ArrayList varlist, PcodeSyntaxTree fd, Address addr, long h) { int opc = getOpCodeFromHash(h); @@ -714,7 +729,7 @@ public class DynamicHash { while (iter.hasNext()) { PcodeOp op = iter.next(); - if (op.getOpcode() != opc) { + if (transtable[op.getOpcode()] != opc) { continue; } if (slot < 0) { @@ -745,6 +760,7 @@ public class DynamicHash { varlist.add(vn); } } + dedupVarnodes(varlist); } public static int getSlotFromHash(long h) {