mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-10 12:08:18 +08:00
GP-6486 Correct distance calculation in nearestArrayedComponent methods
This commit is contained in:
@@ -6087,39 +6087,41 @@ bool AddTreeState::hasMatchingSubType(int8 off,uint4 arrayHint,int8 *newoff) con
|
||||
|
||||
int8 elSizeBefore;
|
||||
int8 offBefore;
|
||||
Datatype *typeBefore = baseType->nearestArrayedComponentBackward(off, &offBefore, &elSizeBefore);
|
||||
if (typeBefore != (Datatype *)0) {
|
||||
if (arrayHint == 1 || elSizeBefore == arrayHint) {
|
||||
int8 sizeAddr = AddrSpace::byteToAddressInt(typeBefore->getSize(),ct->getWordSize());
|
||||
if (offBefore >= 0 && offBefore < sizeAddr) {
|
||||
// If the offset is \e inside a component with a compatible array, return it.
|
||||
*newoff = offBefore;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
int8 typeBefore = baseType->nearestArrayedComponentBackward(off, 128, &offBefore, &elSizeBefore);
|
||||
int8 elSizeAfter;
|
||||
int8 offAfter;
|
||||
Datatype *typeAfter = baseType->nearestArrayedComponentForward(off, &offAfter, &elSizeAfter);
|
||||
if (typeBefore == (Datatype *)0 && typeAfter == (Datatype *)0)
|
||||
int8 typeAfter = baseType->nearestArrayedComponentForward(off, 128, &offAfter, &elSizeAfter);
|
||||
if (typeBefore < 0 && typeAfter < 0)
|
||||
return (baseType->getSubType(off,newoff) != (Datatype *)0);
|
||||
if (typeBefore == (Datatype *)0) {
|
||||
if (typeBefore < 0) {
|
||||
*newoff = offAfter; // Only array is after
|
||||
return true;
|
||||
}
|
||||
if (typeAfter < 0) {
|
||||
*newoff = offBefore; // Only array is before
|
||||
return true;
|
||||
}
|
||||
if (offAfter == offBefore) {
|
||||
*newoff = offAfter;
|
||||
return true;
|
||||
}
|
||||
if (typeAfter == (Datatype *)0) {
|
||||
*newoff = offBefore;
|
||||
return true;
|
||||
// Reaching here we know there is an array before and an array after the offset point
|
||||
if (arrayHint != 1 && elSizeBefore != elSizeAfter) { // element sizes are different, try to distinguish by arrayHint
|
||||
if (elSizeBefore == arrayHint) {
|
||||
*newoff = offBefore;
|
||||
return true;
|
||||
}
|
||||
if (elSizeAfter == arrayHint) {
|
||||
*newoff = offAfter;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (baseType->getSubType(off,newoff) != (Datatype *)0) {
|
||||
if (*newoff == offBefore || *newoff == offAfter)
|
||||
return true; // Offset is contained in one of the arrayed components. Return it.
|
||||
}
|
||||
|
||||
uint8 distBefore = (offBefore < 0) ? -offBefore : offBefore;
|
||||
uint8 distAfter = (offAfter < 0) ? -offAfter : offAfter;
|
||||
if (arrayHint != 1) {
|
||||
if (elSizeBefore != arrayHint)
|
||||
distBefore += 0x1000;
|
||||
if (elSizeAfter != arrayHint)
|
||||
distAfter += 0x1000;
|
||||
}
|
||||
*newoff = (distAfter < distBefore) ? offAfter : offBefore;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -179,30 +179,33 @@ Datatype *Datatype::getSubType(int8 off,int8 *newoff) const
|
||||
return (Datatype *)0;
|
||||
}
|
||||
|
||||
/// Find the first component data-type that is (or contains) an array starting after the given
|
||||
/// offset, and pass back the difference between the component's start and the given offset.
|
||||
/// Return the component data-type or null if no array is found.
|
||||
/// If \b this data-type is (or contains) an array starting after the given
|
||||
/// offset, return the distance in bytes to the start of the array,
|
||||
/// and pass back the difference between the component's start and the given offset.
|
||||
/// \param off is the given offset into \b this data-type
|
||||
/// \param max is the maximum distance, in bytes, to search
|
||||
/// \param newoff is used to pass back the offset difference
|
||||
/// \param elSize is used to pass back the array element size
|
||||
/// \return the component data-type or null
|
||||
Datatype *Datatype::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
/// \return the distance to the array or -1 otherwise
|
||||
int8 Datatype::nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
return (TypeArray *)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Find the last component data-type that is (or contains) an array starting before the given
|
||||
/// offset, and pass back the difference between the component's start and the given offset.
|
||||
/// If \b this data-type is (or contains) an array starting before the given
|
||||
/// offset, return the distance in bytes to the end of the array,
|
||||
/// and pass back the difference between the component's start and the given offset.
|
||||
/// Return the component data-type or null if no array is found.
|
||||
/// \param off is the given offset into \b this data-type
|
||||
/// \param max is the maximum distance, in bytes, to search
|
||||
/// \param newoff is used to pass back the offset difference
|
||||
/// \param elSize is used to pass back the array element size
|
||||
/// \return the component data-type or null
|
||||
Datatype *Datatype::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
/// \return the distance to the array or -1 otherwise
|
||||
int8 Datatype::nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
return (TypeArray *)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Order \b this with another data-type, in a way suitable for the type propagation algorithm.
|
||||
@@ -1132,14 +1135,10 @@ bool TypePointer::testForArraySlack(Datatype *dt,int8 off)
|
||||
int8 elSize;
|
||||
if (dt->getMetatype() == TYPE_ARRAY)
|
||||
return true;
|
||||
Datatype *compType;
|
||||
if (off < 0) {
|
||||
compType = dt->nearestArrayedComponentForward(off, &newoff, &elSize);
|
||||
return (dt->nearestArrayedComponentForward(off, 128, &newoff, &elSize) >= 0);
|
||||
}
|
||||
else {
|
||||
compType = dt->nearestArrayedComponentBackward(off, &newoff, &elSize);
|
||||
}
|
||||
return (compType != (Datatype *)0);
|
||||
return (dt->nearestArrayedComponentBackward(off, 128, &newoff, &elSize) >= 0);
|
||||
}
|
||||
|
||||
/// Parse a \<type> element with a child describing the data-type being pointed to
|
||||
@@ -1378,6 +1377,26 @@ Datatype *TypeArray::getSubType(int8 off,int8 *newoff) const
|
||||
return arrayof;
|
||||
}
|
||||
|
||||
int8 TypeArray::nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
if (off > 0) return -1; // Skip if we are in the middle of array
|
||||
*newoff = off;
|
||||
*elSize = arrayof->getAlignSize();
|
||||
return -off;
|
||||
}
|
||||
|
||||
int8 TypeArray::nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
if (off < 0) return -1; // Skip if we are before array
|
||||
*newoff = off;
|
||||
*elSize = arrayof->getAlignSize();
|
||||
if (off <= size)
|
||||
return (size - off);
|
||||
return (off - size);
|
||||
}
|
||||
|
||||
int4 TypeArray::getHoleSize(int4 off) const
|
||||
|
||||
{
|
||||
@@ -1886,7 +1905,7 @@ int4 TypeStruct::getHoleSize(int4 off) const
|
||||
return getSize() - off; // Distance to end of structure
|
||||
}
|
||||
|
||||
Datatype *TypeStruct::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
int8 TypeStruct::nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
int4 firstIndex = getLowerBoundField(off);
|
||||
@@ -1894,28 +1913,23 @@ Datatype *TypeStruct::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8
|
||||
while(i >= 0) {
|
||||
const TypeField &subfield( field[i] );
|
||||
int8 diff = off - subfield.offset;
|
||||
if (diff > 128) break;
|
||||
Datatype *subtype = subfield.type;
|
||||
if (subtype->getMetatype() == TYPE_ARRAY) {
|
||||
int8 suboff;
|
||||
int8 remain = (i == firstIndex) ? diff : subtype->getSize();
|
||||
if (diff - remain > max) break;
|
||||
int8 distance = subtype->nearestArrayedComponentBackward(remain, max, &suboff, elSize);
|
||||
if (distance >= 0) {
|
||||
distance = (diff - remain) + distance;
|
||||
if (distance > max) break;
|
||||
*newoff = diff;
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getAlignSize();
|
||||
return subtype;
|
||||
}
|
||||
else {
|
||||
int8 suboff;
|
||||
int8 remain = (i == firstIndex) ? diff : subtype->getSize() - 1;
|
||||
Datatype *res = subtype->nearestArrayedComponentBackward(remain, &suboff, elSize);
|
||||
if (res != (Datatype *)0) {
|
||||
*newoff = diff;
|
||||
return subtype;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
return (Datatype *)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Datatype *TypeStruct::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
int8 TypeStruct::nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
int4 i = getLowerBoundField(off);
|
||||
@@ -1924,39 +1938,26 @@ Datatype *TypeStruct::nearestArrayedComponentForward(int8 off,int8 *newoff,int8
|
||||
i += 1; // First component starting after
|
||||
remain = 0;
|
||||
}
|
||||
else {
|
||||
const TypeField &subfield( field[i] );
|
||||
remain = off - subfield.offset;
|
||||
if (remain != 0 && (subfield.type->getMetatype() != TYPE_STRUCT || remain >= subfield.type->getSize())) {
|
||||
i += 1; // Middle of non-structure that we must go forward from, skip over it
|
||||
remain = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
remain = off - field[i].offset;
|
||||
while(i<field.size()) {
|
||||
const TypeField &subfield( field[i] );
|
||||
int8 diff = subfield.offset - off; // The first struct field examined may have a negative diff
|
||||
if (diff > 128) break;
|
||||
if (diff + remain > max) break;
|
||||
Datatype *subtype = subfield.type;
|
||||
if (subtype->getMetatype() == TYPE_ARRAY) {
|
||||
int8 suboff;
|
||||
int8 distance = subtype->nearestArrayedComponentForward(remain, max, &suboff, elSize);
|
||||
if (distance >= 0) {
|
||||
distance = diff + remain + distance;
|
||||
if (distance > max)
|
||||
break;
|
||||
*newoff = -diff;
|
||||
*elSize = ((TypeArray *)subtype)->getBase()->getAlignSize();
|
||||
return subtype;
|
||||
}
|
||||
else {
|
||||
int8 suboff;
|
||||
Datatype *res = subtype->nearestArrayedComponentForward(remain, &suboff, elSize);
|
||||
if (res != (Datatype *)0) {
|
||||
int8 subdiff = diff + remain - suboff;
|
||||
if (subdiff > 128)
|
||||
break;
|
||||
*newoff = -diff;
|
||||
return subtype;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
i += 1;
|
||||
remain = 0;
|
||||
}
|
||||
return (Datatype *)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int4 TypeStruct::compare(const Datatype &op,int4 level) const
|
||||
@@ -3389,7 +3390,7 @@ Datatype *TypeSpacebase::getSubType(int8 off,int8 *newoff) const
|
||||
return smallest->getSymbol()->getType();
|
||||
}
|
||||
|
||||
Datatype *TypeSpacebase::nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
int8 TypeSpacebase::nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
Scope *scope = getMap();
|
||||
@@ -3406,55 +3407,50 @@ Datatype *TypeSpacebase::nearestArrayedComponentForward(int8 off,int8 *newoff,in
|
||||
nextAddr = addr + 32;
|
||||
else {
|
||||
symbolType = smallest->getSymbol()->getType();
|
||||
if (symbolType->getMetatype() == TYPE_STRUCT) {
|
||||
int8 structOff = addr.getOffset() - smallest->getAddr().getOffset();
|
||||
int8 dummyOff;
|
||||
Datatype *res = symbolType->nearestArrayedComponentForward(structOff, &dummyOff, elSize);
|
||||
if (res != (Datatype *)0) {
|
||||
*newoff = structOff;
|
||||
return symbolType;
|
||||
}
|
||||
int8 structOff = addr.getOffset() - smallest->getAddr().getOffset();
|
||||
int8 dummyOff;
|
||||
int8 distance = symbolType->nearestArrayedComponentForward(structOff, max, &dummyOff, elSize);
|
||||
if (distance >= 0) {
|
||||
if (distance > max)
|
||||
return -1;
|
||||
*newoff = structOff;
|
||||
return distance;
|
||||
}
|
||||
int8 sz = AddrSpace::byteToAddressInt(smallest->getSize(), spaceid->getWordSize());
|
||||
nextAddr = smallest->getAddr() + sz;
|
||||
}
|
||||
if (nextAddr < addr)
|
||||
return (Datatype *)0; // Don't let the address wrap
|
||||
return -1; // Don't let the address wrap
|
||||
smallest = scope->queryContainer(nextAddr,1,nullPoint);
|
||||
if (smallest == (SymbolEntry *)0 || smallest->getOffset() != 0)
|
||||
return (Datatype *)0;
|
||||
return -1;
|
||||
symbolType = smallest->getSymbol()->getType();
|
||||
*newoff = addr.getOffset() - smallest->getAddr().getOffset();
|
||||
if (symbolType->getMetatype() == TYPE_ARRAY) {
|
||||
*elSize = ((TypeArray *)symbolType)->getBase()->getAlignSize();
|
||||
return symbolType;
|
||||
int8 dummyOff;
|
||||
int8 distance = symbolType->nearestArrayedComponentForward(0, max, &dummyOff, elSize);
|
||||
if (distance >= 0) {
|
||||
distance = distance - *newoff;
|
||||
if (distance > max)
|
||||
return -1;
|
||||
return distance;
|
||||
}
|
||||
if (symbolType->getMetatype() == TYPE_STRUCT) {
|
||||
int8 dummyOff;
|
||||
Datatype *res = symbolType->nearestArrayedComponentForward(0, &dummyOff, elSize);
|
||||
if (res != (Datatype *)0)
|
||||
return symbolType;
|
||||
}
|
||||
return (Datatype *)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Datatype *TypeSpacebase::nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const
|
||||
int8 TypeSpacebase::nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const
|
||||
|
||||
{
|
||||
Datatype *subType = getSubType(off, newoff);
|
||||
if (subType == (Datatype *)0)
|
||||
return (Datatype *)0;
|
||||
if (subType->getMetatype() == TYPE_ARRAY) {
|
||||
*elSize = ((TypeArray *)subType)->getBase()->getAlignSize();
|
||||
return subType;
|
||||
return -1;
|
||||
int8 dummyOff;
|
||||
int8 distance = subType->nearestArrayedComponentBackward(*newoff,max,&dummyOff,elSize);
|
||||
if (distance >= 0) {
|
||||
if (distance > max)
|
||||
return -1;
|
||||
return distance;
|
||||
}
|
||||
if (subType->getMetatype() == TYPE_STRUCT) {
|
||||
int8 dummyOff;
|
||||
Datatype *res = subType->nearestArrayedComponentBackward(*newoff,&dummyOff,elSize);
|
||||
if (res != (Datatype *)0)
|
||||
return subType;
|
||||
}
|
||||
return (Datatype *)0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int4 TypeSpacebase::compare(const Datatype &op,int4 level) const
|
||||
|
||||
@@ -249,8 +249,8 @@ public:
|
||||
virtual void printRaw(ostream &s) const; ///< Print a description of the type to stream
|
||||
virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const; ///< Recover component data-type one-level down
|
||||
virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
|
||||
/// \brief Get number of bytes at the given offset that are padding
|
||||
///
|
||||
@@ -500,6 +500,8 @@ public:
|
||||
Datatype *getSubEntry(int4 off,int4 sz,int4 *newoff,int4 *el) const; ///< Figure out what a byte range overlaps
|
||||
virtual void printRaw(ostream &s) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual int8 nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int4 getHoleSize(int4 off) const;
|
||||
virtual int4 numDepend(void) const { return 1; }
|
||||
virtual Datatype *getDepend(int4 index) const { return arrayof; }
|
||||
@@ -585,8 +587,8 @@ public:
|
||||
bool hasBitFieldsInRange(int4 offset,int4 sz) const; ///< Return \b true if \b this structure has 1 or more bitfields in the given byte range
|
||||
virtual const TypeField *findTruncation(int8 off,int4 sz,const PcodeOp *op,int4 slot,int8 &newoff) const;
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int4 getHoleSize(int4 off) const;
|
||||
virtual int4 numDepend(void) const { return field.size(); }
|
||||
virtual Datatype *getDepend(int4 index) const { return field[index].type; }
|
||||
@@ -803,8 +805,8 @@ public:
|
||||
Scope *getMap(void) const; ///< Get the symbol table indexed by \b this
|
||||
Address getAddress(uintb off,int4 sz,const Address &point) const; ///< Construct an Address given an offset
|
||||
virtual Datatype *getSubType(int8 off,int8 *newoff) const;
|
||||
virtual Datatype *nearestArrayedComponentForward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual Datatype *nearestArrayedComponentBackward(int8 off,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentForward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int8 nearestArrayedComponentBackward(int8 off,int8 max,int8 *newoff,int8 *elSize) const;
|
||||
virtual int4 compare(const Datatype &op,int4 level) const;
|
||||
virtual int4 compareDependency(const Datatype &op) const; // For tree structure
|
||||
virtual Datatype *clone(void) const { return new TypeSpacebase(*this); }
|
||||
|
||||
Reference in New Issue
Block a user