mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
ActionCollectLanedAccess
This commit is contained in:
parent
e7c75b663d
commit
dddcf4c715
5 changed files with 202 additions and 60 deletions
|
@ -495,6 +495,127 @@ int4 ActionStackPtrFlow::apply(Funcdata &data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark every PcodeOp that is reachable from the given Varnode and create a LanedAccess record.
|
||||||
|
/// \param data is the function to trace through
|
||||||
|
/// \param base is the description of the laned register being traced from
|
||||||
|
/// \param vn is the Varnode to trace
|
||||||
|
/// \param pos is the significance position of the Varnode within the laned register
|
||||||
|
void ActionCollectLanedAccess::traceVarnode(Funcdata &data,const LanedRegister *base,Varnode *vn,int4 pos)
|
||||||
|
|
||||||
|
{
|
||||||
|
list<PcodeOp *>::const_iterator iter = vn->beginDescend();
|
||||||
|
int4 step = 0;
|
||||||
|
while(step < 2) {
|
||||||
|
PcodeOp *op;
|
||||||
|
if (step == 0) {
|
||||||
|
op = *iter;
|
||||||
|
++iter;
|
||||||
|
if (iter == vn->endDescend())
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
step = 2;
|
||||||
|
if (!vn->isWritten()) continue;
|
||||||
|
op = vn->getDef();
|
||||||
|
}
|
||||||
|
if (op->isMark()) continue;
|
||||||
|
// Make sure op is associated with a lane access records describing its biggest Varnode
|
||||||
|
switch(op->code()) {
|
||||||
|
case CPUI_LOAD:
|
||||||
|
case CPUI_PIECE:
|
||||||
|
case CPUI_INT_ZEXT:
|
||||||
|
case CPUI_INT_SEXT:
|
||||||
|
if (vn != op->getOut()) continue; // Biggest Varnode is the output
|
||||||
|
break;
|
||||||
|
case CPUI_SUBPIECE:
|
||||||
|
if (vn != op->getIn(0)) continue; // Biggest Varnode is first input
|
||||||
|
break;
|
||||||
|
case CPUI_STORE:
|
||||||
|
if (vn != op->getIn(2)) continue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
op->setMark();
|
||||||
|
data.opMarkLanedAccess(base, op, vn->getSize(), pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Search for Varnodes that match the given laned vector register
|
||||||
|
///
|
||||||
|
/// All varnodes (bigger than 8 bytes) that are contained in the vector register are processed,
|
||||||
|
/// looking for a working lane scheme. Data-flow from these Varnodes is traces and LanedAccess
|
||||||
|
/// records are created for each PcodeOp flowed through.
|
||||||
|
/// \param data is the function being traced
|
||||||
|
/// \param lanedRegister is the given register and acceptable lane schemes
|
||||||
|
/// \param iter is an iterator to the first Varnode that matches the vector register
|
||||||
|
void ActionCollectLanedAccess::processLane(Funcdata &data,const LanedRegister &lanedRegister,
|
||||||
|
VarnodeLocSet::const_iterator iter)
|
||||||
|
{
|
||||||
|
int4 fullSize = lanedRegister.getStorage().size;
|
||||||
|
Address startAddress(lanedRegister.getStorage().getAddr());
|
||||||
|
Address lastAddress(startAddress + (fullSize-1));
|
||||||
|
VarnodeLocSet::const_iterator enditer = data.endLoc();
|
||||||
|
while(iter != enditer) {
|
||||||
|
Varnode *vn = *iter;
|
||||||
|
++iter;
|
||||||
|
if (lastAddress < vn->getAddr())
|
||||||
|
break;
|
||||||
|
if (vn->getSize() <= 8) // Varnode not big enough to be vector register
|
||||||
|
continue;
|
||||||
|
int4 diff = (int4)(vn->getOffset() - startAddress.getOffset());
|
||||||
|
if (diff + vn->getSize() > fullSize) // Must be contained by full register
|
||||||
|
continue;
|
||||||
|
if (vn->getSpace()->isBigEndian())
|
||||||
|
diff = fullSize - (diff + vn->getSize());
|
||||||
|
traceVarnode(data, &lanedRegister, vn, diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Give each PcodeOp in the laned access list a chance to propagate to new PcodeOps,
|
||||||
|
/// which will have new records added to the list.
|
||||||
|
/// \param data is the function being traced
|
||||||
|
void ActionCollectLanedAccess::propagate(Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
list<LanedAccess>::const_iterator iter = data.beginLaneAccess();
|
||||||
|
while(iter != data.endLaneAccess()) {
|
||||||
|
const LanedAccess lanedAccess( *iter );
|
||||||
|
PcodeOp *op = lanedAccess.getOp();
|
||||||
|
int4 sz = lanedAccess.getSize();
|
||||||
|
for(int4 i=0;i<op->numInput();++i) {
|
||||||
|
Varnode *vn = op->getIn(i);
|
||||||
|
if (vn->getSize() != sz) continue; // Size must match exactly
|
||||||
|
if (vn->isConstant() || vn->isAnnotation()) continue;
|
||||||
|
traceVarnode(data, lanedAccess.getBase(), vn, lanedAccess.getBytePos());
|
||||||
|
}
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 ActionCollectLanedAccess::apply(Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (data.getArch()->lanerecords.empty())
|
||||||
|
return 0;
|
||||||
|
const LanedRegister &lastRecord( data.getArch()->lanerecords.back() );
|
||||||
|
Address lastAddress( lastRecord.getStorage().getAddr() + lastRecord.getStorage().size - 1);
|
||||||
|
list<LanedRegister>::const_iterator iter;
|
||||||
|
for(iter=data.getArch()->lanerecords.begin();iter!=data.getArch()->lanerecords.end();++iter) {
|
||||||
|
const LanedRegister &lanedRegister( *iter );
|
||||||
|
VarnodeLocSet::const_iterator viter = data.beginLoc(lanedRegister.getStorage().getAddr());
|
||||||
|
if (viter == data.endLoc()) break;
|
||||||
|
Varnode *vn = *viter;
|
||||||
|
if (lastAddress < vn->getAddr()) break;
|
||||||
|
processLane(data,lanedRegister,viter);
|
||||||
|
}
|
||||||
|
propagate(data);
|
||||||
|
list<LanedAccess>::const_iterator aiter;
|
||||||
|
for(aiter=data.beginLaneAccess();aiter!=data.endLaneAccess();++aiter)
|
||||||
|
(*aiter).getOp()->clearMark();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Try to divide a single Varnode into lanes
|
/// \brief Try to divide a single Varnode into lanes
|
||||||
///
|
///
|
||||||
/// Look for a CPUI_SUBPIECE op that takes the given Varnode as the input or a
|
/// Look for a CPUI_SUBPIECE op that takes the given Varnode as the input or a
|
||||||
|
@ -505,8 +626,10 @@ int4 ActionStackPtrFlow::apply(Funcdata &data)
|
||||||
/// \param data is the function being transformed
|
/// \param data is the function being transformed
|
||||||
/// \param vn is the given single Varnode
|
/// \param vn is the given single Varnode
|
||||||
/// \param lanedRegister is acceptable set of lane sizes for the Varnode
|
/// \param lanedRegister is acceptable set of lane sizes for the Varnode
|
||||||
|
/// \param bytePos is the significance position of the Varnode within the laned register
|
||||||
/// \param allowDowncast is \b true if we allow lane systems with SUBPIECE terminators
|
/// \param allowDowncast is \b true if we allow lane systems with SUBPIECE terminators
|
||||||
bool ActionLaneDivide::processVarnode(Funcdata &data,Varnode *vn,const LanedRegister &lanedRegister,bool allowDowncast)
|
bool ActionLaneDivide::processVarnode(Funcdata &data,Varnode *vn,const LanedRegister &lanedRegister,int4 bytePos,
|
||||||
|
bool allowDowncast)
|
||||||
|
|
||||||
{
|
{
|
||||||
list<PcodeOp *>::const_iterator iter = vn->beginDescend();
|
list<PcodeOp *>::const_iterator iter = vn->beginDescend();
|
||||||
|
@ -536,10 +659,6 @@ bool ActionLaneDivide::processVarnode(Funcdata &data,Varnode *vn,const LanedRegi
|
||||||
if (checkedLanes.allowedLane(curSize)) continue;
|
if (checkedLanes.allowedLane(curSize)) continue;
|
||||||
checkedLanes.addSize(curSize); // Only check this scheme once
|
checkedLanes.addSize(curSize); // Only check this scheme once
|
||||||
LaneDescription description(lanedRegister.getStorage().size,curSize); // Lane scheme dictated by curSize
|
LaneDescription description(lanedRegister.getStorage().size,curSize); // Lane scheme dictated by curSize
|
||||||
int4 bytePos = (int4)(lanedRegister.getStorage().offset - vn->getOffset());
|
|
||||||
if (lanedRegister.getStorage().space->isBigEndian()) {
|
|
||||||
bytePos = lanedRegister.getStorage().size - (bytePos + vn->getSize()); // Convert to significance order
|
|
||||||
}
|
|
||||||
if (!description.subset(bytePos,vn->getSize())) // Try to restrict lane scheme to actual Varnode
|
if (!description.subset(bytePos,vn->getSize())) // Try to restrict lane scheme to actual Varnode
|
||||||
continue;
|
continue;
|
||||||
LaneDivide laneDivide(&data,vn,description,allowDowncast);
|
LaneDivide laneDivide(&data,vn,description,allowDowncast);
|
||||||
|
@ -553,63 +672,34 @@ bool ActionLaneDivide::processVarnode(Funcdata &data,Varnode *vn,const LanedRegi
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Search for and attempt to split Varnodes that match the given laned vector register
|
|
||||||
///
|
|
||||||
/// All varnodes (bigger than 8 bytes) that are contained in the vector register are processed,
|
|
||||||
/// looking for a working lane scheme, and splitting based on that scheme. Return \b false if there
|
|
||||||
/// is at least one eligible Varnode that could not be split.
|
|
||||||
/// \param data is the function being modified
|
|
||||||
/// \param lanedRegister is the given register and acceptable lane schemes
|
|
||||||
/// \param allowDowncast is \b true if SUBPIECE terminators are allowed in the schemes
|
|
||||||
/// \param iter is an iterator to the first Varnode that matches the vector register
|
|
||||||
/// \return \b true if all varnodes were successfully split
|
|
||||||
bool ActionLaneDivide::processLane(Funcdata &data,const LanedRegister &lanedRegister,bool allowDowncast,
|
|
||||||
VarnodeLocSet::const_iterator iter)
|
|
||||||
|
|
||||||
{
|
|
||||||
int4 fullSize = lanedRegister.getStorage().size;
|
|
||||||
Address startAddress(lanedRegister.getStorage().getAddr());
|
|
||||||
Address lastAddress(startAddress + (fullSize-1));
|
|
||||||
VarnodeLocSet::const_iterator enditer = data.endLoc();
|
|
||||||
bool res = true;
|
|
||||||
while(iter != enditer) {
|
|
||||||
Varnode *vn = *iter;
|
|
||||||
++iter;
|
|
||||||
if (lastAddress < vn->getAddr())
|
|
||||||
break;
|
|
||||||
if (vn->getSize() <= 8) // Varnode not big enough to be vector register
|
|
||||||
continue;
|
|
||||||
int4 diff = (int4)(vn->getOffset() - startAddress.getOffset());
|
|
||||||
if (diff + vn->getSize() > fullSize) // Must be contained by full register
|
|
||||||
continue;
|
|
||||||
if (processVarnode(data,vn,lanedRegister,allowDowncast)) {
|
|
||||||
// If changes were made, iterator may no longer be valid, generate a new one
|
|
||||||
iter = data.beginLoc(startAddress);
|
|
||||||
res = true; // We may have eliminated a previous failure
|
|
||||||
}
|
|
||||||
else
|
|
||||||
res = false; // Note the failure
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int4 ActionLaneDivide::apply(Funcdata &data)
|
int4 ActionLaneDivide::apply(Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (data.getArch()->lanerecords.empty())
|
list<LanedAccess>::const_iterator iter;
|
||||||
return 0;
|
bool allowDowncast = false;
|
||||||
const LanedRegister &lastRecord( data.getArch()->lanerecords.back() );
|
for(int4 i=0;i<2;++i) {
|
||||||
Address lastAddress( lastRecord.getStorage().getAddr() + lastRecord.getStorage().size - 1);
|
for(iter=data.beginLaneAccess();iter!=data.endLaneAccess();++iter) {
|
||||||
list<LanedRegister>::const_iterator iter;
|
const LanedAccess &lanedAccess(*iter);
|
||||||
for(iter=data.getArch()->lanerecords.begin();iter!=data.getArch()->lanerecords.end();++iter) {
|
PcodeOp *op = lanedAccess.getOp();
|
||||||
const LanedRegister &lanedRegister( *iter );
|
if (op->isDead()) continue;
|
||||||
VarnodeLocSet::const_iterator viter = data.beginLoc(lanedRegister.getStorage().getAddr());
|
Varnode *vn = op->getOut();
|
||||||
if (viter == data.endLoc()) break;
|
if (vn != (Varnode *)0 && vn->getSize() == lanedAccess.getSize())
|
||||||
Varnode *vn = *viter;
|
processVarnode(data, vn, *lanedAccess.getBase(), lanedAccess.getBytePos(), allowDowncast);
|
||||||
if (lastAddress < vn->getAddr()) break;
|
else {
|
||||||
if (!processLane(data,lanedRegister,false,viter)) // Try without SUBPIECE terminators
|
for(int4 j=0;j<op->numInput();++j) {
|
||||||
processLane(data,lanedRegister,true,viter); // If we fail, try with SUBPIECE terminators
|
vn = op->getIn(j);
|
||||||
|
if (vn->getSize() == lanedAccess.getSize()) {
|
||||||
|
if (!vn->isConstant() && !vn->isAnnotation() && !vn->isWritten()) {
|
||||||
|
processVarnode(data, vn, *lanedAccess.getBase(), lanedAccess.getBytePos(), allowDowncast);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allowDowncast = true;
|
||||||
|
}
|
||||||
|
data.clearLanedAccessList();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4624,6 +4714,7 @@ void universal_action(Architecture *conf)
|
||||||
// actmainloop->addAction( new ActionParamShiftStop("paramshift") );
|
// actmainloop->addAction( new ActionParamShiftStop("paramshift") );
|
||||||
actmainloop->addAction( new ActionRestrictLocal("localrecovery") ); // Do before dead code removed
|
actmainloop->addAction( new ActionRestrictLocal("localrecovery") ); // Do before dead code removed
|
||||||
actmainloop->addAction( new ActionDeadCode("deadcode") );
|
actmainloop->addAction( new ActionDeadCode("deadcode") );
|
||||||
|
actmainloop->addAction( new ActionCollectLanedAccess("base") );
|
||||||
actmainloop->addAction( new ActionDynamicMapping("dynamic") ); // Must come before restructurevarnode and infertypes
|
actmainloop->addAction( new ActionDynamicMapping("dynamic") ); // Must come before restructurevarnode and infertypes
|
||||||
actmainloop->addAction( new ActionRestructureVarnode("localrecovery") );
|
actmainloop->addAction( new ActionRestructureVarnode("localrecovery") );
|
||||||
actmainloop->addAction( new ActionSpacebase("base") ); // Must come before infertypes and nonzeromask
|
actmainloop->addAction( new ActionSpacebase("base") ); // Must come before infertypes and nonzeromask
|
||||||
|
|
|
@ -97,6 +97,26 @@ public:
|
||||||
virtual int4 apply(Funcdata &data);
|
virtual int4 apply(Funcdata &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Find PcodeOps that are accessing values from laned registers
|
||||||
|
///
|
||||||
|
/// This looks for Varnodes that match any of the LanedRegister records associated with
|
||||||
|
/// the architecture. A record is created in the function's LanedAccess list for every
|
||||||
|
/// PcodeOp that accesses one of these Varnodes. These are later examined by ActionLaneDivide.
|
||||||
|
/// The LanedRegister is the key for finding the Varnode, but the \e big property can propagate
|
||||||
|
/// through data-flow to other Varnodes that are not necessarily using the same storage (i.e. uniques).
|
||||||
|
class ActionCollectLanedAccess : public Action {
|
||||||
|
void traceVarnode(Funcdata &data,const LanedRegister *base,Varnode *vn,int4 pos); ///< Trace a big Varnode instance to other big Varnodes
|
||||||
|
void processLane(Funcdata &data,const LanedRegister &lanedRegister,VarnodeLocSet::const_iterator iter);
|
||||||
|
void propagate(Funcdata &data); ///< Discover other PcodeOps that use laned values
|
||||||
|
public:
|
||||||
|
ActionCollectLanedAccess(const string &g) : Action(rule_onceperfunc,"collectlanedaccess",g) {} ///< Constructor
|
||||||
|
virtual Action *clone(const ActionGroupList &grouplist) const {
|
||||||
|
if (!grouplist.contains(getGroup())) return (Action *)0;
|
||||||
|
return new ActionCollectLanedAccess(getGroup());
|
||||||
|
}
|
||||||
|
virtual int4 apply(Funcdata &data);
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief Find Varnodes with a vectorized lane scheme and attempt to split the lanes
|
/// \brief Find Varnodes with a vectorized lane scheme and attempt to split the lanes
|
||||||
///
|
///
|
||||||
/// The Architecture lists (vector) registers that may be used to perform parallelized operations
|
/// The Architecture lists (vector) registers that may be used to perform parallelized operations
|
||||||
|
@ -104,8 +124,7 @@ public:
|
||||||
/// if a particular lane scheme makes sense in terms of the function's data-flow, and then
|
/// if a particular lane scheme makes sense in terms of the function's data-flow, and then
|
||||||
/// rewrites the data-flow so that the lanes become explicit Varnodes.
|
/// rewrites the data-flow so that the lanes become explicit Varnodes.
|
||||||
class ActionLaneDivide : public Action {
|
class ActionLaneDivide : public Action {
|
||||||
bool processVarnode(Funcdata &data,Varnode *vn,const LanedRegister &lanedRegister,bool allowDowncast);
|
bool processVarnode(Funcdata &data,Varnode *vn,const LanedRegister &lanedRegister,int4 bytePos,bool allowDowncast);
|
||||||
bool processLane(Funcdata &data,const LanedRegister &lanedRegister,bool allowDowncast,VarnodeLocSet::const_iterator iter);
|
|
||||||
public:
|
public:
|
||||||
ActionLaneDivide(const string &g) : Action(rule_onceperfunc,"lanedivide",g) {} ///< Constructor
|
ActionLaneDivide(const string &g) : Action(rule_onceperfunc,"lanedivide",g) {} ///< Constructor
|
||||||
virtual Action *clone(const ActionGroupList &grouplist) const {
|
virtual Action *clone(const ActionGroupList &grouplist) const {
|
||||||
|
|
|
@ -80,6 +80,7 @@ class Funcdata {
|
||||||
Merge covermerge; ///< Variable range intersection algorithms
|
Merge covermerge; ///< Variable range intersection algorithms
|
||||||
ParamActive *activeoutput; ///< Data for assessing which parameters are passed to \b this function
|
ParamActive *activeoutput; ///< Data for assessing which parameters are passed to \b this function
|
||||||
Override localoverride; ///< Overrides of data-flow, prototypes, etc. that are local to \b this function
|
Override localoverride; ///< Overrides of data-flow, prototypes, etc. that are local to \b this function
|
||||||
|
list<LanedAccess> lanedList; ///< List of ops that are accessing potentially laned registers
|
||||||
|
|
||||||
// Low level Varnode functions
|
// Low level Varnode functions
|
||||||
void setVarnodeProperties(Varnode *vn) const; ///< Look-up boolean properties and data-type information
|
void setVarnodeProperties(Varnode *vn) const; ///< Look-up boolean properties and data-type information
|
||||||
|
@ -428,6 +429,10 @@ public:
|
||||||
Varnode *opStackLoad(AddrSpace *spc,uintb off,uint4 sz,PcodeOp *op,Varnode *stackptr,bool insertafter);
|
Varnode *opStackLoad(AddrSpace *spc,uintb off,uint4 sz,PcodeOp *op,Varnode *stackptr,bool insertafter);
|
||||||
PcodeOp *opStackStore(AddrSpace *spc,uintb off,PcodeOp *op,bool insertafter);
|
PcodeOp *opStackStore(AddrSpace *spc,uintb off,PcodeOp *op,bool insertafter);
|
||||||
void opUndoPtradd(PcodeOp *op,bool finalize); ///< Convert a CPUI_PTRADD back into a CPUI_INT_ADD
|
void opUndoPtradd(PcodeOp *op,bool finalize); ///< Convert a CPUI_PTRADD back into a CPUI_INT_ADD
|
||||||
|
void opMarkLanedAccess(const LanedRegister *base,PcodeOp *op,int4 sz,int4 pos); ///< Mark op as using laned register
|
||||||
|
list<LanedAccess>::const_iterator beginLaneAccess(void) const { return lanedList.begin(); } ///< Beginning iterator over laned accesses
|
||||||
|
list<LanedAccess>::const_iterator endLaneAccess(void) const { return lanedList.end(); } ///< Ending iterator over laned accesses
|
||||||
|
void clearLanedAccessList(void) { lanedList.clear(); } ///< Clear records from the laned access list
|
||||||
|
|
||||||
/// \brief Start of PcodeOp objects with the given op-code
|
/// \brief Start of PcodeOp objects with the given op-code
|
||||||
list<PcodeOp *>::const_iterator beginOp(OpCode opc) const { return obank.begin(opc); }
|
list<PcodeOp *>::const_iterator beginOp(OpCode opc) const { return obank.begin(opc); }
|
||||||
|
|
|
@ -557,6 +557,19 @@ void Funcdata::opUndoPtradd(PcodeOp *op,bool finalize)
|
||||||
opInsertBefore(multOp,op);
|
opInsertBefore(multOp,op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Store a record indicating a potential use of a large laned register. Generally, the output
|
||||||
|
/// of the op is the use, except in the case of SUBPIECE or STORE, where getIn(0) and getIn(2)
|
||||||
|
/// respectively are the Varnodes being used.
|
||||||
|
/// \param base is the description of the laned register that is triggering this record
|
||||||
|
/// \param op is the PcodeOp using the large Varnode
|
||||||
|
/// \param sz is the size of the large Varnode in bytes
|
||||||
|
/// \param pos is the significance position of the Varnode, relative to the LanedRegister description
|
||||||
|
void Funcdata::opMarkLanedAccess(const LanedRegister *base,PcodeOp *op,int4 sz,int4 pos)
|
||||||
|
|
||||||
|
{
|
||||||
|
lanedList.push_back(LanedAccess(base,op,sz,pos));
|
||||||
|
}
|
||||||
|
|
||||||
/// Make a clone of the given PcodeOp, copying control-flow properties as well. The data-type
|
/// Make a clone of the given PcodeOp, copying control-flow properties as well. The data-type
|
||||||
/// is \e not cloned.
|
/// is \e not cloned.
|
||||||
/// \param op is the PcodeOp to clone
|
/// \param op is the PcodeOp to clone
|
||||||
|
|
|
@ -98,6 +98,20 @@ public:
|
||||||
bool operator<(const LanedRegister &op2) const { return (storage < op2.storage); } ///< Compare based on VarnodeData
|
bool operator<(const LanedRegister &op2) const { return (storage < op2.storage); } ///< Compare based on VarnodeData
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Record describing the access of a large Varnode that can be traced to a LanedRegister
|
||||||
|
class LanedAccess {
|
||||||
|
const LanedRegister *base; ///< Base register dictating the lane scheme
|
||||||
|
PcodeOp *op; ///< Operation using the big register
|
||||||
|
int4 size; ///< Size of the register in bytes
|
||||||
|
int4 bytePos; ///< Significance position relative to the laned register
|
||||||
|
public:
|
||||||
|
LanedAccess(const LanedRegister *b,PcodeOp *o,int4 sz,int4 pos) { base=b; op=o; size=sz; bytePos=pos; } ///< Constructor
|
||||||
|
const LanedRegister *getBase(void) const { return base; } ///< Get the base LanedRegister being traced
|
||||||
|
PcodeOp *getOp(void) const { return op; } ///< Get the PcodeOp using the large Varnode
|
||||||
|
int4 getSize(void) const { return size; } ///< Get the size of the Varnode being accessed
|
||||||
|
int4 getBytePos(void) const { return bytePos; } ///< Get the significance position relative to the laned register
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief Description of logical lanes within a \b big Varnode
|
/// \brief Description of logical lanes within a \b big Varnode
|
||||||
///
|
///
|
||||||
/// A \b lane is a byte offset and size within a Varnode. Lanes within a
|
/// A \b lane is a byte offset and size within a Varnode. Lanes within a
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue