GP-4169 Adjustments to extractPrimitives

This commit is contained in:
caheckman 2024-01-03 00:00:01 +00:00
parent 0c58ce9088
commit 021c5b7af3
6 changed files with 55 additions and 44 deletions

View file

@ -33,20 +33,20 @@ ElementId ELEM_JOIN_PER_PRIMITIVE = ElementId("join_per_primitive",283);
/// \brief Extract an ordered list of primitive data-types making up the given data-type /// \brief Extract an ordered list of primitive data-types making up the given data-type
/// ///
/// The primitive data-types are passed back in an array. If the given data-type is already /// The primitive data-types are passed back in an array. If the given data-type is already
/// primitive, it is passed back as is. Otherwise if it is composite, its components are recursively /// primitive, it is passed back as is. Otherwise if it is composite, its components are
/// listed. If a filler data-type is provided, it is used to fill \e holes in structures. If /// recursively listed. If a maximum number of extracted primitives is exceeded, or if the
/// a maximum number of extracted primitives is exceeded, or if no filler is provided and a hole /// primitives are not properly aligned, or if a non-primitive non-composite data-type is
/// is encountered, or if a non-primitive non-composite data-type is encountered, \b false is returned. /// encountered, false is returned.
/// \param dt is the given data-type to extract primitives from /// \param dt is the given data-type to extract primitives from
/// \param max is the maximum number of primitives to extract before giving up /// \param max is the maximum number of primitives to extract before giving up
/// \param filler is the data-type to use as filler (or null)
/// \param res will hold the list of primitives /// \param res will hold the list of primitives
/// \return \b true if all primitives were extracted /// \return \b true if all primitives were extracted
bool DatatypeFilter::extractPrimitives(Datatype *dt,int4 max,Datatype *filler,vector<Datatype *> &res) bool DatatypeFilter::extractPrimitives(Datatype *dt,int4 max,vector<Datatype *> &res)
{ {
switch(dt->getMetatype()) { switch(dt->getMetatype()) {
case TYPE_UNKNOWN: case TYPE_UNKNOWN:
return false; // Do not consider undefined data-types as primitive
case TYPE_INT: case TYPE_INT:
case TYPE_UINT: case TYPE_UINT:
case TYPE_BOOL: case TYPE_BOOL:
@ -63,7 +63,7 @@ bool DatatypeFilter::extractPrimitives(Datatype *dt,int4 max,Datatype *filler,ve
int4 numEls = ((TypeArray *)dt)->numElements(); int4 numEls = ((TypeArray *)dt)->numElements();
Datatype *base = ((TypeArray *)dt)->getBase(); Datatype *base = ((TypeArray *)dt)->getBase();
for(int4 i=0;i<numEls;++i) { for(int4 i=0;i<numEls;++i) {
if (!extractPrimitives(base,max,filler,res)) if (!extractPrimitives(base,max,res))
return false; return false;
} }
return true; return true;
@ -77,20 +77,19 @@ bool DatatypeFilter::extractPrimitives(Datatype *dt,int4 max,Datatype *filler,ve
int4 curOff = 0; int4 curOff = 0;
vector<TypeField>::const_iterator enditer = structPtr->endField(); vector<TypeField>::const_iterator enditer = structPtr->endField();
for(vector<TypeField>::const_iterator iter=structPtr->beginField();iter!=enditer;++iter) { for(vector<TypeField>::const_iterator iter=structPtr->beginField();iter!=enditer;++iter) {
Datatype *compDt = (*iter).type;
int4 nextOff = (*iter).offset; int4 nextOff = (*iter).offset;
if (nextOff > curOff) { int4 align = dt->getAlignment();
if (filler == (Datatype *)0) int4 rem = curOff % align;
return false; if (rem != 0) {
while(curOff < nextOff) { curOff += (align - rem);
if (res.size() >= max)
return false;
res.push_back(filler);
curOff += filler->getSize();
}
} }
if (!extractPrimitives((*iter).type,max,filler,res)) if (curOff != nextOff) {
return false;
}
curOff = nextOff + compDt->getAlignSize();
if (!extractPrimitives(compDt,max,res))
return false; return false;
curOff += (*iter).type->getSize();
} }
return true; return true;
} }
@ -198,7 +197,7 @@ bool HomogeneousAggregate::filter(Datatype *dt) const
if (meta != TYPE_ARRAY && meta != TYPE_STRUCT) if (meta != TYPE_ARRAY && meta != TYPE_STRUCT)
return false; return false;
vector<Datatype *> res; vector<Datatype *> res;
if (!extractPrimitives(dt, 4, (Datatype *)0, res)) if (!extractPrimitives(dt, 4, res) || res.empty())
return false; return false;
Datatype *base = res[0]; Datatype *base = res[0];
if (base->getMetatype() != metaType) if (base->getMetatype() != metaType)
@ -657,7 +656,7 @@ uint4 MultiMemberAssign::assignAddress(Datatype *dt,const PrototypePieces &proto
vector<int4> tmpStatus = status; vector<int4> tmpStatus = status;
vector<VarnodeData> pieces; vector<VarnodeData> pieces;
vector<Datatype *> primitives; vector<Datatype *> primitives;
if (!DatatypeFilter::extractPrimitives(dt,16,(Datatype *)0,primitives)) if (!DatatypeFilter::extractPrimitives(dt,16,primitives) || primitives.empty())
return fail; return fail;
ParameterPieces param; ParameterPieces param;
for(int4 i=0;i<primitives.size();++i) { for(int4 i=0;i<primitives.size();++i) {

View file

@ -63,7 +63,7 @@ public:
/// \param decoder is the given stream decoder /// \param decoder is the given stream decoder
virtual void decode(Decoder &decoder)=0; virtual void decode(Decoder &decoder)=0;
static bool extractPrimitives(Datatype *dt,int4 max,Datatype *filler,vector<Datatype *> &res); static bool extractPrimitives(Datatype *dt,int4 max,vector<Datatype *> &res);
static DatatypeFilter *decodeFilter(Decoder &decoder); ///< Instantiate a filter from the given stream static DatatypeFilter *decodeFilter(Decoder &decoder); ///< Instantiate a filter from the given stream
}; };

View file

@ -130,6 +130,9 @@ public class ParamListStandard implements ParamList {
int[] status, ParameterPieces res) int[] status, ParameterPieces res)
{ {
if (dt.isZeroLength()) {
return AssignAction.FAIL;
}
for (ModelRule modelRule : modelRules) { for (ModelRule modelRule : modelRules) {
int responseCode = modelRule.assignAddress(dt, proto, pos, dtManager, status, res); int responseCode = modelRule.assignAddress(dt, proto, pos, dtManager, status, res);
if (responseCode != AssignAction.FAIL) { if (responseCode != AssignAction.FAIL) {
@ -178,8 +181,18 @@ public class ParamListStandard implements ParamList {
} }
for (int i = 0; i < proto.intypes.size(); ++i) { for (int i = 0; i < proto.intypes.size(); ++i) {
ParameterPieces store = new ParameterPieces(); ParameterPieces store = new ParameterPieces();
assignAddress(proto.intypes.get(i), proto, i, dtManager, status, store);
res.add(store); res.add(store);
int resCode = assignAddress(proto.intypes.get(i), proto, i, dtManager, status, store);
if (resCode == AssignAction.FAIL) {
// Do not continue to assign after first failure
++i;
while (i < proto.intypes.size()) {
store = new ParameterPieces(); // Fill out with UNASSIGNED pieces
res.add(store);
++i;
}
return;
}
} }
} }

View file

@ -70,24 +70,23 @@ public interface DatatypeFilter {
* Extract an ordered list of primitive data-types making up the given data-type * Extract an ordered list of primitive data-types making up the given data-type
* *
* The primitive data-types are passed back in an ArrayList. If the given data-type is already * The primitive data-types are passed back in an ArrayList. If the given data-type is already
* primitive, it is passed back as is. Otherwise if it is composite, its components are recursively * primitive, it is passed back as is. Otherwise if it is composite, its components are
* listed. If a filler data-type is provided, it is used to fill holes in structures. If * recursively listed. If a maximum number of extracted primitives is exceeded, or if the
* a maximum number of extracted primitives is exceeded, or if no filler is provided and a hole * primitives are not properly aligned, or if a non-primitive non-composite data-type is
* is encountered, or if a non-primitive non-composite data-type is encountered, false is returned. * encountered, false is returned.
* @param dt is the given data-type to extract primitives from * @param dt is the given data-type to extract primitives from
* @param max is the maximum number of primitives to extract before giving up * @param max is the maximum number of primitives to extract before giving up
* @param filler is the data-type to use as filler (or null)
* @param res will hold the list of primitives * @param res will hold the list of primitives
* @return true if all primitives were extracted * @return true if all primitives were extracted
*/ */
public static boolean extractPrimitives(DataType dt, int max, DataType filler, public static boolean extractPrimitives(DataType dt, int max, ArrayList<DataType> res) {
ArrayList<DataType> res) {
if (dt instanceof TypeDef) { if (dt instanceof TypeDef) {
dt = ((TypeDef) dt).getBaseDataType(); dt = ((TypeDef) dt).getBaseDataType();
} }
int metaType = PcodeDataTypeManager.getMetatype(dt); int metaType = PcodeDataTypeManager.getMetatype(dt);
switch (metaType) { switch (metaType) {
case PcodeDataTypeManager.TYPE_UNKNOWN: case PcodeDataTypeManager.TYPE_UNKNOWN:
return false; // Do not consider undefined data-types as primitive
case PcodeDataTypeManager.TYPE_INT: case PcodeDataTypeManager.TYPE_INT:
case PcodeDataTypeManager.TYPE_UINT: case PcodeDataTypeManager.TYPE_UINT:
case PcodeDataTypeManager.TYPE_BOOL: case PcodeDataTypeManager.TYPE_BOOL:
@ -104,7 +103,7 @@ public interface DatatypeFilter {
int numEls = ((Array) dt).getNumElements(); int numEls = ((Array) dt).getNumElements();
DataType base = ((Array) dt).getDataType(); DataType base = ((Array) dt).getDataType();
for (int i = 0; i < numEls; ++i) { for (int i = 0; i < numEls; ++i) {
if (!extractPrimitives(base, max, filler, res)) { if (!extractPrimitives(base, max, res)) {
return false; return false;
} }
} }
@ -116,26 +115,26 @@ public interface DatatypeFilter {
return false; return false;
} }
Structure structPtr = (Structure) dt; Structure structPtr = (Structure) dt;
boolean isPacked = structPtr.isPackingEnabled();
int curOff = 0; int curOff = 0;
DataTypeComponent[] components = structPtr.getDefinedComponents(); DataTypeComponent[] components = structPtr.getDefinedComponents();
for (DataTypeComponent component : components) { for (DataTypeComponent component : components) {
int nextOff = component.getOffset(); DataType compDT = component.getDataType();
if (nextOff > curOff) { if (!isPacked) {
if (filler == null) { int nextOff = component.getOffset();
int align = dt.getAlignment();
int rem = curOff % align;
if (rem != 0) {
curOff += (align - rem);
}
if (curOff != nextOff) {
return false; return false;
} }
while (curOff < nextOff) { curOff = nextOff + compDT.getAlignedLength();
if (res.size() >= max) {
return false;
}
res.add(filler);
curOff += filler.getLength();
}
} }
if (!extractPrimitives(component.getDataType(), max, filler, res)) { if (!extractPrimitives(compDT, max, res)) {
return false; return false;
} }
curOff += component.getDataType().getLength();
} }
return true; return true;
} }

View file

@ -68,7 +68,7 @@ public class HomogeneousAggregate extends SizeRestrictedFilter {
return false; return false;
} }
ArrayList<DataType> res = new ArrayList<>(); ArrayList<DataType> res = new ArrayList<>();
if (!DatatypeFilter.extractPrimitives(dt, MAX_PRIMITIVES, null, res)) { if (!DatatypeFilter.extractPrimitives(dt, MAX_PRIMITIVES, res) || res.isEmpty()) {
return false; return false;
} }
DataType base = res.get(0); DataType base = res.get(0);

View file

@ -78,7 +78,7 @@ public class MultiMemberAssign extends AssignAction {
ArrayList<Varnode> pieces = new ArrayList<>(); ArrayList<Varnode> pieces = new ArrayList<>();
ParameterPieces param = new ParameterPieces(); ParameterPieces param = new ParameterPieces();
ArrayList<DataType> primitives = new ArrayList<>(); ArrayList<DataType> primitives = new ArrayList<>();
if (!DatatypeFilter.extractPrimitives(dt, 16, null, primitives)) { if (!DatatypeFilter.extractPrimitives(dt, 16, primitives) || primitives.isEmpty()) {
return FAIL; return FAIL;
} }
for (int i = 0; i < primitives.size(); ++i) { for (int i = 0; i < primitives.size(); ++i) {