GP-6486 Correct distance calculation in nearestArrayedComponent methods

This commit is contained in:
caheckman
2026-02-20 22:55:14 +00:00
parent da798dfea6
commit c81657d2ae
3 changed files with 120 additions and 120 deletions
@@ -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); }