mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
New LaneDescription methods, refactor TransformVar initialize
This commit is contained in:
parent
ad87a8d40f
commit
4f925923c5
2 changed files with 148 additions and 55 deletions
|
@ -49,6 +49,81 @@ LaneDescription::LaneDescription(int4 origSize,int4 lo,int4 hi)
|
|||
lanePosition[1] = lo;
|
||||
}
|
||||
|
||||
/// Position 0 will map to index 0 and a position equal to whole size will
|
||||
/// map to the number of lanes. Positions that are out of bounds or that do
|
||||
/// not fall on a lane boundary will return -1.
|
||||
/// \param bytePos is the given byte position to test
|
||||
/// \return the index of the lane that start at the given position
|
||||
int4 LaneDescription::getBoundary(int4 bytePos) const
|
||||
|
||||
{
|
||||
if (bytePos < 0 || bytePos > wholeSize)
|
||||
return -1;
|
||||
if (bytePos == wholeSize)
|
||||
return lanePosition.size();
|
||||
int4 min = 0;
|
||||
int4 max = lanePosition.size() - 1;
|
||||
while(min < max) {
|
||||
int4 index = (min + max) / 2;
|
||||
int4 pos = lanePosition[index];
|
||||
if (pos == bytePos) return index;
|
||||
if (pos < bytePos)
|
||||
min = pos + 1;
|
||||
else
|
||||
max = pos - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// \brief Decide if a given truncation is natural for \b this description
|
||||
///
|
||||
/// A subset of lanes are specified and a truncation (given by a byte position and byte size).
|
||||
/// If the truncation, relative to the subset, contains at least 1 lane and does not split any
|
||||
/// lanes, then return \b true and pass back the number of lanes and starting lane of the truncation.
|
||||
/// \param numLanes is the number of lanes in the original subset
|
||||
/// \param skipLanes is the starting (least significant) lane index of the original subset
|
||||
/// \param bytePos is the number of bytes to truncate from the front (least significant portion) of the subset
|
||||
/// \param size is the number of bytes to include in the truncation
|
||||
/// \param resNumLanes will hold the number of lanes in the truncation
|
||||
/// \param resSkipLanes will hold the starting lane in the truncation
|
||||
/// \return \b true if the truncation is natural
|
||||
bool LaneDescription::restriction(int4 numLanes,int4 skipLanes,int4 bytePos,int4 size,
|
||||
int4 &resNumLanes,int4 &resSkipLanes) const
|
||||
|
||||
{
|
||||
resSkipLanes = getBoundary(lanePosition[skipLanes] + bytePos);
|
||||
if (resSkipLanes < 0) return false;
|
||||
int4 finalIndex = getBoundary(lanePosition[skipLanes] + bytePos + size);
|
||||
if (finalIndex < 0) return false;
|
||||
resNumLanes = finalIndex - resSkipLanes;
|
||||
return (resNumLanes != 0);
|
||||
}
|
||||
|
||||
/// \brief Decide if a given subset of lanes can be extended naturally for \b this description
|
||||
///
|
||||
/// A subset of lanes are specified and their position within an extension (given by a byte position).
|
||||
/// The size in bytes of the extension is also given. If the extension is contained within \b this description,
|
||||
/// and the boundaries of the extension don't split any lanes, then return \b true and pass back
|
||||
/// the number of lanes and starting lane of the extension.
|
||||
/// \param numLanes is the number of lanes in the original subset
|
||||
/// \param skipLanes is the starting (least significant) lane index of the original subset
|
||||
/// \param bytePos is the number of bytes to truncate from the front (least significant portion) of the extension
|
||||
/// \param size is the number of bytes in the extension
|
||||
/// \param resNumLanes will hold the number of lanes in the extension
|
||||
/// \param resSkipLanes will hold the starting lane in the extension
|
||||
/// \return \b true if the extension is natural
|
||||
bool LaneDescription::extension(int4 numLanes,int4 skipLanes,int4 bytePos,int4 size,
|
||||
int4 &resNumLanes,int4 &resSkipLanes) const
|
||||
|
||||
{
|
||||
resSkipLanes = getBoundary(lanePosition[skipLanes] - bytePos);
|
||||
if (resSkipLanes < 0) return false;
|
||||
int4 finalIndex = getBoundary(lanePosition[skipLanes] - bytePos + size);
|
||||
if (finalIndex < 0) return false;
|
||||
resNumLanes = finalIndex - resSkipLanes;
|
||||
return (resNumLanes != 0);
|
||||
}
|
||||
|
||||
/// Create the Varnode object (constant, unique, vector piece) described by the
|
||||
/// given placeholder. If the Varnode is an output, assume the op already exists
|
||||
/// and create the Varnode as an output. Set the \b replacement field with the
|
||||
|
@ -193,14 +268,10 @@ TransformVar *TransformManager::newPreexistingVarnode(Varnode *vn)
|
|||
{
|
||||
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;
|
||||
|
||||
// value of 0 treats this as "piece" of itself at offset 0, allows getPiece() to find it
|
||||
res->initialize(TransformVar::preexisting,vn,vn->getSize()*8,vn->getSize(),0);
|
||||
res->flags = TransformVar::split_terminator;
|
||||
res->val = 0; // Treat this as "piece" of itself at offset 0, allows getPiece() to find this
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -211,13 +282,7 @@ TransformVar *TransformManager::newUnique(int4 size)
|
|||
{
|
||||
newVarnodes.push_back(TransformVar());
|
||||
TransformVar *res = &newVarnodes.back();
|
||||
res->vn = (Varnode *)0;
|
||||
res->replacement = (Varnode *)0;
|
||||
res->byteSize = size;
|
||||
res->bitSize = size * 8;
|
||||
res->def = (TransformOp *)0;
|
||||
res->type = TransformVar::normal_temp;
|
||||
res->flags = 0;
|
||||
res->initialize(TransformVar::normal_temp,(Varnode *)0,size*8,size,0);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -232,30 +297,19 @@ TransformVar *TransformManager::newConstant(int4 size,int4 lsbOffset,uintb val)
|
|||
{
|
||||
newVarnodes.push_back(TransformVar());
|
||||
TransformVar *res = &newVarnodes.back();
|
||||
res->vn = (Varnode *)0;
|
||||
res->replacement = (Varnode *)0;
|
||||
res->byteSize = size;
|
||||
res->bitSize = size * 8;
|
||||
res->val = (val >> lsbOffset) & calc_mask(size);
|
||||
res->def = (TransformOp *)0;
|
||||
res->type = TransformVar::constant;
|
||||
res->flags = 0;
|
||||
res->initialize(TransformVar::constant,(Varnode *)0,size*8,size,(val >> lsbOffset) & calc_mask(size));
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Used for creating INDIRECT placeholders.
|
||||
/// \param vn is the original iop parameter to the INDIRECT
|
||||
/// \return the new placeholder node
|
||||
TransformVar *TransformManager::newIop(Varnode *vn)
|
||||
|
||||
{
|
||||
newVarnodes.push_back(TransformVar());
|
||||
TransformVar *res = &newVarnodes.back();
|
||||
res->vn = (Varnode *)0;
|
||||
res->replacement = (Varnode *)0;
|
||||
res->byteSize = vn->getSize();
|
||||
res->bitSize = res->byteSize * 8;
|
||||
res->val = vn->getOffset(); // The encoded iop
|
||||
res->def = (TransformOp *)0;
|
||||
res->type = TransformVar::constant_iop;
|
||||
res->flags = 0;
|
||||
res->initialize(TransformVar::constant_iop,(Varnode *)0,vn->getSize()*8,vn->getSize(),vn->getOffset());
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -270,17 +324,10 @@ TransformVar *TransformManager::newPiece(Varnode *vn,int4 bitSize,int4 lsbOffset
|
|||
{
|
||||
TransformVar *res = new TransformVar[1];
|
||||
pieceMap[vn->getCreateIndex()] = res;
|
||||
res->vn = vn;
|
||||
res->replacement = (Varnode *)0;
|
||||
res->bitSize = bitSize;
|
||||
res->byteSize = (bitSize + 7) / 8;
|
||||
res->def = (TransformOp *)0;
|
||||
if (preserveAddress(vn, bitSize, lsbOffset))
|
||||
res->type = TransformVar::piece;
|
||||
else
|
||||
res->type = TransformVar::piece_temp;
|
||||
int4 byteSize = (bitSize + 7) / 8;
|
||||
uint4 type = preserveAddress(vn, bitSize, lsbOffset) ? TransformVar::piece : TransformVar::piece_temp;
|
||||
res->initialize(type, vn, bitSize, byteSize, lsbOffset);
|
||||
res->flags = TransformVar::split_terminator;
|
||||
res->val = lsbOffset;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -300,28 +347,47 @@ TransformVar *TransformManager::newSplit(Varnode *vn,const LaneDescription &desc
|
|||
for(int4 i=0;i<num;++i) {
|
||||
int4 bitpos = description.getPosition(i) * 8;
|
||||
TransformVar *newVar = &res[i];
|
||||
newVar->vn = vn;
|
||||
newVar->replacement = (Varnode *)0;
|
||||
newVar->byteSize = description.getSize(i);
|
||||
newVar->bitSize = newVar->byteSize * 8;
|
||||
newVar->def = (TransformOp *)0;
|
||||
newVar->flags = 0;
|
||||
if (vn->isConstant()) {
|
||||
newVar->type = TransformVar::constant;
|
||||
newVar->val = (vn->getOffset() >> bitpos) & calc_mask(newVar->byteSize);
|
||||
}
|
||||
int4 byteSize = description.getSize(i);
|
||||
if (vn->isConstant())
|
||||
newVar->initialize(TransformVar::constant,vn,byteSize * 8,byteSize, (vn->getOffset() >> bitpos) & calc_mask(byteSize));
|
||||
else {
|
||||
if (preserveAddress(vn, newVar->bitSize, bitpos))
|
||||
newVar->type = TransformVar::piece;
|
||||
else
|
||||
newVar->type = TransformVar::piece_temp;
|
||||
newVar->val = bitpos;
|
||||
uint4 type = preserveAddress(vn, byteSize * 8, bitpos) ? TransformVar::piece : TransformVar::piece_temp;
|
||||
newVar->initialize(type,vn,byteSize * 8, byteSize, bitpos);
|
||||
}
|
||||
}
|
||||
res[num-1].flags = TransformVar::split_terminator;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Create placeholder nodes splitting a Varnode into a subset of lanes in the given description
|
||||
///
|
||||
/// Given a big Varnode and specific subset of a lane description, create placeholders for all
|
||||
/// the explicit pieces that the big Varnode will be split into.
|
||||
/// \param vn is the big Varnode to split
|
||||
/// \param description gives a list of potentional lanes
|
||||
/// \param numLanes is the number of lanes in the subset
|
||||
/// \param startLane is the starting (least significant) lane in the subset
|
||||
/// \return an array of the new TransformVar placeholders from least to most significant
|
||||
TransformVar *TransformManager::newSplit(Varnode *vn,const LaneDescription &description,int4 numLanes,int4 startLane)
|
||||
|
||||
{
|
||||
TransformVar *res = new TransformVar[numLanes];
|
||||
pieceMap[vn->getCreateIndex()] = res;
|
||||
for(int4 i=0;i<numLanes;++i) {
|
||||
int4 bitpos = description.getPosition(startLane + i) * 8;
|
||||
int4 byteSize = description.getSize(startLane + i);
|
||||
TransformVar *newVar = &res[i];
|
||||
if (vn->isConstant())
|
||||
newVar->initialize(TransformVar::constant,vn,byteSize * 8, byteSize, (vn->getOffset() >> bitpos) & calc_mask(byteSize));
|
||||
else {
|
||||
uint4 type = preserveAddress(vn, byteSize * 8, bitpos) ? TransformVar::piece : TransformVar::piece_temp;
|
||||
newVar->initialize(type,vn,byteSize * 8, byteSize, bitpos);
|
||||
}
|
||||
}
|
||||
res[numLanes-1].flags = TransformVar::split_terminator;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Create a new placeholder op intended to replace an existing op
|
||||
///
|
||||
/// An uninitialized placeholder for the new op is created.
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/// \file transform.hh
|
||||
/// \brief Classes for building large scale transforms of function data-flow
|
||||
#ifndef __TRANSFORM__
|
||||
#define __TRANSFORM__
|
||||
|
||||
|
@ -49,6 +51,7 @@ private:
|
|||
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 initialize(uint4 tp,Varnode *v,int4 bits,int4 bytes,uintb value);
|
||||
public:
|
||||
Varnode *getOriginal(void) const { return vn; } ///< Get the original Varnode \b this placeholder models
|
||||
TransformOp *getDef(void) const { return def; } ///< Get the operator that defines this placeholder variable
|
||||
|
@ -97,6 +100,9 @@ public:
|
|||
int4 getWholeSize(void) const { return wholeSize; } ///< Get the size of the region being split
|
||||
int4 getSize(int4 i) const { return laneSize[i]; } ///< Get the size of the i-th lane
|
||||
int4 getPosition(int4 i) const { return lanePosition[i]; } ///< Get the significance offset of the i-th lane
|
||||
int4 getBoundary(int4 bytePos) const; ///< Get index of lane that starts at the given byte position
|
||||
bool restriction(int4 numLanes,int4 skipLanes,int4 bytePos,int4 size,int4 &resNumLanes,int4 &resSkipLanes) const;
|
||||
bool extension(int4 numLanes,int4 skipLanes,int4 bytePos,int4 size,int4 &resNumLanes,int4 &resSkipLanes) const;
|
||||
};
|
||||
|
||||
/// \brief Class for splitting larger registers holding smaller logical lanes
|
||||
|
@ -129,6 +135,7 @@ public:
|
|||
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
|
||||
TransformVar *newSplit(Varnode *vn,const LaneDescription &description);
|
||||
TransformVar *newSplit(Varnode *vn,const LaneDescription &description,int4 numLanes,int4 startLane);
|
||||
TransformOp *newOpReplace(int4 numParams,OpCode opc,PcodeOp *replace);
|
||||
TransformOp *newOp(int4 numParams,OpCode opc,TransformOp *follow);
|
||||
TransformOp *newPreexistingOp(int4 numParams,OpCode opc,PcodeOp *originalOp);
|
||||
|
@ -142,6 +149,26 @@ public:
|
|||
void apply(void); ///< Apply the full transform to the function
|
||||
};
|
||||
|
||||
/// \brief Initialize \b this variable from raw data
|
||||
///
|
||||
/// \param tp is the type of variable to create
|
||||
/// \param v is the underlying Varnode of which this is a piece (may be null)
|
||||
/// \param bits is the number of bits in the variable
|
||||
/// \param bytes is the number of bytes in the variable
|
||||
/// \param value is the associated value
|
||||
inline void TransformVar::initialize(uint4 tp,Varnode *v,int4 bits,int4 bytes,uintb value)
|
||||
|
||||
{
|
||||
type = tp;
|
||||
vn = v;
|
||||
val = value;
|
||||
bitSize = bits;
|
||||
byteSize = bytes;
|
||||
flags = 0;
|
||||
def = (TransformOp *)0;
|
||||
replacement = (Varnode *)0;
|
||||
}
|
||||
|
||||
/// \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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue