bit based pieces, preserveAddress virtual method

This commit is contained in:
caheckman 2019-10-05 15:49:30 -04:00
parent ace956c215
commit 0af94c23c1
2 changed files with 66 additions and 27 deletions

View file

@ -29,21 +29,28 @@ void TransformVar::createReplacement(Funcdata *fd)
replacement = vn; replacement = vn;
break; break;
case TransformVar::constant: case TransformVar::constant:
replacement = fd->newConstant(size,val); replacement = fd->newConstant(byteSize,val);
break; break;
case TransformVar::normal_temp: case TransformVar::normal_temp:
if (def == (TransformOp *)0) if (def == (TransformOp *)0)
replacement = fd->newUnique(size); replacement = fd->newUnique(byteSize);
else else
replacement = fd->newUniqueOut(size,def->replacement); replacement = fd->newUniqueOut(byteSize,def->replacement);
break; break;
case TransformVar::piece: case TransformVar::piece:
{ {
Address addr = vn->getAddr() + (int4)val; int4 bytePos = (int4)val;
if ((bytePos & 7) != 0)
throw LowlevelError("Varnode piece is not byte aligned");
bytePos >>= 3;
if (vn->getSpace()->isBigEndian())
bytePos = vn->getSize() - bytePos - byteSize;
Address addr = vn->getAddr() + bytePos;
if (def == (TransformOp *)0) if (def == (TransformOp *)0)
replacement = fd->newVarnode(size,addr); replacement = fd->newVarnode(byteSize,addr);
else else
replacement = fd->newVarnodeOut(size, addr, def->replacement); replacement = fd->newVarnodeOut(byteSize, addr, def->replacement);
// TODO: fd->preserveProperties(vn,replacement,bytePos);
break; break;
} }
case TransformVar::constant_iop: case TransformVar::constant_iop:
@ -97,6 +104,24 @@ bool TransformOp::attemptInsertion(Funcdata *fd)
return true; // Already inserted return true; // Already inserted
} }
/// \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.
/// This routine determines whether the new Varnode should be constructed using
/// storage which overlaps the given Varnode. It returns \b true if overlapping storage
/// should be used, \b false if the new Varnode should be constructed as a unique temporary.
/// \param vn is the given Varnode
/// \param bitSize is the logical size of the Varnode piece being constructed
/// \param lsbOffset is the least significant bit position of the logical value within the given Varnode
/// \return \b true if overlapping storage should be used in construction
bool TransformManager::preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) const
{
if ((lsbOffset & 7) != 0) return false; // Logical value not aligned
if (vn->getSpace()->getType() == IPTR_INTERNAL) return false;
return true;
}
/// \param vn is the preexisting Varnode to create a placeholder for /// \param vn is the preexisting Varnode to create a placeholder for
/// \return the new placeholder node /// \return the new placeholder node
TransformVar *TransformManager::newPreexistingVarnode(Varnode *vn) TransformVar *TransformManager::newPreexistingVarnode(Varnode *vn)
@ -106,7 +131,8 @@ TransformVar *TransformManager::newPreexistingVarnode(Varnode *vn)
TransformVar *res = &newVarnodes.back(); TransformVar *res = &newVarnodes.back();
res->vn = vn; res->vn = vn;
res->replacement = (Varnode *)0; res->replacement = (Varnode *)0;
res->size = vn->getSize(); res->byteSize = vn->getSize();
res->bitSize = res->byteSize * 8;
res->def = (TransformOp *)0; res->def = (TransformOp *)0;
res->type = TransformVar::preexisting; res->type = TransformVar::preexisting;
MapKey key(vn->getCreateIndex(),0); MapKey key(vn->getCreateIndex(),0);
@ -122,7 +148,8 @@ TransformVar *TransformManager::newUnique(int4 size)
newVarnodes.push_back(TransformVar()); newVarnodes.push_back(TransformVar());
TransformVar *res = &newVarnodes.back(); TransformVar *res = &newVarnodes.back();
res->replacement = (Varnode *)0; res->replacement = (Varnode *)0;
res->size = size; res->byteSize = size;
res->bitSize = size * 8;
res->def = (TransformOp *)0; res->def = (TransformOp *)0;
res->type = TransformVar::normal_temp; res->type = TransformVar::normal_temp;
return res; return res;
@ -137,7 +164,7 @@ TransformVar *TransformManager::newConstant(int4 size,uintb val)
newVarnodes.push_back(TransformVar()); newVarnodes.push_back(TransformVar());
TransformVar *res = &newVarnodes.back(); TransformVar *res = &newVarnodes.back();
res->replacement = (Varnode *)0; res->replacement = (Varnode *)0;
res->size = size; res->byteSize = size;
res->val = val; res->val = val;
res->def = (TransformOp *)0; res->def = (TransformOp *)0;
res->type = TransformVar::constant; res->type = TransformVar::constant;
@ -151,7 +178,8 @@ TransformVar *TransformManager::newIop(Varnode *vn)
TransformVar *res = &newVarnodes.back(); TransformVar *res = &newVarnodes.back();
res->vn = (Varnode *)0; res->vn = (Varnode *)0;
res->replacement = (Varnode *)0; res->replacement = (Varnode *)0;
res->size = vn->getSize(); res->byteSize = vn->getSize();
res->bitSize = res->byteSize * 8;
res->val = vn->getOffset(); // The encoded iop res->val = vn->getOffset(); // The encoded iop
res->def = (TransformOp *)0; res->def = (TransformOp *)0;
res->type = TransformVar::constant_iop; res->type = TransformVar::constant_iop;
@ -161,19 +189,24 @@ TransformVar *TransformManager::newIop(Varnode *vn)
/// Given a single logical value within a larger Varnode, create a placeholder for /// Given a single logical value within a larger Varnode, create a placeholder for
/// that logical value. /// that logical value.
/// \param vn is the large Varnode /// \param vn is the large Varnode
/// \param size is the size of the logical value in bytes /// \param bitSize is the size of the logical value in bits
/// \param lsbOffset is the number of least significant bytes of the Varnode dropped from the value /// \param lsbOffset is the number of least significant bits of the Varnode dropped from the value
/// \return the placeholder variable /// \return the placeholder variable
TransformVar *TransformManager::newPiece(Varnode *vn,int4 size,int4 lsbOffset) TransformVar *TransformManager::newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset)
{ {
newVarnodes.push_back(TransformVar()); newVarnodes.push_back(TransformVar());
TransformVar *res = &newVarnodes.back(); TransformVar *res = &newVarnodes.back();
res->vn = vn; res->vn = vn;
res->replacement = (Varnode *)0; res->replacement = (Varnode *)0;
res->size = size; res->bitSize = bitSize;
res->byteSize = (bitSize + 7) / 8;
res->def = (TransformOp *)0; res->def = (TransformOp *)0;
res->type = TransformVar::piece; if (preserveAddress(vn, bitSize, lsbOffset))
res->type = TransformVar::piece;
else
res->type = TransformVar::normal_temp;
res->val = lsbOffset;
MapKey key(vn->getCreateIndex(),lsbOffset); MapKey key(vn->getCreateIndex(),lsbOffset);
pieceMap[key] = res; pieceMap[key] = res;
return res; return res;
@ -192,14 +225,17 @@ void TransformManager::newSplit(vector<TransformVar *> &res,Varnode *vn,const La
int4 num = description.getNumLanes(); int4 num = description.getNumLanes();
res.resize(num,(TransformVar *)0); res.resize(num,(TransformVar *)0);
for(int4 i=0;i<num;++i) { for(int4 i=0;i<num;++i) {
int4 bitpos = description.getPosition(i) * 8;
newVarnodes.push_back(TransformVar()); newVarnodes.push_back(TransformVar());
TransformVar *newVar = &newVarnodes.back(); TransformVar *newVar = &newVarnodes.back();
newVar->vn = vn; newVar->vn = vn;
newVar->replacement = (Varnode *)0; newVar->replacement = (Varnode *)0;
newVar->size = description.getSize(i); newVar->byteSize = description.getSize(i);
newVar->bitSize = newVar->byteSize * 8;
newVar->def = (TransformOp *)0; newVar->def = (TransformOp *)0;
newVar->type = TransformVar::piece; newVar->type = TransformVar::piece;
MapKey key(vn->getCreateIndex(),description.getPosition(i)); newVar->val = bitpos;
MapKey key(vn->getCreateIndex(),bitpos);
pieceMap[key] = newVar; pieceMap[key] = newVar;
res[i] = newVar; res[i] = newVar;
} }
@ -292,10 +328,10 @@ TransformVar *TransformManager::getPreexistingVarnode(Varnode *vn)
/// Given a big Varnode, find the placeholder corresponding to the logical value /// Given a big Varnode, find the placeholder corresponding to the logical value
/// given by a size and significance offset. If it doesn't exist, create it. /// given by a size and significance offset. If it doesn't exist, create it.
/// \param vn is the big Varnode containing the logical value /// \param vn is the big Varnode containing the logical value
/// \param size is the size of the logical value in bytes /// \param bitSize is the size of the logical value in bytes
/// \param lsbOffset is the signficance offset of the logical value within the Varnode /// \param lsbOffset is the signficance offset of the logical value within the Varnode
/// \return the found/created placeholder /// \return the found/created placeholder
TransformVar *TransformManager::getPiece(Varnode *vn,int4 size,int4 lsbOffset) TransformVar *TransformManager::getPiece(Varnode *vn,int4 bitSize,int4 lsbOffset)
{ {
map<MapKey,TransformVar *>::const_iterator iter; map<MapKey,TransformVar *>::const_iterator iter;
@ -304,7 +340,7 @@ TransformVar *TransformManager::getPiece(Varnode *vn,int4 size,int4 lsbOffset)
if (iter != pieceMap.end()) { if (iter != pieceMap.end()) {
return (*iter).second; return (*iter).second;
} }
return newPiece(vn,size,lsbOffset); return newPiece(vn,bitSize,lsbOffset);
} }
/// \brief Find (or create) placeholder nodes splitting a Varnode into its lanes /// \brief Find (or create) placeholder nodes splitting a Varnode into its lanes

View file

@ -33,12 +33,13 @@ public:
constant_iop = 5, ///< Special iop constant encoding a PcodeOp reference constant_iop = 5, ///< Special iop constant encoding a PcodeOp reference
}; };
private: private:
Varnode *vn; ///< Original \b big Varnode of which \b this is a component Varnode *vn; ///< Original \b big Varnode of which \b this is a component
Varnode *replacement; ///< The new explicit lane Varnode Varnode *replacement; ///< The new explicit lane Varnode
int4 size; ///< Size of the lane Varnode in bytes
uintb val; ///< Value of constant or position within the original big Varnode
TransformOp *def; ///< Defining op for new Varnode
uint4 type; ///< Type of new Varnode uint4 type; ///< Type of new Varnode
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
TransformOp *def; ///< Defining op for new Varnode
void createReplacement(Funcdata *fd); ///< Create the new/modified variable this placeholder represents void createReplacement(Funcdata *fd); ///< Create the new/modified variable this placeholder represents
}; };
@ -110,18 +111,20 @@ class TransformManager {
void placeInputs(void); ///< Set input Varnodes for all new ops void placeInputs(void); ///< Set input Varnodes for all new ops
public: public:
TransformManager(Funcdata *f) { fd = f; } ///< Constructor TransformManager(Funcdata *f) { fd = f; } ///< Constructor
virtual ~TransformManager(void) {}
virtual bool preserveAddress(Varnode *vn,int4 bitSize,int4 lsbOffset) const;
TransformVar *newPreexistingVarnode(Varnode *vn); ///< Make placeholder for preexisting Varnode TransformVar *newPreexistingVarnode(Varnode *vn); ///< Make placeholder for preexisting Varnode
TransformVar *newUnique(int4 size); ///< Make placeholder for new unique space Varnode TransformVar *newUnique(int4 size); ///< Make placeholder for new unique space Varnode
TransformVar *newConstant(int4 size,uintb val); ///< Make placeholder for constant Varnode TransformVar *newConstant(int4 size,uintb val); ///< Make placeholder for constant Varnode
TransformVar *newIop(Varnode *vn); ///< Make placeholder for special iop constant TransformVar *newIop(Varnode *vn); ///< Make placeholder for special iop constant
TransformVar *newPiece(Varnode *vn,int4 size,int4 lsbOffset); ///< Make placeholder for piece of a Varnode TransformVar *newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset); ///< Make placeholder for piece of a Varnode
void newSplit(vector<TransformVar *> &res,Varnode *vn,const LaneDescription &description); void newSplit(vector<TransformVar *> &res,Varnode *vn,const LaneDescription &description);
TransformOp *newOpReplace(int4 numParams,OpCode opc,PcodeOp *replace); TransformOp *newOpReplace(int4 numParams,OpCode opc,PcodeOp *replace);
TransformOp *newOp(int4 numParams,OpCode opc,TransformOp *follow); TransformOp *newOp(int4 numParams,OpCode opc,TransformOp *follow);
TransformOp *newPreexistingOp(int4 numParams,OpCode opc,PcodeOp *originalOp); TransformOp *newPreexistingOp(int4 numParams,OpCode opc,PcodeOp *originalOp);
TransformVar *getPreexistingVarnode(Varnode *vn); ///< Get (or create) placeholder for preexisting Varnode TransformVar *getPreexistingVarnode(Varnode *vn); ///< Get (or create) placeholder for preexisting Varnode
TransformVar *getPiece(Varnode *vn,int4 size,int4 lsbOffset); ///< Get (or create) placeholder piece TransformVar *getPiece(Varnode *vn,int4 bitSize,int4 lsbOffset); ///< Get (or create) placeholder piece
void getSplit(vector<TransformVar *> &res,Varnode *vn,const LaneDescription &description); void getSplit(vector<TransformVar *> &res,Varnode *vn,const LaneDescription &description);
void opSetInput(TransformOp *rop,TransformVar *rvn,int4 slot); ///< Mark given variable as input to given op 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 opSetOutput(TransformOp *rop,TransformVar *rvn); ///< Mark given variable as output of given op