From 547a4f2ab5c81d9cd0187cf9ec5b97f9d29b38cd Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Wed, 22 Apr 2020 18:23:20 -0400 Subject: [PATCH] Opaque strings and variable length data-types --- .../Decompiler/src/decompile/cpp/cast.cc | 7 +- .../Decompiler/src/decompile/cpp/printc.cc | 2 +- .../Decompiler/src/decompile/cpp/type.cc | 76 ++++++- .../Decompiler/src/decompile/cpp/type.hh | 12 +- .../model/pcode/PcodeDataTypeManager.java | 190 ++++++++++++------ 5 files changed, 211 insertions(+), 76 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc index 95868fbcc3..48c32dc49d 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc @@ -234,7 +234,12 @@ Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype, if (curtype == reqtype) return (Datatype *)0; // Different typedefs could point to the same type if ((reqbase->getMetatype()==TYPE_VOID)||(reqbase->getMetatype()==TYPE_VOID)) return (Datatype *)0; // Don't cast from or to VOID - if (reqbase->getSize() != curbase->getSize()) return reqtype; // Always cast change in size + if (reqbase->getSize() != curbase->getSize()) { + if (reqbase->isVariableLength() && isptr && reqbase->hasSameVariableBase(curbase)) { + return (Datatype *)0; // Don't need a cast + } + return reqtype; // Otherwise, always cast change in size + } switch(reqbase->getMetatype()) { case TYPE_UNKNOWN: return (Datatype *)0; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc index 6d81ac8a9a..8ef64e26d5 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc @@ -1223,7 +1223,7 @@ bool PrintC::printCharacterConstant(ostream &s,const Address &addr,Datatype *cha const vector &buffer(manager->getStringData(addr, charType, isTrunc)); if (buffer.empty()) return false; - if (doEmitWideCharPrefix() && charType->getSize() > 1) + if (doEmitWideCharPrefix() && charType->getSize() > 1 && !charType->isOpaqueString()) s << 'L'; // Print symbol indicating wide character s << '"'; escapeCharacterData(s,buffer.data(),buffer.size(),1,glb->translate->isBigEndian()); diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc index b8c4af1ae7..7bd13949bf 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc @@ -63,6 +63,20 @@ void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseaddr) } } +/// If \b this and the other given data-type are both variable length and come from the +/// the same base data-type, return \b true. +/// \param ct is the other given data-type to compare with \b this +/// \return \b true if they are the same variable length data-type. +bool Datatype::hasSameVariableBase(const Datatype *ct) const + +{ + if (!isVariableLength()) return false; + if (!ct->isVariableLength()) return false; + uint8 thisId = hashSize(id, size); + uint8 themId = hashSize(ct->id, ct->size); + return (thisId == themId); +} + /// Print a raw description of the type to stream. Intended for debugging. /// Not intended to produce parsable C. /// \param s is the output stream @@ -240,8 +254,13 @@ void Datatype::saveXmlBasic(ostream &s) const { a_v(s,"name",name); - if (id != 0) { - s << " id=\"0x" << hex << id << '\"'; + uint8 saveId; + if (isVariableLength()) + saveId = hashSize(id, size); + else + saveId = id; + if (saveId != 0) { + s << " id=\"0x" << hex << saveId << '\"'; } a_v_i(s,"size",size); string metastring; @@ -249,6 +268,10 @@ void Datatype::saveXmlBasic(ostream &s) const a_v(s,"metatype",metastring); if ((flags & coretype)!=0) a_v_b(s,"core",true); + if (isVariableLength()) + a_v_b(s,"varlength",true); + if ((flags & opaque_string)!=0) + a_v_b(s,"opaquestring",true); } /// Write a simple reference to \b this data-type as an XML \ tag, @@ -283,18 +306,31 @@ void Datatype::restoreXmlBasic(const Element *el) metatype = string2metatype( el->getAttributeValue("metatype") ); id = 0; for(int4 i=0;igetNumAttributes();++i) { - if (el->getAttributeName(i) == "core") { + const string &attribName( el->getAttributeName(i) ); + if (attribName == "core") { if (xml_readbool(el->getAttributeValue(i))) flags |= coretype; } - else if (el->getAttributeName(i) == "id") { + else if (attribName == "id") { istringstream i1(el->getAttributeValue(i)); i1.unsetf(ios::dec | ios::hex | ios::oct); i1 >> id; } + else if (attribName == "varlength") { + if (xml_readbool(el->getAttributeValue(i))) + flags |= variable_length; + } + else if (attribName == "opaquestring") { + if (xml_readbool(el->getAttributeValue(i))) + flags |= opaque_string; + } } if ((id==0)&&(name.size()>0)) // If there is a type name id = hashName(name); // There must be some kind of id + if (isVariableLength()) { + // Id needs to be unique compared to another data-type with the same name + id = hashSize(id, size); + } } /// Restore a Datatype object from an XML element @@ -326,6 +362,21 @@ uint8 Datatype::hashName(const string &nm) return res; } +/// This allows IDs for variable length structures to be uniquefied based on size. +/// A base ID is given and a size of the specific instance. A unique ID is returned. +/// The hashing is reversible by feeding the output ID back into this function with the same size. +/// \param id is the given ID to (de)uniquify +/// \param size is the instance size of the structure +/// \param return the (de)uniquified id +uint8 Datatype::hashSize(uint8 id,int4 size) + +{ + uint8 sizeHash = size; + sizeHash *= 0x98251033aecbabaf; // Hash the size + id ^= sizeHash; + return id; +} + void TypeChar::saveXml(ostream &s) const { @@ -1483,8 +1534,9 @@ Datatype *TypeFactory::setName(Datatype *ct,const string &n) /// \param fd is the list of fields to set /// \param ot is the TypeStruct object to modify /// \param fixedsize is 0 or the forced size of the structure +/// \param flags are other flags to set on the structure /// \return true if modification was successful -bool TypeFactory::setFields(vector &fd,TypeStruct *ot,int4 fixedsize) +bool TypeFactory::setFields(vector &fd,TypeStruct *ot,int4 fixedsize,uint4 flags) { int4 offset,cursize,curalign; @@ -1529,6 +1581,7 @@ bool TypeFactory::setFields(vector &fd,TypeStruct *ot,int4 fixedsize) tree.erase(ot); ot->setFields(fd); + ot->flags |= (flags & (Datatype::opaque_string | Datatype::variable_length)); if (fixedsize > 0) { // If the caller is trying to force a size if (fixedsize > ot->size) // If the forced size is bigger than the size required for fields ot->size = fixedsize; // Force the bigger size @@ -2073,20 +2126,27 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore) int4 num = el->getNumAttributes(); uint8 newid = 0; int4 structsize = 0; + bool isVarLength = false; for(int4 i=0;igetAttributeName(i) == "id") { + const string &attribName(el->getAttributeName(i)); + if (attribName == "id") { istringstream s(el->getAttributeValue(i)); s.unsetf(ios::dec | ios::hex | ios::oct); s >> newid; } - else if (el->getAttributeName(i) == "size") { + else if (attribName == "size") { istringstream s(el->getAttributeValue(i)); s.unsetf(ios::dec | ios::hex | ios::oct); s >> structsize; } + else if (attribName == "varlength") { + isVarLength = xml_readbool(el->getAttributeValue(i)); + } } if (newid == 0) newid = Datatype::hashName(structname); + if (isVarLength) + newid = Datatype::hashSize(newid, structsize); ct = findByIdLocal(structname,newid); bool stubfirst = false; if (ct == (Datatype *)0) { @@ -2105,7 +2165,7 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore) throw LowlevelError("Redefinition of structure: "+structname); } else // If structure is a placeholder stub - if (!setFields(ts.field,(TypeStruct *)ct,ts.size)) // Define structure now by copying fields + if (!setFields(ts.field,(TypeStruct *)ct,ts.size,ts.flags)) // Define structure now by copying fields throw LowlevelError("Bad structure definition"); } break; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh index ab60be1820..f5ddd7dba7 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh @@ -73,7 +73,9 @@ protected: enumtype = 4, ///< An enumeration type (as well as an integer) poweroftwo = 8, ///< An enumeration type where all values are of 2^^n form utf16 = 16, ///< 16-bit wide chars in unicode UTF16 - utf32 = 32 ///< 32-bit wide chars in unicode UTF32 + utf32 = 32, ///< 32-bit wide chars in unicode UTF32 + opaque_string = 64, ///< Structure that should be treated as a string + variable_length = 128 ///< May be other structures with same name different lengths }; friend class TypeFactory; friend struct DatatypeCompare; @@ -85,6 +87,7 @@ protected: void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties virtual void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore data-type from XML 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 public: /// 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; } @@ -94,12 +97,15 @@ public: Datatype(int4 s,type_metatype m,const string &n) { name=n; size=s; metatype=m; flags=0; id=0; } virtual ~Datatype(void) {} ///< Destructor bool isCoreType(void) const { return ((flags&coretype)!=0); } ///< Is this a core data-type - bool isCharPrint(void) const { return ((flags&(chartype|utf16|utf32))!=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' bool isEnumType(void) const { return ((flags&enumtype)!=0); } ///< Is this an enumerated type bool isPowerOfTwo(void) const { return ((flags&poweroftwo)!=0); } ///< Is this a flag-based enumeration bool isASCII(void) const { return ((flags&chartype)!=0); } ///< Does this print as an ASCII 'char' bool isUTF16(void) const { return ((flags&utf16)!=0); } ///< Does this print as UTF16 'wchar' bool isUTF32(void) const { return ((flags&utf32)!=0); } ///< Does this print as UTF32 'wchar' + bool isVariableLength(void) const { return ((flags&variable_length)!=0); } ///< Is \b this a variable length structure + bool hasSameVariableBase(const Datatype *ct) const; ///< Are these the same variable length data-type + bool isOpaqueString(void) const { return ((flags&opaque_string)!=0); } ///< Is \b this an opaquely encoded string uint4 getInheritable(void) const { return (flags & coretype); } ///< Get properties pointers inherit type_metatype getMetatype(void) const { return metatype; } ///< Get the type \b meta-type uint8 getId(void) const { return id; } ///< Get the type id @@ -412,7 +418,7 @@ public: Architecture *getArch(void) const { return glb; } ///< Get the Architecture object Datatype *findByName(const string &n); ///< Return type of given name Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name - bool setFields(vector &fd,TypeStruct *ot,int4 fixedsize); ///< Set fields on a TypeStruct + bool setFields(vector &fd,TypeStruct *ot,int4 fixedsize,uint4 flags); ///< Set fields on a TypeStruct bool setEnumValues(const vector &namelist, const vector &vallist, const vector &assignlist, diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java index 0d415f8820..7a1fe9ea3e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/PcodeDataTypeManager.java @@ -318,12 +318,43 @@ public class PcodeDataTypeManager { throw new IllegalArgumentException("Unsupported character size"); } - private String buildTypeInternal(DataType type, int size) { // Build all of type except name attribute - if (type instanceof TypeDef) { - type = ((TypeDef) type).getBaseDataType(); + private void appendOpaqueString(StringBuilder resBuf, DataType type, int size) { + SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "struct"); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); + SpecXmlUtils.encodeBooleanAttribute(resBuf, "opaquestring", true); + SpecXmlUtils.encodeBooleanAttribute(resBuf, "varlength", true); + resBuf.append(">\n"); + resBuf.append(" \n"); + size -= 1; + resBuf.append(" "); + resBuf.append("\n"); + } + + private String buildTypeInternal(DataType origType, int size) { // Build all of type except name attribute + DataType type; + if (origType instanceof TypeDef) { + type = ((TypeDef) origType).getBaseDataType(); + } + else { + type = origType; } StringBuilder resBuf = new StringBuilder(); if (type instanceof Pointer) { + if (origType == type) { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); + } + else { + appendNameIdAttributes(resBuf, origType); + } SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "ptr"); int ptrLen = type.getLength(); if (ptrLen <= 0) { @@ -344,26 +375,35 @@ public class PcodeDataTypeManager { if (ptrto == null) { ptrtoTypeRef = buildTypeRef(DefaultDataType.dataType, 1); } - else if ((ptrto instanceof StringDataType) || - (type instanceof TerminatedStringDataType)) { // Convert pointer to string - ptrtoTypeRef = getCharTypeRef(dataOrganization.getCharSize()); // to pointer to char - } - else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string - // TODO: Need to ensure that UTF8 decoding applies - ptrtoTypeRef = getCharTypeRef(1); // to pointer to char + else if (ptrto instanceof AbstractStringDataType) { + if ((ptrto instanceof StringDataType) || + (type instanceof TerminatedStringDataType)) { // Convert pointer to string + ptrtoTypeRef = getCharTypeRef(dataOrganization.getCharSize()); // to pointer to char + } + else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string + // TODO: Need to ensure that UTF8 decoding applies + ptrtoTypeRef = getCharTypeRef(1); // to pointer to char + } + else if ((ptrto instanceof UnicodeDataType) || + (ptrto instanceof TerminatedUnicodeDataType)) { + ptrtoTypeRef = getCharTypeRef(2); + } + else if ((ptrto instanceof Unicode32DataType) || + (ptrto instanceof TerminatedUnicode32DataType)) { + ptrtoTypeRef = getCharTypeRef(4); + } + else { + ptrtoTypeRef = new StringBuilder(); + ptrtoTypeRef.append("\n"); + } } else if (ptrto instanceof FunctionDefinition) { // FunctionDefinition may have size of -1, do not translate to undefined ptrtoTypeRef = buildTypeRef(ptrto, ptrto.getLength()); } - else if ((ptrto instanceof UnicodeDataType) || - (ptrto instanceof TerminatedUnicodeDataType)) { - ptrtoTypeRef = getCharTypeRef(2); - } - else if ((ptrto instanceof Unicode32DataType) || - (ptrto instanceof TerminatedUnicode32DataType)) { - ptrtoTypeRef = getCharTypeRef(4); - } else if (ptrto.getLength() < 0 && !(ptrto instanceof FunctionDefinition)) { ptrtoTypeRef = buildTypeRef(Undefined1DataType.dataType, 1); } @@ -373,6 +413,12 @@ public class PcodeDataTypeManager { resBuf.append(ptrtoTypeRef); } else if (type instanceof Array) { + if (origType == type) { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); + } + else { + appendNameIdAttributes(resBuf, origType); + } int sz = type.getLength(); if (sz == 0) { sz = size; @@ -386,6 +432,7 @@ public class PcodeDataTypeManager { buildTypeRef(((Array) type).getDataType(), ((Array) type).getElementLength())); } else if (type instanceof Structure) { + appendNameIdAttributes(resBuf, origType); // if size is 0, insert an Undefined4 component // int sz = type.getLength(); @@ -417,6 +464,7 @@ public class PcodeDataTypeManager { // TODO: trailing flexible array component not yet supported } else if (type instanceof Enum) { + appendNameIdAttributes(resBuf, origType); Enum enumDt = (Enum) type; long[] keys = enumDt.getValues(); String metatype = "uint"; @@ -438,6 +486,7 @@ public class PcodeDataTypeManager { } } else if (type instanceof CharDataType) { + appendNameIdAttributes(resBuf, origType); boolean signed = ((CharDataType) type).isSigned(); int sz = type.getLength(); if (sz <= 0) { @@ -455,44 +504,57 @@ public class PcodeDataTypeManager { } else if (type instanceof WideCharDataType || type instanceof WideChar16DataType || type instanceof WideChar32DataType) { + appendNameIdAttributes(resBuf, origType); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "int"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength()); SpecXmlUtils.encodeBooleanAttribute(resBuf, "utf", true); resBuf.append('>'); } - else if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) { - SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); - resBuf.append('>'); - resBuf.append(getCharTypeRef(dataOrganization.getCharSize())); - } - else if (type instanceof StringUTF8DataType) { - SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); - resBuf.append('>'); - resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies - } - else if ((type instanceof UnicodeDataType) || (type instanceof TerminatedUnicodeDataType)) { - SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2); - resBuf.append('>'); - resBuf.append(getCharTypeRef(2)); - } - else if ((type instanceof Unicode32DataType) || - (type instanceof TerminatedUnicode32DataType)) { - SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); - SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4); - resBuf.append('>'); - resBuf.append(getCharTypeRef(4)); + else if (type instanceof AbstractStringDataType) { + if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); + SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); + resBuf.append('>'); + resBuf.append(getCharTypeRef(dataOrganization.getCharSize())); + } + else if (type instanceof StringUTF8DataType) { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); + SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); + resBuf.append('>'); + resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies + } + else if ((type instanceof UnicodeDataType) || + (type instanceof TerminatedUnicodeDataType)) { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); + SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2); + resBuf.append('>'); + resBuf.append(getCharTypeRef(2)); + } + else if ((type instanceof Unicode32DataType) || + (type instanceof TerminatedUnicode32DataType)) { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); + SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); + SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4); + resBuf.append('>'); + resBuf.append(getCharTypeRef(4)); + } + else { + appendNameIdAttributes(resBuf, type); + appendOpaqueString(resBuf, type, size); + } } else if (type instanceof FunctionDefinition) { if (size <= 0) { size = 1; } + appendNameIdAttributes(resBuf, origType); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "code"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", 1); // Force size of 1 resBuf.append('>'); @@ -502,6 +564,7 @@ public class PcodeDataTypeManager { fproto.buildPrototypeXML(resBuf, this); } else if (type instanceof BooleanDataType) { + appendNameIdAttributes(resBuf, origType); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "bool"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength()); resBuf.append('>'); @@ -512,11 +575,13 @@ public class PcodeDataTypeManager { if (sz <= 0) { sz = size; } + appendNameIdAttributes(resBuf, origType); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", signed ? "int" : "uint"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); resBuf.append('>'); } else if (type instanceof AbstractFloatDataType) { + appendNameIdAttributes(resBuf, origType); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "float"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", type.getLength()); resBuf.append('>'); @@ -527,11 +592,13 @@ public class PcodeDataTypeManager { sz = size; } if (sz < 16) { + appendNameIdAttributes(resBuf, origType); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "unknown"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); resBuf.append('>'); } else { + SpecXmlUtils.encodeStringAttribute(resBuf, "name", ""); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", sz); @@ -542,6 +609,20 @@ public class PcodeDataTypeManager { return resBuf.toString(); } + private void appendNameIdAttributes(StringBuilder resBuf, DataType type) { + if (type instanceof BuiltIn) { + SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", + ((BuiltIn) type).getDecompilerDisplayName(displayLanguage)); + } + else { + SpecXmlUtils.xmlEscapeAttribute(resBuf, "name", type.getName()); + long id = progDataTypes.getID(type); + if (id > 0) { + SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id); + } + } + } + /** * Build an XML document string representing the type information for a data type * @@ -559,23 +640,6 @@ public class PcodeDataTypeManager { return resBuf.append(""); } resBuf.append(" 0) { - SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id); - } - } - } resBuf.append(buildTypeInternal(type, size)); resBuf.append(""); return resBuf;