mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
bugfixes, overlapping lanerecords check
This commit is contained in:
parent
04d28bcc4e
commit
ce0ab31576
7 changed files with 56 additions and 13 deletions
|
@ -817,16 +817,33 @@ void Architecture::parseIncidentalCopy(const Element *el)
|
|||
void Architecture::parseLaneSizes(const Element *el)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
const List &childList(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
|
||||
LanedRegister lanedRegister; // Only allocate once
|
||||
for(iter=list.begin();iter!=list.end();++iter) {
|
||||
for(iter=childList.begin();iter!=childList.end();++iter) {
|
||||
if (lanedRegister.restoreXml(*iter, this)) {
|
||||
lanerecords.push_back(lanedRegister);
|
||||
}
|
||||
}
|
||||
if (lanerecords.empty()) return;
|
||||
lanerecords.sort();
|
||||
|
||||
// Dedup records that are contained by (the following) records
|
||||
list<LanedRegister>::const_iterator viter = lanerecords.begin();
|
||||
list<LanedRegister>::const_iterator nextiter = viter;
|
||||
++nextiter;
|
||||
while(nextiter != lanerecords.end()) {
|
||||
if ((*viter).contains(*nextiter)) {
|
||||
lanerecords.erase(nextiter);
|
||||
nextiter = viter;
|
||||
++nextiter;
|
||||
}
|
||||
else {
|
||||
++viter;
|
||||
++nextiter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a stack space and a stack-pointer register from this \<stackpointer> element
|
||||
|
|
|
@ -514,8 +514,8 @@ bool ActionLaneDivide::processVarnode(Funcdata &data,Varnode *vn,const LanedRegi
|
|||
++iter;
|
||||
if (op->code() != CPUI_SUBPIECE) continue;
|
||||
int4 curSize = op->getOut()->getSize();
|
||||
if (lanedRegister.contains(curSize)) {
|
||||
if (checkedLanes.contains(curSize)) continue;
|
||||
if (lanedRegister.allowedLane(curSize)) {
|
||||
if (checkedLanes.allowedLane(curSize)) continue;
|
||||
checkedLanes.addSize(curSize); // Only check this scheme once
|
||||
LaneDescription description(lanedRegister.getStorage().size,curSize); // Lane scheme dictated by curSize
|
||||
int4 bytePos = (int4)(lanedRegister.getStorage().offset - vn->getOffset());
|
||||
|
@ -552,11 +552,11 @@ void ActionLaneDivide::processLane(Funcdata &data,const LanedRegister &lanedRegi
|
|||
++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 (diff != 0 && diff != fullSize/2) // Must be all or half of full register
|
||||
continue;
|
||||
if (processVarnode(data,vn,lanedRegister)) {
|
||||
// If changes were made, iterator may no longer be valid, generate a new one
|
||||
iter = data.beginLoc(startAddress);
|
||||
|
|
|
@ -42,3 +42,14 @@ void VarnodeData::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
|||
}
|
||||
}
|
||||
|
||||
/// Return \b true, if \b this, as an address range, contains the other address range
|
||||
/// \param op2 is the other VarnodeData to test for containment
|
||||
/// \return \b true if \b this contains the other
|
||||
bool VarnodeData::contains(const VarnodeData &op2) const
|
||||
|
||||
{
|
||||
if (space != op2.space) return false;
|
||||
if (op2.offset < offset) return false;
|
||||
if ((offset + (size-1)) < (op2.offset + (op2.size-1))) return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ struct VarnodeData {
|
|||
|
||||
/// Recover this object from an XML tag
|
||||
void restoreXml(const Element *el,const AddrSpaceManager *manage);
|
||||
|
||||
/// Does \b this container another given VarnodeData
|
||||
bool contains(const VarnodeData &op2) const;
|
||||
};
|
||||
|
||||
/// VarnodeData can be sorted in terms of the space its in
|
||||
|
|
|
@ -1964,9 +1964,8 @@ void LaneDivide::buildUnaryOp(OpCode opc,PcodeOp *op,TransformVar *inVars,Transf
|
|||
|
||||
{
|
||||
for(int4 i=0;i<numLanes;++i) {
|
||||
TransformVar *outVn = outVars + i;
|
||||
TransformOp *rop = newOpReplace(1, opc, op);
|
||||
opSetOutput(rop, outVn);
|
||||
opSetOutput(rop, outVars + i);
|
||||
opSetInput(rop,inVars + i,0);
|
||||
}
|
||||
}
|
||||
|
@ -2203,7 +2202,7 @@ bool LaneDivide::traceForward(TransformVar *rvn,int4 numLanes,int4 skipLanes)
|
|||
return false;
|
||||
if (outLanes == 1) {
|
||||
TransformOp *rop = newPreexistingOp(1, CPUI_COPY, op);
|
||||
opSetInput(rop,rvn + (outLanes-skipLanes), 0);
|
||||
opSetInput(rop,rvn + (outSkip-skipLanes), 0);
|
||||
}
|
||||
else {
|
||||
TransformVar *outRvn = setReplacement(outvn,outLanes,outSkip);
|
||||
|
|
|
@ -102,14 +102,14 @@ int4 LaneDescription::getBoundary(int4 bytePos) const
|
|||
return lanePosition.size();
|
||||
int4 min = 0;
|
||||
int4 max = lanePosition.size() - 1;
|
||||
while(min < max) {
|
||||
while(min <= max) {
|
||||
int4 index = (min + max) / 2;
|
||||
int4 pos = lanePosition[index];
|
||||
if (pos == bytePos) return index;
|
||||
if (pos < bytePos)
|
||||
min = pos + 1;
|
||||
min = index + 1;
|
||||
else
|
||||
max = pos - 1;
|
||||
max = index - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -304,6 +304,18 @@ bool LanedRegister::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
|||
return true;
|
||||
}
|
||||
|
||||
/// In order to return \b true, the storage for \b this must contain the storage for the other
|
||||
/// LanedRegister, and every lane scheme of the other LanedRegister must also be a lane scheme
|
||||
/// for \b this.
|
||||
/// \param op2 is the other LanedRegister to check for containment
|
||||
/// \return \b true if \b this contains the other register
|
||||
bool LanedRegister::contains(const LanedRegister &op2) const
|
||||
|
||||
{
|
||||
if (!storage.contains(op2.storage)) return false;
|
||||
return ((sizeBitMask & op2.sizeBitMask) == op2.sizeBitMask); // Check for containment of lane size sets
|
||||
}
|
||||
|
||||
TransformManager::~TransformManager(void)
|
||||
|
||||
{
|
||||
|
|
|
@ -93,7 +93,8 @@ public:
|
|||
bool restoreXml(const Element *el,const AddrSpaceManager *manage); ///< Restore object from XML stream
|
||||
const VarnodeData &getStorage(void) const { return storage; } ///< Get VarnodeData for storage
|
||||
void addSize(int4 size) { sizeBitMask |= ((uint4)1 << size); } ///< Add a new \e size to the allowed list
|
||||
bool contains(int4 size) const { return (((sizeBitMask >> size) & 1) != 0); } ///< Is \e size among the allowed lane sizes
|
||||
bool allowedLane(int4 size) const { return (((sizeBitMask >> size) & 1) != 0); } ///< Is \e size among the allowed lane sizes
|
||||
bool contains(const LanedRegister &op2) const; ///< Does \b this contain the given register and its possible lanes
|
||||
bool operator<(const LanedRegister &op2) const { return (storage < op2.storage); } ///< Compare based on VarnodeData
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue