GP-1297 More explicit support for typedefs in the decompiler (Closes #2393, Closes #3249)

This commit is contained in:
caheckman 2021-09-15 16:50:19 -04:00 committed by ghidra1
parent 8b2ea61e27
commit 8aed810d4a
10 changed files with 259 additions and 124 deletions

View file

@ -231,6 +231,10 @@ Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype,
care_uint_int = true; care_uint_int = true;
isptr = true; isptr = true;
} }
while(reqbase->getTypedef() != (Datatype *)0)
reqbase = reqbase->getTypedef();
while(curbase->getTypedef() != (Datatype *)0)
curbase = curbase->getTypedef();
if (curbase == reqbase) return (Datatype *)0; // Different typedefs could point to the same type if (curbase == reqbase) return (Datatype *)0; // Different typedefs could point to the same type
if ((reqbase->getMetatype()==TYPE_VOID)||(curtype->getMetatype()==TYPE_VOID)) if ((reqbase->getMetatype()==TYPE_VOID)||(curtype->getMetatype()==TYPE_VOID))
return (Datatype *)0; // Don't cast from or to VOID return (Datatype *)0; // Don't cast from or to VOID

View file

@ -311,12 +311,11 @@ void Datatype::saveXmlRef(ostream &s) const
s << "<typeref"; s << "<typeref";
a_v(s,"name",name); a_v(s,"name",name);
if (isVariableLength()) { // For a type with a "variable length" base if (isVariableLength()) { // For a type with a "variable length" base
uintb origId = hashSize(id, size); // Emit the size independent version of the id a_v_u(s,"id",hashSize(id,size)); // Emit the size independent version of the id
s << " id=\"0x" << hex << origId << '\"'; a_v_i(s,"size",size); // but also emit size of this instance
s << " size=\"" << dec << size << '\"'; // but also emit size of this instance
} }
else { else {
s << " id=\"0x" << hex << id << '\"'; a_v_u(s,"id",id);
} }
s << "/>"; s << "/>";
} }
@ -324,6 +323,21 @@ void Datatype::saveXmlRef(ostream &s) const
saveXml(s); saveXml(s);
} }
/// Called only if the \b typedefImm field is non-null. Write the data-type to the
/// stream as a simple \<typedef> tag including only the names and ids of \b this and
/// the data-type it typedefs.
/// \param s is the output stream
void Datatype::saveXmlTypedef(ostream &s) const
{
s << "<def";
a_v(s,"name",name);
a_v_u(s,"id",id);
s << ">";
typedefImm->saveXmlRef(s);
s << "</def>";
}
/// A CPUI_PTRSUB must act on a pointer data-type where the given offset addresses a component. /// A CPUI_PTRSUB must act on a pointer data-type where the given offset addresses a component.
/// Perform this check. /// Perform this check.
/// \param offset is the given offset /// \param offset is the given offset
@ -443,6 +457,10 @@ uint8 Datatype::hashSize(uint8 id,int4 size)
void TypeChar::saveXml(ostream &s) const void TypeChar::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
a_v_b(s,"char",true); a_v_b(s,"char",true);
@ -479,6 +497,10 @@ TypeUnicode::TypeUnicode(const string &nm,int4 sz,type_metatype m)
void TypeUnicode::saveXml(ostream &s) const void TypeUnicode::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
a_v_b(s,"utf",true); a_v_b(s,"utf",true);
@ -488,6 +510,10 @@ void TypeUnicode::saveXml(ostream &s) const
void TypeVoid::saveXml(ostream &s) const void TypeVoid::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<void/>"; s << "<void/>";
} }
@ -533,6 +559,10 @@ int4 TypePointer::compareDependency(const Datatype &op) const
void TypePointer::saveXml(ostream &s) const void TypePointer::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
if (wordsize != 1) if (wordsize != 1)
@ -660,6 +690,10 @@ Datatype *TypeArray::getSubEntry(int4 off,int4 sz,int4 *newoff,int4 *el) const
void TypeArray::saveXml(ostream &s) const void TypeArray::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
a_v_i(s,"arraysize",arraysize); a_v_i(s,"arraysize",arraysize);
@ -830,6 +864,10 @@ int4 TypeEnum::compareDependency(const Datatype &op) const
void TypeEnum::saveXml(ostream &s) const void TypeEnum::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
a_v(s,"enum","true"); a_v(s,"enum","true");
@ -1099,6 +1137,10 @@ int4 TypeStruct::compareDependency(const Datatype &op) const
void TypeStruct::saveXml(ostream &s) const void TypeStruct::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
s << ">\n"; s << ">\n";
@ -1326,6 +1368,10 @@ int4 TypeCode::compareDependency(const Datatype &op) const
void TypeCode::saveXml(ostream &s) const void TypeCode::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
s << ">\n"; s << ">\n";
@ -1500,6 +1546,10 @@ Address TypeSpacebase::getAddress(uintb off,int4 sz,const Address &point) const
void TypeSpacebase::saveXml(ostream &s) const void TypeSpacebase::saveXml(ostream &s) const
{ {
if (typedefImm != (Datatype *)0) {
saveXmlTypedef(s);
return;
}
s << "<type"; s << "<type";
saveXmlBasic(s); saveXmlBasic(s);
a_v(s,"space",spaceid->getName()); a_v(s,"space",spaceid->getName());
@ -1709,7 +1759,7 @@ Datatype *TypeFactory::findByIdLocal(const string &n,uint8 id) const
/// Derived classes may search outside this container. /// Derived classes may search outside this container.
/// \param n is the name of the data-type /// \param n is the name of the data-type
/// \param id is the type id of the data-type /// \param id is the type id of the data-type
/// \param sz is the given distinguishign size if non-zero /// \param sz is the given distinguishing size if non-zero
/// \return the matching Datatype object /// \return the matching Datatype object
Datatype *TypeFactory::findById(const string &n,uint8 id,int4 sz) Datatype *TypeFactory::findById(const string &n,uint8 id,int4 sz)
@ -1745,6 +1795,26 @@ Datatype *TypeFactory::findNoName(Datatype &ct)
return res; return res;
} }
/// Internal method for finally inserting a new Datatype pointer
/// \param newtype is the new pointer
void TypeFactory::insert(Datatype *newtype)
{
pair<DatatypeSet::iterator,bool> insres = tree.insert(newtype);
if (!insres.second) {
ostringstream s;
s << "Shared type id: " << hex << newtype->getId() << endl;
s << " ";
newtype->printRaw(s);
s << " : ";
(*insres.first)->printRaw(s);
delete newtype;
throw LowlevelError(s.str());
}
if (newtype->id!=0)
nametree.insert(newtype);
}
/// Use quickest method (name or id is possible) to locate the matching data-type. /// Use quickest method (name or id is possible) to locate the matching data-type.
/// If its not currently in \b this container, clone the data-type and add it to the container. /// If its not currently in \b this container, clone the data-type and add it to the container.
/// \param ct is the data-type to match /// \param ct is the data-type to match
@ -1770,18 +1840,7 @@ Datatype *TypeFactory::findAdd(Datatype &ct)
} }
newtype = ct.clone(); // Add the new type to trees newtype = ct.clone(); // Add the new type to trees
pair<DatatypeSet::iterator,bool> insres = tree.insert(newtype); insert(newtype);
if (!insres.second) {
ostringstream s;
s << "Shared type id: " << hex << newtype->getId() << endl;
s << " ";
newtype->printRaw(s);
s << " : ";
(*insres.first)->printRaw(s);
throw LowlevelError(s.str());
}
if (newtype->id!=0)
nametree.insert(newtype);
return newtype; return newtype;
} }
@ -1926,6 +1985,8 @@ void TypeFactory::orderRecurse(vector<Datatype *> &deporder,DatatypeSet &mark,
{ // Make sure dependants of ct are in order, then add ct { // Make sure dependants of ct are in order, then add ct
pair<DatatypeSet::iterator,bool> res = mark.insert(ct); pair<DatatypeSet::iterator,bool> res = mark.insert(ct);
if (!res.second) return; // Already inserted before if (!res.second) return; // Already inserted before
if (ct->typedefImm != (Datatype *)0)
orderRecurse(deporder,mark,ct->typedefImm);
int4 size = ct->numDepend(); int4 size = ct->numDepend();
for(int4 i=0;i<size;++i) for(int4 i=0;i<size;++i)
orderRecurse(deporder,mark,ct->getDepend(i)); orderRecurse(deporder,mark,ct->getDepend(i));
@ -2074,6 +2135,32 @@ TypeCode *TypeFactory::getTypeCode(const string &nm)
return (TypeCode *) findAdd(tmp); return (TypeCode *) findAdd(tmp);
} }
/// Find or create a data-type identical to the given data-type except for its name and id.
/// If the name and id already describe an incompatible data-type, an exception is thrown.
/// \param ct is the given data-type to clone
/// \param name is the new name for the clone
/// \param id is the new id for the clone (or 0)
/// \return the (found or created) \e typedef data-type
Datatype *TypeFactory::getTypedef(Datatype *ct,const string &name,uint8 id)
{
if (id == 0)
id = Datatype::hashName(name);
Datatype *res = findByIdLocal(name, id);
if (res != (Datatype *)0) {
if (ct != res->getTypedef())
throw LowlevelError("Trying to create typedef of existing type: " + name);
return res;
}
res = ct->clone(); // Clone everything
res->name = name; // But a new name
res->id = id; // and new id
res->flags &= ~((uint4)Datatype::coretype); // Not a core type
res->typedefImm = ct;
insert(res);
return res;
}
/// This creates a pointer to a given data-type. If the given data-type is /// This creates a pointer to a given data-type. If the given data-type is
/// an array, the TYPE_ARRAY property is stripped off, and a pointer to /// an array, the TYPE_ARRAY property is stripped off, and a pointer to
/// the array element data-type is returned. /// the array element data-type is returned.
@ -2355,6 +2442,37 @@ void TypeFactory::saveXmlCoreTypes(ostream &s) const
s << "</coretypes>\n"; s << "</coretypes>\n";
} }
/// Scan the new id and name. A subtag references the data-type being typedefed.
/// Construct the new data-type based on the referenced data-type but with new name and id.
/// \param el is the \<def> element
/// \return the constructed typedef data-type
Datatype *TypeFactory::restoreTypedef(const Element *el)
{
uint8 id;
istringstream s1(el->getAttributeValue("id"));
s1.unsetf(ios::dec | ios::hex | ios::oct);
s1 >> id;
string nm = el->getAttributeValue("name");
Datatype *defedType = restoreXmlType( *el->getChildren().begin() );
if (defedType->isVariableLength())
id = Datatype::hashSize(id, defedType->size);
if (defedType->getMetatype() == TYPE_STRUCT) {
// Its possible that a typedef of a struct is recursively defined, in which case
// an incomplete version may already be in the container
TypeStruct *prev = (TypeStruct *)findByIdLocal(nm, id);
if (prev != (Datatype *)0) {
if (defedType != prev->getTypedef())
throw LowlevelError("Trying to create typedef of existing type: " + prev->name);
TypeStruct *defedStruct = (TypeStruct *)defedType;
if (prev->field.size() != defedStruct->field.size())
prev->field = defedStruct->field;
return prev;
}
}
return getTypedef(defedType, nm, id);
}
/// Restore a Datatype object from an XML \<type> tag. (Don't use for \<typeref> tags) /// Restore a Datatype object from an XML \<type> tag. (Don't use for \<typeref> tags)
/// The new Datatype is added to \b this container /// The new Datatype is added to \b this container
/// \param el is the XML element /// \param el is the XML element
@ -2366,9 +2484,12 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
string metastring; string metastring;
Datatype *ct; Datatype *ct;
if (el->getNumAttributes() == 0) { char c = el->getName()[0];
if (c != 't') {
if (el->getName() == "void") if (el->getName() == "void")
return getTypeVoid(); // Automatically a coretype return getTypeVoid(); // Automatically a coretype
if (el->getName() == "def")
return restoreTypedef(el);
} }
metastring = el->getAttributeValue("metatype"); metastring = el->getAttributeValue("metatype");
type_metatype meta = string2metatype(metastring); type_metatype meta = string2metatype(metastring);

View file

@ -84,17 +84,21 @@ protected:
type_metatype metatype; ///< Meta-type - type disregarding size type_metatype metatype; ///< Meta-type - type disregarding size
uint4 flags; ///< Boolean properties of the type uint4 flags; ///< Boolean properties of the type
uint8 id; ///< A unique id for the type (or 0 if an id is not assigned) uint8 id; ///< A unique id for the type (or 0 if an id is not assigned)
Datatype *typedefImm; ///< The immediate data-type being typedefed by \e this
void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties
void saveXmlBasic(ostream &s) const; ///< Save basic data-type properties
void saveXmlTypedef(ostream &s) const; ///< Write \b this as a \e typedef tag to stream
virtual void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore data-type from XML virtual void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore data-type from XML
virtual Datatype *clone(void) const=0; ///< Clone the data-type
static uint8 hashName(const string &nm); ///< Produce a data-type id by hashing the type name static uint8 hashName(const string &nm); ///< Produce a data-type id by hashing the type name
static uint8 hashSize(uint8 id,int4 size); ///< Reversibly hash size into id static uint8 hashSize(uint8 id,int4 size); ///< Reversibly hash size into id
public: public:
/// Construct the base data-type copying low-level properties of another /// Construct the base data-type copying low-level properties of another
Datatype(const Datatype &op) { size = op.size; name=op.name; metatype=op.metatype; flags=op.flags; id=op.id; } Datatype(const Datatype &op) { size = op.size; name=op.name; metatype=op.metatype; flags=op.flags; id=op.id; typedefImm=op.typedefImm; }
/// Construct the base data-type providing size and meta-type /// Construct the base data-type providing size and meta-type
Datatype(int4 s,type_metatype m) { size=s; metatype=m; flags=0; id=0; } Datatype(int4 s,type_metatype m) { size=s; metatype=m; flags=0; id=0; typedefImm=(Datatype *)0; }
/// Construct the base data-type providing size, meta-type, and name /// Construct the base data-type providing size, meta-type, and name
Datatype(int4 s,type_metatype m,const string &n) { name=n; size=s; metatype=m; flags=0; id=0; } Datatype(int4 s,type_metatype m,const string &n) { name=n; size=s; metatype=m; flags=0; id=0; typedefImm=(Datatype *)0; }
virtual ~Datatype(void) {} ///< Destructor virtual ~Datatype(void) {} ///< Destructor
bool isCoreType(void) const { return ((flags&coretype)!=0); } ///< Is this a core data-type bool isCoreType(void) const { return ((flags&coretype)!=0); } ///< Is this a core data-type
bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32|opaque_string))!=0); } ///< Does this print as a 'char' bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32|opaque_string))!=0); } ///< Does this print as a 'char'
@ -111,6 +115,7 @@ public:
uint8 getId(void) const { return id; } ///< Get the type id uint8 getId(void) const { return id; } ///< Get the type id
int4 getSize(void) const { return size; } ///< Get the type size int4 getSize(void) const { return size; } ///< Get the type size
const string &getName(void) const { return name; } ///< Get the type name const string &getName(void) const { return name; } ///< Get the type name
Datatype *getTypedef(void) const { return typedefImm; } ///< Get the data-type immediately typedefed by \e this (or null)
virtual void printRaw(ostream &s) const; ///< Print a description of the type to stream virtual void printRaw(ostream &s) const; ///< Print a description of the type to stream
virtual Datatype *getSubType(uintb off,uintb *newoff) const; ///< Recover component data-type one-level down virtual Datatype *getSubType(uintb off,uintb *newoff) const; ///< Recover component data-type one-level down
virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const; virtual Datatype *nearestArrayedComponentForward(uintb off,uintb *newoff,int4 *elSize) const;
@ -120,11 +125,9 @@ public:
virtual void printNameBase(ostream &s) const { if (!name.empty()) s<<name[0]; } ///< Print name as short prefix virtual void printNameBase(ostream &s) const { if (!name.empty()) s<<name[0]; } ///< Print name as short prefix
virtual int4 compare(const Datatype &op,int4 level) const; ///< Order types for propagation virtual int4 compare(const Datatype &op,int4 level) const; ///< Order types for propagation
virtual int4 compareDependency(const Datatype &op) const; ///< Compare for storage in tree structure virtual int4 compareDependency(const Datatype &op) const; ///< Compare for storage in tree structure
virtual Datatype *clone(void) const=0; ///< Clone the data-type
virtual void saveXml(ostream &s) const; ///< Serialize the data-type to XML virtual void saveXml(ostream &s) const; ///< Serialize the data-type to XML
int4 typeOrder(const Datatype &op) const { if (this==&op) return 0; return compare(op,10); } ///< Order this with -op- datatype int4 typeOrder(const Datatype &op) const { if (this==&op) return 0; return compare(op,10); } ///< Order this with -op- datatype
int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special int4 typeOrderBool(const Datatype &op) const; ///< Order \b this with -op-, treating \e bool data-type as special
void saveXmlBasic(ostream &s) const; ///< Save basic data-type properties
void saveXmlRef(ostream &s) const; ///< Write an XML reference of \b this to stream void saveXmlRef(ostream &s) const; ///< Write an XML reference of \b this to stream
bool isPtrsubMatching(uintb offset) const; ///< Is this data-type suitable as input to a CPUI_PTRSUB op bool isPtrsubMatching(uintb offset) const; ///< Is this data-type suitable as input to a CPUI_PTRSUB op
}; };
@ -406,8 +409,10 @@ class TypeFactory {
Datatype *typecache16; ///< Specially cached 16-byte float type Datatype *typecache16; ///< Specially cached 16-byte float type
Datatype *type_nochar; ///< Same dimensions as char but acts and displays as an INT Datatype *type_nochar; ///< Same dimensions as char but acts and displays as an INT
Datatype *findNoName(Datatype &ct); ///< Find data-type (in this container) by function Datatype *findNoName(Datatype &ct); ///< Find data-type (in this container) by function
void insert(Datatype *newtype); ///< Insert pointer into the cross-reference sets
Datatype *findAdd(Datatype &ct); ///< Find data-type in this container or add it Datatype *findAdd(Datatype &ct); ///< Find data-type in this container or add it
void orderRecurse(vector<Datatype *> &deporder,DatatypeSet &mark,Datatype *ct) const; ///< Write out dependency list void orderRecurse(vector<Datatype *> &deporder,DatatypeSet &mark,Datatype *ct) const; ///< Write out dependency list
Datatype *restoreTypedef(const Element *el); ///< Restore a \<def> XML tag describing a typedef
Datatype *restoreXmlTypeNoRef(const Element *el,bool forcecore); ///< Restore from an XML tag Datatype *restoreXmlTypeNoRef(const Element *el,bool forcecore); ///< Restore from an XML tag
void clearCache(void); ///< Clear the common type cache void clearCache(void); ///< Clear the common type cache
TypeChar *getTypeChar(const string &n); ///< Create a default "char" type TypeChar *getTypeChar(const string &n); ///< Create a default "char" type
@ -452,6 +457,7 @@ public:
TypeCode *getTypeCode(ProtoModel *model,Datatype *outtype, TypeCode *getTypeCode(ProtoModel *model,Datatype *outtype,
const vector<Datatype *> &intypes, const vector<Datatype *> &intypes,
bool dotdotdot); ///< Create a "function" datatype bool dotdotdot); ///< Create a "function" datatype
Datatype *getTypedef(Datatype *ct,const string &name,uint8 id); ///< Create a new \e typedef data-type
void destroyType(Datatype *ct); ///< Remove a data-type from \b this void destroyType(Datatype *ct); ///< Remove a data-type from \b this
Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form
void dependentOrder(vector<Datatype *> &deporder) const; ///< Place all data-types in dependency order void dependentOrder(vector<Datatype *> &deporder) const; ///< Place all data-types in dependency order

View file

@ -817,7 +817,8 @@ public class DecompileCallback {
if (type == null) { if (type == null) {
return null; return null;
} }
StringBuilder resBuf = dtmanage.buildType(type, 0); StringBuilder resBuf = new StringBuilder();
dtmanage.buildType(resBuf, type, 0);
resBuf.append("\n"); // Make into official XML document resBuf.append("\n"); // Make into official XML document
String res = resBuf.toString(); String res = resBuf.toString();
if (debug != null) { if (debug != null) {

View file

@ -347,9 +347,11 @@ public class DecompileDebug {
//Next, use the dependency stack to output types. //Next, use the dependency stack to output types.
for (DataType dataType : TypeOrderer.getDependencyList()) { for (DataType dataType : TypeOrderer.getDependencyList()) {
if (!(dataType instanceof BuiltIn)) { if (!(dataType instanceof BuiltIn)) {
debugStream.write( StringBuilder typeBuf = new StringBuilder();
(dtmanage.buildType(dataType, dataType.getLength()) + "\n").toString()
.getBytes()); dtmanage.buildType(typeBuf, dataType, dataType.getLength());
typeBuf.append('\n');
debugStream.write(typeBuf.toString().getBytes());
} }
} }
debugStream.write("</typegrp>\n".getBytes()); debugStream.write("</typegrp>\n".getBytes());

View file

@ -142,7 +142,7 @@ public class DataTypeDependencyOrderer {
/** /**
* This method returns two lists: * This method returns two lists:
* 1) is the set of structs and typedefs to structs. Intended for outputting zero-sized definitions. * 1) is the set of structs. Intended for outputting zero-sized definitions.
* 2) is the acyclic dependency list (broken at structs and pointers to structs) * 2) is the acyclic dependency list (broken at structs and pointers to structs)
* This works (and the dependency graph is able to be broken of cycles) because * This works (and the dependency graph is able to be broken of cycles) because
* structures can be given zero size to start with and then later updated with full size. * structures can be given zero size to start with and then later updated with full size.
@ -156,10 +156,10 @@ public class DataTypeDependencyOrderer {
} }
/** /**
* This method returns the ArrayList of structs and typedefs * This method returns the ArrayList of structs
* to structs found in the input list, intended * to structs found in the input list, intended
* to be used initially as zero-sized structures. * to be used initially as zero-sized structures.
* @return An arrayList of structs and typedefs of structs * @return An arrayList of structs
*/ */
public ArrayList<DataType> getStructList() { public ArrayList<DataType> getStructList() {
if (processed == false) { if (processed == false) {
@ -316,9 +316,8 @@ public class DataTypeDependencyOrderer {
//Msg.debug(this, "ORDERED_LIST_SIZE: " + orderedDependentsList.size() + " -- TYPE: " + //Msg.debug(this, "ORDERED_LIST_SIZE: " + orderedDependentsList.size() + " -- TYPE: " +
// dataType.getName()); // dataType.getName());
orderedDependentsList.add(entry.dataType); orderedDependentsList.add(entry.dataType);
//dependency stack of struct or typedef to struct types for which zero-sized structs should first be used. See _____TODO:method //dependency stack of struct for which zero-sized structs should first be used.
if ((entry.dataType instanceof Structure) || ((entry.dataType instanceof TypeDef) && if (entry.dataType instanceof Structure) {
(((TypeDef) entry.dataType).getBaseDataType() instanceof Structure))) {
structList.add(entry.dataType); structList.add(entry.dataType);
} }
removeMyDependentsEdgesToMe(entry); removeMyDependentsEdgesToMe(entry);
@ -343,8 +342,7 @@ public class DataTypeDependencyOrderer {
procSet.add(subEntry); procSet.add(subEntry);
} }
if (entry.dataType instanceof Pointer) { //avoid cycles with structures/composites if (entry.dataType instanceof Pointer) { //avoid cycles with structures/composites
if ((subType instanceof Structure) || (subType instanceof TypeDef) && if (subType instanceof Structure) {
(((TypeDef) subType).getBaseDataType() instanceof Structure)) {
return; return;
} }
} }

View file

@ -102,7 +102,7 @@ public abstract class ConstantPool {
SpecXmlUtils.xmlEscape(buf, token); SpecXmlUtils.xmlEscape(buf, token);
buf.append("</token>\n"); buf.append("</token>\n");
} }
buf.append(dtmanage.buildTypeRef(type, type.getLength())); dtmanage.buildTypeRef(buf, type, type.getLength());
buf.append("</cpoolrec>\n"); buf.append("</cpoolrec>\n");
return buf; return buf;
} }

View file

@ -378,7 +378,7 @@ public class FunctionPrototype {
res.append("<addr/>\n "); // Don't specify where return type is stored res.append("<addr/>\n "); // Don't specify where return type is stored
} }
res.append(dtmanage.buildTypeRef(returntype, sz)); dtmanage.buildTypeRef(res, returntype, sz);
res.append(" </returnsym>\n"); res.append(" </returnsym>\n");
if (injectname != null) { if (injectname != null) {
res.append("<inject>"); res.append("<inject>");
@ -404,7 +404,7 @@ public class FunctionPrototype {
if (sz < 0) { if (sz < 0) {
sz = 1; sz = 1;
} }
res.append(dtmanage.buildTypeRef(dt, sz)); dtmanage.buildTypeRef(res, dt, sz);
res.append("</param>\n"); res.append("</param>\n");
} }
res.append("</internallist>\n"); res.append("</internallist>\n");

View file

@ -401,7 +401,7 @@ public class HighSymbol {
buf.append("<symbol"); buf.append("<symbol");
saveXMLHeader(buf); saveXMLHeader(buf);
buf.append(">\n"); buf.append(">\n");
buf.append(dtmanage.buildTypeRef(type, getSize())); dtmanage.buildTypeRef(buf, type, getSize());
buf.append("</symbol>\n"); buf.append("</symbol>\n");
} }

View file

@ -164,7 +164,7 @@ public class PcodeDataTypeManager {
* element * element
*/ */
public DataType readXMLDataType(XmlPullParser parser) throws PcodeXMLException { public DataType readXMLDataType(XmlPullParser parser) throws PcodeXMLException {
XmlElement el = parser.start("type", "void", "typeref"); XmlElement el = parser.start("type", "void", "typeref", "def");
try { try {
if (el == null) { if (el == null) {
throw new PcodeXMLException("Bad <type> tag"); throw new PcodeXMLException("Bad <type> tag");
@ -176,6 +176,12 @@ public class PcodeDataTypeManager {
if (el.getName().equals("typeref")) { if (el.getName().equals("typeref")) {
return findBaseType(el.getAttribute("name"), el.getAttribute("id")); return findBaseType(el.getAttribute("name"), el.getAttribute("id"));
} }
if (el.getName().equals("def")) {
String nameStr = el.getAttribute("name");
String idStr = el.getAttribute("id");
parser.discardSubTree(); // Get rid of unused <typeref>
return findBaseType(nameStr, idStr);
}
String name = el.getAttribute("name"); String name = el.getAttribute("name");
if (name.length() != 0) { if (name.length() != 0) {
return findBaseType(name, el.getAttribute("id")); return findBaseType(name, el.getAttribute("id"));
@ -249,25 +255,29 @@ public class PcodeDataTypeManager {
* fully describing the data-type. Where possible a {@code <typeref>} tag is produced, which just gives * fully describing the data-type. Where possible a {@code <typeref>} tag is produced, which just gives
* the name of the data-type, deferring a full description of the data-type. For certain simple or * the name of the data-type, deferring a full description of the data-type. For certain simple or
* nameless data-types, a {@code <type>} tag is emitted giving a full description. * nameless data-types, a {@code <type>} tag is emitted giving a full description.
* @param resBuf is the stream to append the tag to
* @param type is the data-type to be converted * @param type is the data-type to be converted
* @param size is the size in bytes of the specific instance of the data-type * @param size is the size in bytes of the specific instance of the data-type
* @return a StringBuilder containing the XML tag
*/ */
public StringBuilder buildTypeRef(DataType type, int size) { public void buildTypeRef(StringBuilder resBuf, DataType type, int size) {
if (type != null && type.getDataTypeManager() != progDataTypes) { if (type != null && type.getDataTypeManager() != progDataTypes) {
type = type.clone(progDataTypes); type = type.clone(progDataTypes);
} }
if ((type instanceof VoidDataType) || (type == null)) { if ((type instanceof VoidDataType) || (type == null)) {
return buildType(type, size); buildType(resBuf, type, size);
return;
} }
if (type instanceof AbstractIntegerDataType) { if (type instanceof AbstractIntegerDataType) {
return buildType(type, size); buildType(resBuf, type, size);
return;
} }
if (type instanceof Pointer) { if (type instanceof Pointer) {
return buildType(type, size); buildType(resBuf, type, size);
return;
} }
if (type instanceof Array) { if (type instanceof Array) {
return buildType(type, size); buildType(resBuf, type, size);
return;
} }
if (type instanceof FunctionDefinition) { if (type instanceof FunctionDefinition) {
long id = progDataTypes.getID(type); long id = progDataTypes.getID(type);
@ -275,14 +285,15 @@ public class PcodeDataTypeManager {
// Its possible the FunctionDefinition was built on the fly and is not // Its possible the FunctionDefinition was built on the fly and is not
// a permanent data-type of the program with an ID. In this case, we can't // a permanent data-type of the program with an ID. In this case, we can't
// construct a <typeref> tag but must build a full <type> tag. // construct a <typeref> tag but must build a full <type> tag.
return buildType(type, size); buildType(resBuf, type, size);
return;
} }
size = 1; size = 1;
} }
else if (type.getLength() <= 0) { else if (type.getLength() <= 0) {
return buildType(type, size); buildType(resBuf, type, size);
return;
} }
StringBuilder resBuf = new StringBuilder();
resBuf.append("<typeref"); resBuf.append("<typeref");
if (type instanceof BuiltIn) { if (type instanceof BuiltIn) {
SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", SpecXmlUtils.xmlEscapeAttribute(resBuf, "name",
@ -300,24 +311,28 @@ public class PcodeDataTypeManager {
} }
} }
resBuf.append("/>"); resBuf.append("/>");
return resBuf;
} }
private StringBuilder getCharTypeRef(int size) { private void appendCharTypeRef(StringBuilder resBuf, int size) {
if (size == dataOrganization.getCharSize()) { if (size == dataOrganization.getCharSize()) {
return new StringBuilder("<typeref name=\"char\"/>"); // could have size 1 or 2 resBuf.append("<typeref name=\"char\"/>"); // could have size 1 or 2
return;
} }
if (size == dataOrganization.getWideCharSize()) { if (size == dataOrganization.getWideCharSize()) {
return new StringBuilder("<typeref name=\"wchar_t\"/>"); resBuf.append("<typeref name=\"wchar_t\"/>");
return;
} }
if (size == 2) { if (size == 2) {
return new StringBuilder("<typeref name=\"wchar16\"/>"); resBuf.append("<typeref name=\"wchar16\"/>");
return;
} }
if (size == 4) { if (size == 4) {
return new StringBuilder("<typeref name=\"wchar32\"/>"); resBuf.append("<typeref name=\"wchar32\"/>");
return;
} }
if (size == 1) { if (size == 1) {
return new StringBuilder("<typeref name=\"byte\"/>"); resBuf.append("<typeref name=\"byte\"/>");
return;
} }
throw new IllegalArgumentException("Unsupported character size"); throw new IllegalArgumentException("Unsupported character size");
} }
@ -343,22 +358,10 @@ public class PcodeDataTypeManager {
resBuf.append("</field>\n"); resBuf.append("</field>\n");
} }
private String buildTypeInternal(DataType origType, int size) { // Build all of type except name attribute private String buildTypeInternal(StringBuilder resBuf, DataType type, int size) {
DataType type; resBuf.append("<type");
if (origType instanceof TypeDef) {
type = ((TypeDef) origType).getBaseDataType();
}
else {
type = origType;
}
StringBuilder resBuf = new StringBuilder();
if (type instanceof Pointer) { if (type instanceof Pointer) {
if (origType == type) { SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
}
else {
appendNameIdAttributes(resBuf, origType);
}
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "ptr"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "ptr");
int ptrLen = type.getLength(); int ptrLen = type.getLength();
if (ptrLen <= 0) { if (ptrLen <= 0) {
@ -375,54 +378,46 @@ public class PcodeDataTypeManager {
ptrto = ptrto.clone(progDataTypes); ptrto = ptrto.clone(progDataTypes);
} }
StringBuilder ptrtoTypeRef;
if (ptrto == null) { if (ptrto == null) {
ptrtoTypeRef = buildTypeRef(DefaultDataType.dataType, 1); buildTypeRef(resBuf, DefaultDataType.dataType, 1);
} }
else if (ptrto instanceof AbstractStringDataType) { else if (ptrto instanceof AbstractStringDataType) {
if ((ptrto instanceof StringDataType) || if ((ptrto instanceof StringDataType) ||
(type instanceof TerminatedStringDataType)) { // Convert pointer to string (type instanceof TerminatedStringDataType)) { // Convert pointer to string
ptrtoTypeRef = getCharTypeRef(dataOrganization.getCharSize()); // to pointer to char appendCharTypeRef(resBuf, dataOrganization.getCharSize()); // to pointer to char
} }
else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string
// TODO: Need to ensure that UTF8 decoding applies // TODO: Need to ensure that UTF8 decoding applies
ptrtoTypeRef = getCharTypeRef(1); // to pointer to char appendCharTypeRef(resBuf, 1); // to pointer to char
} }
else if ((ptrto instanceof UnicodeDataType) || else if ((ptrto instanceof UnicodeDataType) ||
(ptrto instanceof TerminatedUnicodeDataType)) { (ptrto instanceof TerminatedUnicodeDataType)) {
ptrtoTypeRef = getCharTypeRef(2); appendCharTypeRef(resBuf, 2);
} }
else if ((ptrto instanceof Unicode32DataType) || else if ((ptrto instanceof Unicode32DataType) ||
(ptrto instanceof TerminatedUnicode32DataType)) { (ptrto instanceof TerminatedUnicode32DataType)) {
ptrtoTypeRef = getCharTypeRef(4); appendCharTypeRef(resBuf, 4);
} }
else { else {
ptrtoTypeRef = new StringBuilder(); resBuf.append("<type");
ptrtoTypeRef.append("<type"); appendNameIdAttributes(resBuf, ptrto);
appendNameIdAttributes(ptrtoTypeRef, ptrto); appendOpaqueString(resBuf, ptrto, 16384);
appendOpaqueString(ptrtoTypeRef, ptrto, 16384); resBuf.append("</type>\n");
ptrtoTypeRef.append("</type>\n");
} }
} }
else if (ptrto instanceof FunctionDefinition) { else if (ptrto instanceof FunctionDefinition) {
// FunctionDefinition may have size of -1, do not translate to undefined // FunctionDefinition may have size of -1, do not translate to undefined
ptrtoTypeRef = buildTypeRef(ptrto, ptrto.getLength()); buildTypeRef(resBuf, ptrto, ptrto.getLength());
} }
else if (ptrto.getLength() < 0 && !(ptrto instanceof FunctionDefinition)) { else if (ptrto.getLength() < 0 && !(ptrto instanceof FunctionDefinition)) {
ptrtoTypeRef = buildTypeRef(Undefined1DataType.dataType, 1); buildTypeRef(resBuf, Undefined1DataType.dataType, 1);
} }
else { else {
ptrtoTypeRef = buildTypeRef(ptrto, ptrto.getLength()); buildTypeRef(resBuf, ptrto, ptrto.getLength());
} }
resBuf.append(ptrtoTypeRef);
} }
else if (type instanceof Array) { else if (type instanceof Array) {
if (origType == type) { SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
}
else {
appendNameIdAttributes(resBuf, origType);
}
int sz = type.getLength(); int sz = type.getLength();
if (sz == 0) { if (sz == 0) {
sz = size; sz = size;
@ -432,11 +427,10 @@ public class PcodeDataTypeManager {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize",
((Array) type).getNumElements()); ((Array) type).getNumElements());
resBuf.append('>'); resBuf.append('>');
resBuf.append( buildTypeRef(resBuf, ((Array) type).getDataType(), ((Array) type).getElementLength());
buildTypeRef(((Array) type).getDataType(), ((Array) type).getElementLength()));
} }
else if (type instanceof Structure) { else if (type instanceof Structure) {
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
// if size is 0, insert an Undefined4 component // if size is 0, insert an Undefined4 component
// //
int sz = type.getLength(); int sz = type.getLength();
@ -462,13 +456,13 @@ public class PcodeDataTypeManager {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", comp.getOffset()); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", comp.getOffset());
resBuf.append('>'); resBuf.append('>');
DataType fieldtype = comp.getDataType(); DataType fieldtype = comp.getDataType();
resBuf.append(buildTypeRef(fieldtype, comp.getLength())); buildTypeRef(resBuf, fieldtype, comp.getLength());
resBuf.append("</field>\n"); resBuf.append("</field>\n");
} }
// TODO: trailing flexible array component not yet supported // TODO: trailing flexible array component not yet supported
} }
else if (type instanceof Enum) { else if (type instanceof Enum) {
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
Enum enumDt = (Enum) type; Enum enumDt = (Enum) type;
long[] keys = enumDt.getValues(); long[] keys = enumDt.getValues();
String metatype = "uint"; String metatype = "uint";
@ -490,7 +484,7 @@ public class PcodeDataTypeManager {
} }
} }
else if (type instanceof CharDataType) { else if (type instanceof CharDataType) {
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
boolean signed = ((CharDataType) type).isSigned(); boolean signed = ((CharDataType) type).isSigned();
int sz = type.getLength(); int sz = type.getLength();
if (sz <= 0) { if (sz <= 0) {
@ -508,7 +502,7 @@ public class PcodeDataTypeManager {
} }
else if (type instanceof WideCharDataType || type instanceof WideChar16DataType || else if (type instanceof WideCharDataType || type instanceof WideChar16DataType ||
type instanceof WideChar32DataType) { type instanceof WideChar32DataType) {
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "int"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "int");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength()); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength());
SpecXmlUtils.encodeBooleanAttribute(resBuf, "utf", true); SpecXmlUtils.encodeBooleanAttribute(resBuf, "utf", true);
@ -521,7 +515,7 @@ public class PcodeDataTypeManager {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append('>'); resBuf.append('>');
resBuf.append(getCharTypeRef(dataOrganization.getCharSize())); appendCharTypeRef(resBuf, dataOrganization.getCharSize());
} }
else if (type instanceof StringUTF8DataType) { else if (type instanceof StringUTF8DataType) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
@ -529,7 +523,7 @@ public class PcodeDataTypeManager {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append('>'); resBuf.append('>');
resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies appendCharTypeRef(resBuf, 1); // TODO: Need to ensure that UTF8 decoding applies
} }
else if ((type instanceof UnicodeDataType) || else if ((type instanceof UnicodeDataType) ||
(type instanceof TerminatedUnicodeDataType)) { (type instanceof TerminatedUnicodeDataType)) {
@ -538,7 +532,7 @@ public class PcodeDataTypeManager {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2);
resBuf.append('>'); resBuf.append('>');
resBuf.append(getCharTypeRef(2)); appendCharTypeRef(resBuf, 2);
} }
else if ((type instanceof Unicode32DataType) || else if ((type instanceof Unicode32DataType) ||
(type instanceof TerminatedUnicode32DataType)) { (type instanceof TerminatedUnicode32DataType)) {
@ -547,7 +541,7 @@ public class PcodeDataTypeManager {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4);
resBuf.append('>'); resBuf.append('>');
resBuf.append(getCharTypeRef(4)); appendCharTypeRef(resBuf, 4);
} }
else { else {
appendNameIdAttributes(resBuf, type); appendNameIdAttributes(resBuf, type);
@ -558,7 +552,7 @@ public class PcodeDataTypeManager {
if (size <= 0) { if (size <= 0) {
size = 1; size = 1;
} }
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "code"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "code");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", 1); // Force size of 1 SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", 1); // Force size of 1
resBuf.append('>'); resBuf.append('>');
@ -568,7 +562,7 @@ public class PcodeDataTypeManager {
fproto.buildPrototypeXML(resBuf, this); fproto.buildPrototypeXML(resBuf, this);
} }
else if (type instanceof BooleanDataType) { else if (type instanceof BooleanDataType) {
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "bool"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "bool");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength()); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength());
resBuf.append('>'); resBuf.append('>');
@ -579,13 +573,13 @@ public class PcodeDataTypeManager {
if (sz <= 0) { if (sz <= 0) {
sz = size; sz = size;
} }
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", signed ? "int" : "uint"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", signed ? "int" : "uint");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
resBuf.append('>'); resBuf.append('>');
} }
else if (type instanceof AbstractFloatDataType) { else if (type instanceof AbstractFloatDataType) {
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "float"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "float");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength()); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength());
resBuf.append('>'); resBuf.append('>');
@ -597,7 +591,7 @@ public class PcodeDataTypeManager {
sz = size; sz = size;
isVarLength = true; isVarLength = true;
} }
appendNameIdAttributes(resBuf, origType); appendNameIdAttributes(resBuf, type);
if (sz < 16) { if (sz < 16) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "unknown"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "unknown");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
@ -613,6 +607,7 @@ public class PcodeDataTypeManager {
resBuf.append('>'); resBuf.append('>');
} }
} }
resBuf.append("</type>");
return resBuf.toString(); return resBuf.toString();
} }
@ -633,27 +628,36 @@ public class PcodeDataTypeManager {
/** /**
* Build an XML document string representing the type information for a data type * Build an XML document string representing the type information for a data type
* *
* @param resBuf is the stream to append the document to
* @param type data type to build XML for * @param type data type to build XML for
* @param size size of the data type * @param size size of the data type
*
* @return XML string document
*/ */
public StringBuilder buildType(DataType type, int size) { public void buildType(StringBuilder resBuf, DataType type, int size) {
if (type != null && type.getDataTypeManager() != progDataTypes) { if (type != null && type.getDataTypeManager() != progDataTypes) {
type = type.clone(progDataTypes); type = type.clone(progDataTypes);
} }
StringBuilder resBuf = new StringBuilder();
if ((type instanceof VoidDataType) || (type == null)) { if ((type instanceof VoidDataType) || (type == null)) {
return resBuf.append("<void/>"); resBuf.append("<void/>");
return;
} }
resBuf.append("<type"); else if (type instanceof TypeDef) {
resBuf.append(buildTypeInternal(type, size)); resBuf.append("<def");
resBuf.append("</type>"); appendNameIdAttributes(resBuf, type);
return resBuf; resBuf.append('>');
DataType refType = ((TypeDef) type).getDataType();
int sz = refType.getLength();
if (sz <= 0) {
sz = size;
}
buildTypeRef(resBuf, refType, sz);
resBuf.append("</def>");
return;
}
buildTypeInternal(resBuf, type, size);
} }
/** /**
* Build an XML document string representing the Structure or Typedef to Structure that has * Build an XML document string representing the Structure that has
* its size reported as zero. * its size reported as zero.
* *
* @param type data type to build XML for * @param type data type to build XML for
@ -662,8 +666,7 @@ public class PcodeDataTypeManager {
*/ */
public StringBuilder buildStructTypeZeroSizeOveride(DataType type) { public StringBuilder buildStructTypeZeroSizeOveride(DataType type) {
StringBuilder resBuf = new StringBuilder(); StringBuilder resBuf = new StringBuilder();
if (!((type instanceof Structure) || ((type instanceof TypeDef) && if (!(type instanceof Structure)) {
(((TypeDef) type).getBaseDataType() instanceof Structure)))) {
return resBuf; //empty. Could throw AssertException. return resBuf; //empty. Could throw AssertException.
} }
resBuf.append("<type"); resBuf.append("<type");