diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc index 73026a7bbd..bb28d61b02 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/transform.cc @@ -24,6 +24,8 @@ void TransformVar::createReplacement(Funcdata *fd) { + if (replacement != (Varnode *)0) + return; // Replacement already created switch(type) { case TransformVar::preexisting: replacement = vn; @@ -32,6 +34,7 @@ void TransformVar::createReplacement(Funcdata *fd) replacement = fd->newConstant(byteSize,val); break; case TransformVar::normal_temp: + case TransformVar::piece_temp: if (def == (TransformOp *)0) replacement = fd->newUnique(byteSize); else @@ -104,6 +107,15 @@ bool TransformOp::attemptInsertion(Funcdata *fd) return true; // Already inserted } +TransformManager::~TransformManager(void) + +{ + map::iterator iter; + for(iter=pieceMap.begin();iter!=pieceMap.end();++iter) { + delete [] (*iter).second; + } +} + /// \brief Should the address of the given Varnode be preserved when constructing a piece /// /// A new Varnode will be created that represents a logical piece of the given Varnode. @@ -127,16 +139,15 @@ bool TransformManager::preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) TransformVar *TransformManager::newPreexistingVarnode(Varnode *vn) { - newVarnodes.push_back(TransformVar()); - TransformVar *res = &newVarnodes.back(); + TransformVar *res = new TransformVar[1]; + pieceMap[vn->getCreateIndex()] = res; // Enter preexisting Varnode into map, so we don't make another placeholder res->vn = vn; res->replacement = (Varnode *)0; res->byteSize = vn->getSize(); res->bitSize = res->byteSize * 8; res->def = (TransformOp *)0; res->type = TransformVar::preexisting; - MapKey key(vn->getCreateIndex(),0); - pieceMap[key] = res; // Enter preexisting Varnode into map, so we don't make another placeholder + res->flags = TransformVar::split_terminator; return res; } @@ -152,6 +163,7 @@ TransformVar *TransformManager::newUnique(int4 size) res->bitSize = size * 8; res->def = (TransformOp *)0; res->type = TransformVar::normal_temp; + res->flags = 0; return res; } @@ -168,6 +180,7 @@ TransformVar *TransformManager::newConstant(int4 size,uintb val) res->val = val; res->def = (TransformOp *)0; res->type = TransformVar::constant; + res->flags = 0; return res; } @@ -183,6 +196,7 @@ TransformVar *TransformManager::newIop(Varnode *vn) res->val = vn->getOffset(); // The encoded iop res->def = (TransformOp *)0; res->type = TransformVar::constant_iop; + res->flags = 0; return res; } @@ -195,8 +209,8 @@ TransformVar *TransformManager::newIop(Varnode *vn) TransformVar *TransformManager::newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset) { - newVarnodes.push_back(TransformVar()); - TransformVar *res = &newVarnodes.back(); + TransformVar *res = new TransformVar[1]; + pieceMap[vn->getCreateIndex()] = res; res->vn = vn; res->replacement = (Varnode *)0; res->bitSize = bitSize; @@ -205,10 +219,9 @@ TransformVar *TransformManager::newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset if (preserveAddress(vn, bitSize, lsbOffset)) res->type = TransformVar::piece; else - res->type = TransformVar::normal_temp; + res->type = TransformVar::piece_temp; + res->flags = TransformVar::split_terminator; res->val = lsbOffset; - MapKey key(vn->getCreateIndex(),lsbOffset); - pieceMap[key] = res; return res; } @@ -216,29 +229,29 @@ TransformVar *TransformManager::newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset /// /// Given a big Varnode and a lane description, create placeholders for all the explicit pieces /// that the big Varnode will be split into. -/// \param res will hold references to the new placeholders in significance order /// \param vn is the big Varnode to split /// \param description shows how the big Varnode will be split -void TransformManager::newSplit(vector &res,Varnode *vn,const LaneDescription &description) +/// \return an array of the new TransformVar placeholders from least to most significant +TransformVar *TransformManager::newSplit(Varnode *vn,const LaneDescription &description) { int4 num = description.getNumLanes(); - res.resize(num,(TransformVar *)0); + TransformVar *res = new TransformVar[num]; + pieceMap[vn->getCreateIndex()] = res; for(int4 i=0;ivn = vn; newVar->replacement = (Varnode *)0; newVar->byteSize = description.getSize(i); newVar->bitSize = newVar->byteSize * 8; newVar->def = (TransformOp *)0; newVar->type = TransformVar::piece; + newVar->flags = 0; newVar->val = bitpos; - MapKey key(vn->getCreateIndex(),bitpos); - pieceMap[key] = newVar; - res[i] = newVar; } + res[num-1].flags = TransformVar::split_terminator; + return res; } /// \brief Create a new placeholder op intended to replace an existing op @@ -317,9 +330,8 @@ TransformOp *TransformManager::newPreexistingOp(int4 numParams,OpCode opc,PcodeO TransformVar *TransformManager::getPreexistingVarnode(Varnode *vn) { - map::const_iterator iter; - MapKey key(vn->getCreateIndex(),0); - iter = pieceMap.find(key); + map::const_iterator iter; + iter = pieceMap.find(vn->getCreateIndex()); if (iter != pieceMap.end()) return (*iter).second; return newPreexistingVarnode(vn); @@ -334,11 +346,13 @@ TransformVar *TransformManager::getPreexistingVarnode(Varnode *vn) TransformVar *TransformManager::getPiece(Varnode *vn,int4 bitSize,int4 lsbOffset) { - map::const_iterator iter; - MapKey key(vn->getCreateIndex(),lsbOffset); - iter = pieceMap.find(key); + map::const_iterator iter; + iter = pieceMap.find(vn->getCreateIndex()); if (iter != pieceMap.end()) { - return (*iter).second; + TransformVar *res = (*iter).second; + if (res->bitSize != bitSize || res->val != lsbOffset) + throw LowlevelError("Cannot create multiple pieces for one Varnode through getPiece"); + return res; } return newPiece(vn,bitSize,lsbOffset); } @@ -347,25 +361,18 @@ TransformVar *TransformManager::getPiece(Varnode *vn,int4 bitSize,int4 lsbOffset /// /// Given a big Varnode and a lane description, look up placeholders for all its /// explicit pieces. If they don't exist, create them. -/// \param res will hold the array of recovered placeholders in significance order /// \param vn is the big Varnode to split /// \param description shows how the big Varnode will be split -void TransformManager::getSplit(vector &res,Varnode *vn,const LaneDescription &description) +/// \return an array of the TransformVar placeholders from least to most significant +TransformVar *TransformManager::getSplit(Varnode *vn,const LaneDescription &description) { - map::const_iterator iter; - MapKey key(vn->getCreateIndex(),0); - iter = pieceMap.lower_bound(key); - if (iter != pieceMap.end() && (*iter).first.getCreateIndex() == vn->getCreateIndex()) { - int4 num = description.getNumLanes(); - res.resize(num,(TransformVar *)0); - for(int4 i=0;i::const_iterator iter; + iter = pieceMap.find(vn->getCreateIndex()); + if (iter != pieceMap.end()) { + return (*iter).second; } - newSplit(res,vn,description); + return newSplit(vn,description); } void TransformManager::opSetInput(TransformOp *rop,TransformVar *rvn,int4 slot) @@ -408,6 +415,15 @@ void TransformManager::createOps(void) void TransformManager::createVarnodes(void) { + map::iterator piter; + for(piter=pieceMap.begin();piter!=pieceMap.end();++piter) { + TransformVar *vArray = (*piter).second; + for(int4 i=0;;++i) { + vArray[i].createReplacement(fd); + if ((vArray[i].flags & TransformVar::split_terminator)!=0) + break; + } + } list::iterator iter; for(iter=newVarnodes.begin();iter!=newVarnodes.end();++iter) { (*iter).createReplacement(fd); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/transform.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/transform.hh index b1fe0098c1..f0d9858e29 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/transform.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/transform.hh @@ -24,18 +24,25 @@ class TransformOp; class TransformVar { friend class TransformManager; public: - /// Types of replacement Varnodes + /// \brief Types of replacement Varnodes enum { piece = 1, ///< New Varnode is a piece of an original Varnode preexisting = 2, ///< Varnode preexisted in the original data-flow normal_temp = 3, ///< A new temporary (unique space) Varnode - constant = 4, ///< A new constant Varnode - constant_iop = 5, ///< Special iop constant encoding a PcodeOp reference + piece_temp = 4, ///< A temporary representing a piece of an original Varnode + constant = 5, ///< A new constant Varnode + constant_iop = 6, ///< Special iop constant encoding a PcodeOp reference + }; + /// \brief Flags for a TransformVar + enum { + split_terminator = 1, ///< The last (most significant piece) of a split array + def_traverse = 2 ///< The op defining this Varnode has already been traversed }; private: Varnode *vn; ///< Original \b big Varnode of which \b this is a component Varnode *replacement; ///< The new explicit lane Varnode uint4 type; ///< Type of new Varnode + uint4 flags; ///< Boolean properties of the placeholder int4 byteSize; ///< Size of the lane Varnode in bytes int4 bitSize; ///< Size of the logical value in bits uintb val; ///< Value of constant or (bit) position within the original big Varnode @@ -88,18 +95,8 @@ public: /// If the interpretation is consistent for data-flow involving the Varnode, split /// Varnode and data-flow into explicit operations on the lanes. class TransformManager { - /// \brief Key for mapping from a \b big Varnode to its pieces - class MapKey { - uint4 create_index; ///< Creation index of Varnode being split - int4 position; ///< Position within the Varnode - public: - MapKey(uint4 index,int4 pos) { create_index = index; position = pos; } ///< Constructor - uint4 getCreateIndex(void) const { return create_index; } ///< Return the creation index part of \b this key - bool operator<(const MapKey &op2) const; ///< Comparator function for \b this key - }; - Funcdata *fd; ///< Function being operated on - map pieceMap; ///< Map from large Varnodes to their new pieces + map pieceMap; ///< Map from large Varnodes to their new pieces list newVarnodes; ///< Storage for Varnode placeholder nodes list newOps; ///< Storage for PcodeOp placeholder nodes @@ -111,37 +108,27 @@ class TransformManager { void placeInputs(void); ///< Set input Varnodes for all new ops public: TransformManager(Funcdata *f) { fd = f; } ///< Constructor - virtual ~TransformManager(void) {} + virtual ~TransformManager(void); ///< Destructor virtual bool preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) const; TransformVar *newPreexistingVarnode(Varnode *vn); ///< Make placeholder for preexisting Varnode TransformVar *newUnique(int4 size); ///< Make placeholder for new unique space Varnode TransformVar *newConstant(int4 size,uintb val); ///< Make placeholder for constant Varnode TransformVar *newIop(Varnode *vn); ///< Make placeholder for special iop constant TransformVar *newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset); ///< Make placeholder for piece of a Varnode - void newSplit(vector &res,Varnode *vn,const LaneDescription &description); + TransformVar *newSplit(Varnode *vn,const LaneDescription &description); TransformOp *newOpReplace(int4 numParams,OpCode opc,PcodeOp *replace); TransformOp *newOp(int4 numParams,OpCode opc,TransformOp *follow); TransformOp *newPreexistingOp(int4 numParams,OpCode opc,PcodeOp *originalOp); TransformVar *getPreexistingVarnode(Varnode *vn); ///< Get (or create) placeholder for preexisting Varnode TransformVar *getPiece(Varnode *vn,int4 bitSize,int4 lsbOffset); ///< Get (or create) placeholder piece - void getSplit(vector &res,Varnode *vn,const LaneDescription &description); + TransformVar *getSplit(Varnode *vn,const LaneDescription &description); void opSetInput(TransformOp *rop,TransformVar *rvn,int4 slot); ///< Mark given variable as input to given op void opSetOutput(TransformOp *rop,TransformVar *rvn); ///< Mark given variable as output of given op void apply(void); ///< Apply the full transform to the function }; -/// \param op2 is the other key to compare with \b this -/// \return \b true if \b this should come before the other key -inline bool TransformManager::MapKey::operator<(const TransformManager::MapKey &op2) const - -{ - if (create_index != op2.create_index) - return (create_index < op2.create_index); - return (position < op2.position); -} - /// \param rop is the given placeholder op whose input is set /// \param rvn is the placeholder variable to set /// \param slot is the input position to set