mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-4169 Adjustments to extractPrimitives
This commit is contained in:
parent
0c58ce9088
commit
021c5b7af3
6 changed files with 55 additions and 44 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue