Opaque strings and variable length data-types

This commit is contained in:
caheckman 2020-04-22 18:23:20 -04:00
parent 2c547ac41b
commit 547a4f2ab5
5 changed files with 211 additions and 76 deletions

View file

@ -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 (curtype == reqtype) return (Datatype *)0; // Different typedefs could point to the same type
if ((reqbase->getMetatype()==TYPE_VOID)||(reqbase->getMetatype()==TYPE_VOID)) if ((reqbase->getMetatype()==TYPE_VOID)||(reqbase->getMetatype()==TYPE_VOID))
return (Datatype *)0; // Don't cast from or to 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()) { switch(reqbase->getMetatype()) {
case TYPE_UNKNOWN: case TYPE_UNKNOWN:
return (Datatype *)0; return (Datatype *)0;

View file

@ -1223,7 +1223,7 @@ bool PrintC::printCharacterConstant(ostream &s,const Address &addr,Datatype *cha
const vector<uint1> &buffer(manager->getStringData(addr, charType, isTrunc)); const vector<uint1> &buffer(manager->getStringData(addr, charType, isTrunc));
if (buffer.empty()) if (buffer.empty())
return false; return false;
if (doEmitWideCharPrefix() && charType->getSize() > 1) if (doEmitWideCharPrefix() && charType->getSize() > 1 && !charType->isOpaqueString())
s << 'L'; // Print symbol indicating wide character s << 'L'; // Print symbol indicating wide character
s << '"'; s << '"';
escapeCharacterData(s,buffer.data(),buffer.size(),1,glb->translate->isBigEndian()); escapeCharacterData(s,buffer.data(),buffer.size(),1,glb->translate->isBigEndian());

View file

@ -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. /// Print a raw description of the type to stream. Intended for debugging.
/// Not intended to produce parsable C. /// Not intended to produce parsable C.
/// \param s is the output stream /// \param s is the output stream
@ -240,8 +254,13 @@ void Datatype::saveXmlBasic(ostream &s) const
{ {
a_v(s,"name",name); a_v(s,"name",name);
if (id != 0) { uint8 saveId;
s << " id=\"0x" << hex << id << '\"'; if (isVariableLength())
saveId = hashSize(id, size);
else
saveId = id;
if (saveId != 0) {
s << " id=\"0x" << hex << saveId << '\"';
} }
a_v_i(s,"size",size); a_v_i(s,"size",size);
string metastring; string metastring;
@ -249,6 +268,10 @@ void Datatype::saveXmlBasic(ostream &s) const
a_v(s,"metatype",metastring); a_v(s,"metatype",metastring);
if ((flags & coretype)!=0) if ((flags & coretype)!=0)
a_v_b(s,"core",true); 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 \<typeref> tag, /// Write a simple reference to \b this data-type as an XML \<typeref> tag,
@ -283,18 +306,31 @@ void Datatype::restoreXmlBasic(const Element *el)
metatype = string2metatype( el->getAttributeValue("metatype") ); metatype = string2metatype( el->getAttributeValue("metatype") );
id = 0; id = 0;
for(int4 i=0;i<el->getNumAttributes();++i) { for(int4 i=0;i<el->getNumAttributes();++i) {
if (el->getAttributeName(i) == "core") { const string &attribName( el->getAttributeName(i) );
if (attribName == "core") {
if (xml_readbool(el->getAttributeValue(i))) if (xml_readbool(el->getAttributeValue(i)))
flags |= coretype; flags |= coretype;
} }
else if (el->getAttributeName(i) == "id") { else if (attribName == "id") {
istringstream i1(el->getAttributeValue(i)); istringstream i1(el->getAttributeValue(i));
i1.unsetf(ios::dec | ios::hex | ios::oct); i1.unsetf(ios::dec | ios::hex | ios::oct);
i1 >> id; 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 if ((id==0)&&(name.size()>0)) // If there is a type name
id = hashName(name); // There must be some kind of id 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 /// Restore a Datatype object from an XML element
@ -326,6 +362,21 @@ uint8 Datatype::hashName(const string &nm)
return res; 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 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 fd is the list of fields to set
/// \param ot is the TypeStruct object to modify /// \param ot is the TypeStruct object to modify
/// \param fixedsize is 0 or the forced size of the structure /// \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 /// \return true if modification was successful
bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize) bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,uint4 flags)
{ {
int4 offset,cursize,curalign; int4 offset,cursize,curalign;
@ -1529,6 +1581,7 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize)
tree.erase(ot); tree.erase(ot);
ot->setFields(fd); 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 > 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 if (fixedsize > ot->size) // If the forced size is bigger than the size required for fields
ot->size = fixedsize; // Force the bigger size ot->size = fixedsize; // Force the bigger size
@ -2073,20 +2126,27 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
int4 num = el->getNumAttributes(); int4 num = el->getNumAttributes();
uint8 newid = 0; uint8 newid = 0;
int4 structsize = 0; int4 structsize = 0;
bool isVarLength = false;
for(int4 i=0;i<num;++i) { for(int4 i=0;i<num;++i) {
if (el->getAttributeName(i) == "id") { const string &attribName(el->getAttributeName(i));
if (attribName == "id") {
istringstream s(el->getAttributeValue(i)); istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct); s.unsetf(ios::dec | ios::hex | ios::oct);
s >> newid; s >> newid;
} }
else if (el->getAttributeName(i) == "size") { else if (attribName == "size") {
istringstream s(el->getAttributeValue(i)); istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct); s.unsetf(ios::dec | ios::hex | ios::oct);
s >> structsize; s >> structsize;
} }
else if (attribName == "varlength") {
isVarLength = xml_readbool(el->getAttributeValue(i));
}
} }
if (newid == 0) if (newid == 0)
newid = Datatype::hashName(structname); newid = Datatype::hashName(structname);
if (isVarLength)
newid = Datatype::hashSize(newid, structsize);
ct = findByIdLocal(structname,newid); ct = findByIdLocal(structname,newid);
bool stubfirst = false; bool stubfirst = false;
if (ct == (Datatype *)0) { if (ct == (Datatype *)0) {
@ -2105,7 +2165,7 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
throw LowlevelError("Redefinition of structure: "+structname); throw LowlevelError("Redefinition of structure: "+structname);
} }
else // If structure is a placeholder stub 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"); throw LowlevelError("Bad structure definition");
} }
break; break;

View file

@ -73,7 +73,9 @@ protected:
enumtype = 4, ///< An enumeration type (as well as an integer) enumtype = 4, ///< An enumeration type (as well as an integer)
poweroftwo = 8, ///< An enumeration type where all values are of 2^^n form poweroftwo = 8, ///< An enumeration type where all values are of 2^^n form
utf16 = 16, ///< 16-bit wide chars in unicode UTF16 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 class TypeFactory;
friend struct DatatypeCompare; friend struct DatatypeCompare;
@ -85,6 +87,7 @@ protected:
void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties
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
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
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; }
@ -94,12 +97,15 @@ public:
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; }
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))!=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 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 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 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 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 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 uint4 getInheritable(void) const { return (flags & coretype); } ///< Get properties pointers inherit
type_metatype getMetatype(void) const { return metatype; } ///< Get the type \b meta-type type_metatype getMetatype(void) const { return metatype; } ///< Get the type \b meta-type
uint8 getId(void) const { return id; } ///< Get the type id 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 Architecture *getArch(void) const { return glb; } ///< Get the Architecture object
Datatype *findByName(const string &n); ///< Return type of given name Datatype *findByName(const string &n); ///< Return type of given name
Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name Datatype *setName(Datatype *ct,const string &n); ///< Set the given types name
bool setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize); ///< Set fields on a TypeStruct bool setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,uint4 flags); ///< Set fields on a TypeStruct
bool setEnumValues(const vector<string> &namelist, bool setEnumValues(const vector<string> &namelist,
const vector<uintb> &vallist, const vector<uintb> &vallist,
const vector<bool> &assignlist, const vector<bool> &assignlist,

View file

@ -318,12 +318,43 @@ public class PcodeDataTypeManager {
throw new IllegalArgumentException("Unsupported character size"); throw new IllegalArgumentException("Unsupported character size");
} }
private String buildTypeInternal(DataType type, int size) { // Build all of type except name attribute private void appendOpaqueString(StringBuilder resBuf, DataType type, int size) {
if (type instanceof TypeDef) { SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "struct");
type = ((TypeDef) type).getBaseDataType(); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "opaquestring", true);
SpecXmlUtils.encodeBooleanAttribute(resBuf, "varlength", true);
resBuf.append(">\n");
resBuf.append("<field name=\"unknown_data1\"");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", 0);
resBuf.append("> <typeref name=\"byte\"/></field>\n");
size -= 1;
resBuf.append("<field name=\"opaque_data\"");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "offset", 1);
resBuf.append("> <type");
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
resBuf.append("><typeref name=\"byte\"/></type>");
resBuf.append("</field>\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(); StringBuilder resBuf = new StringBuilder();
if (type instanceof Pointer) { if (type instanceof Pointer) {
if (origType == type) {
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) {
@ -344,26 +375,35 @@ public class PcodeDataTypeManager {
if (ptrto == null) { if (ptrto == null) {
ptrtoTypeRef = buildTypeRef(DefaultDataType.dataType, 1); ptrtoTypeRef = buildTypeRef(DefaultDataType.dataType, 1);
} }
else if ((ptrto instanceof StringDataType) || else if (ptrto instanceof AbstractStringDataType) {
(type instanceof TerminatedStringDataType)) { // Convert pointer to string if ((ptrto instanceof StringDataType) ||
ptrtoTypeRef = getCharTypeRef(dataOrganization.getCharSize()); // to pointer to char (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 else if (ptrto instanceof StringUTF8DataType) { // Convert pointer to string
ptrtoTypeRef = getCharTypeRef(1); // to pointer to char // 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("<type");
appendNameIdAttributes(ptrtoTypeRef, ptrto);
appendOpaqueString(ptrtoTypeRef, ptrto, 16384);
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()); 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)) { else if (ptrto.getLength() < 0 && !(ptrto instanceof FunctionDefinition)) {
ptrtoTypeRef = buildTypeRef(Undefined1DataType.dataType, 1); ptrtoTypeRef = buildTypeRef(Undefined1DataType.dataType, 1);
} }
@ -373,6 +413,12 @@ public class PcodeDataTypeManager {
resBuf.append(ptrtoTypeRef); resBuf.append(ptrtoTypeRef);
} }
else if (type instanceof Array) { else if (type instanceof Array) {
if (origType == type) {
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;
@ -386,6 +432,7 @@ public class PcodeDataTypeManager {
buildTypeRef(((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);
// if size is 0, insert an Undefined4 component // if size is 0, insert an Undefined4 component
// //
int sz = type.getLength(); int sz = type.getLength();
@ -417,6 +464,7 @@ public class PcodeDataTypeManager {
// 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);
Enum enumDt = (Enum) type; Enum enumDt = (Enum) type;
long[] keys = enumDt.getValues(); long[] keys = enumDt.getValues();
String metatype = "uint"; String metatype = "uint";
@ -438,6 +486,7 @@ public class PcodeDataTypeManager {
} }
} }
else if (type instanceof CharDataType) { else if (type instanceof CharDataType) {
appendNameIdAttributes(resBuf, origType);
boolean signed = ((CharDataType) type).isSigned(); boolean signed = ((CharDataType) type).isSigned();
int sz = type.getLength(); int sz = type.getLength();
if (sz <= 0) { if (sz <= 0) {
@ -455,44 +504,57 @@ 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);
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);
resBuf.append('>'); resBuf.append('>');
} }
else if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) { else if (type instanceof AbstractStringDataType) {
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); if ((type instanceof StringDataType) || (type instanceof TerminatedStringDataType)) {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
resBuf.append('>'); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
resBuf.append(getCharTypeRef(dataOrganization.getCharSize())); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
} resBuf.append('>');
else if (type instanceof StringUTF8DataType) { resBuf.append(getCharTypeRef(dataOrganization.getCharSize()));
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); }
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); else if (type instanceof StringUTF8DataType) {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size); SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
resBuf.append('>'); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
} SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size);
else if ((type instanceof UnicodeDataType) || (type instanceof TerminatedUnicodeDataType)) { resBuf.append('>');
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); resBuf.append(getCharTypeRef(1)); // TODO: Need to ensure that UTF8 decoding applies
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); }
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2); else if ((type instanceof UnicodeDataType) ||
resBuf.append('>'); (type instanceof TerminatedUnicodeDataType)) {
resBuf.append(getCharTypeRef(2)); SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
} SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
else if ((type instanceof Unicode32DataType) || SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
(type instanceof TerminatedUnicode32DataType)) { SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 2);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); resBuf.append('>');
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size); resBuf.append(getCharTypeRef(2));
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", size / 4); }
resBuf.append('>'); else if ((type instanceof Unicode32DataType) ||
resBuf.append(getCharTypeRef(4)); (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) { else if (type instanceof FunctionDefinition) {
if (size <= 0) { if (size <= 0) {
size = 1; size = 1;
} }
appendNameIdAttributes(resBuf, origType);
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('>');
@ -502,6 +564,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);
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('>');
@ -512,11 +575,13 @@ public class PcodeDataTypeManager {
if (sz <= 0) { if (sz <= 0) {
sz = size; sz = size;
} }
appendNameIdAttributes(resBuf, origType);
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);
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('>');
@ -527,11 +592,13 @@ public class PcodeDataTypeManager {
sz = size; sz = size;
} }
if (sz < 16) { if (sz < 16) {
appendNameIdAttributes(resBuf, origType);
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "unknown"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "unknown");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
resBuf.append('>'); resBuf.append('>');
} }
else { else {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array"); SpecXmlUtils.encodeStringAttribute(resBuf, "metatype", "array");
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", sz);
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", sz); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "arraysize", sz);
@ -542,6 +609,20 @@ public class PcodeDataTypeManager {
return resBuf.toString(); 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 * Build an XML document string representing the type information for a data type
* *
@ -559,23 +640,6 @@ public class PcodeDataTypeManager {
return resBuf.append("<void/>"); return resBuf.append("<void/>");
} }
resBuf.append("<type"); resBuf.append("<type");
if ((type instanceof Pointer) || (type instanceof Array) ||
(!(type instanceof FunctionDefinition) && type.getLength() <= 0)) {
SpecXmlUtils.encodeStringAttribute(resBuf, "name", "");
}
else {
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);
}
}
}
resBuf.append(buildTypeInternal(type, size)); resBuf.append(buildTypeInternal(type, size));
resBuf.append("</type>"); resBuf.append("</type>");
return resBuf; return resBuf;