Adjust typeref tags for variable length data-types

This commit is contained in:
caheckman 2021-05-21 20:50:10 -04:00
parent 6397e835dc
commit bb7bf84ac9
5 changed files with 35 additions and 11 deletions

View file

@ -309,7 +309,14 @@ void Datatype::saveXmlRef(ostream &s) const
if ((id!=0)&&(metatype != TYPE_VOID)) { if ((id!=0)&&(metatype != TYPE_VOID)) {
s << "<typeref"; s << "<typeref";
a_v(s,"name",name); a_v(s,"name",name);
if (isVariableLength()) { // For a type with a "variable length" base
uintb origId = hashSize(id, size); // Emit the size independent version of the id
s << " id=\"0x" << hex << origId << '\"';
s << " size=\"" << dec << size << '\"'; // but also emit size of this instance
}
else {
s << " id=\"0x" << hex << id << '\"'; s << " id=\"0x" << hex << id << '\"';
}
s << "/>"; s << "/>";
} }
else else
@ -1656,13 +1663,20 @@ Datatype *TypeFactory::findByIdLocal(const string &n,uint8 id) const
return *iter; return *iter;
} }
/// Search for a Datatype by \b name and/or \b id. Derived classes may search outside this container. /// The id is expected to resolve uniquely. Internally, different length instances
/// of a variable length data-type are stored as separate Datatype objects. A non-zero
/// size can be given to distinguish these cases.
/// 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
/// \return the matching Datatype object /// \return the matching Datatype object
Datatype *TypeFactory::findById(const string &n,uint8 id) Datatype *TypeFactory::findById(const string &n,uint8 id,int4 sz)
{ {
if (sz > 0) { // If the id is for a "variable length" base data-type
id = Datatype::hashSize(id, sz); // Construct the id for the "sized" variant
}
return findByIdLocal(n,id); return findByIdLocal(n,id);
} }
@ -1672,7 +1686,7 @@ Datatype *TypeFactory::findById(const string &n,uint8 id)
Datatype *TypeFactory::findByName(const string &n) Datatype *TypeFactory::findByName(const string &n)
{ {
return findById(n,0); return findById(n,0,0);
} }
/// Find data-type without reference to name, using the functional comparators /// Find data-type without reference to name, using the functional comparators
@ -2197,18 +2211,25 @@ Datatype *TypeFactory::restoreXmlType(const Element *el)
Datatype *ct; Datatype *ct;
if (el->getName() == "typeref") { if (el->getName() == "typeref") {
uint8 newid = 0; uint8 newid = 0;
int4 size = -1;
int4 num = el->getNumAttributes(); int4 num = el->getNumAttributes();
for(int4 i=0;i<num;++i) { for(int4 i=0;i<num;++i) {
if (el->getAttributeName(i) == "id") { const string &nm(el->getAttributeName(i));
if (nm == "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 (nm == "size") { // A "size" attribute indicates a "variable length" base
istringstream s(el->getAttributeValue(i));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> size;
}
} }
const string &newname( el->getAttributeValue("name")); const string &newname( el->getAttributeValue("name"));
if (newid == 0) // If there was no id, use the name hash if (newid == 0) // If there was no id, use the name hash
newid = Datatype::hashName(newname); newid = Datatype::hashName(newname);
ct = findById(newname,newid); ct = findById(newname,newid,size);
if (ct == (Datatype *)0) if (ct == (Datatype *)0)
throw LowlevelError("Unable to resolve type: "+newname); throw LowlevelError("Unable to resolve type: "+newname);
return ct; return ct;

View file

@ -415,7 +415,7 @@ class TypeFactory {
protected: protected:
Architecture *glb; ///< The Architecture object that owns this TypeFactory Architecture *glb; ///< The Architecture object that owns this TypeFactory
Datatype *findByIdLocal(const string &nm,uint8 id) const; ///< Search locally by name and id Datatype *findByIdLocal(const string &nm,uint8 id) const; ///< Search locally by name and id
virtual Datatype *findById(const string &n,uint8 id); ///< Search by name and id virtual Datatype *findById(const string &n,uint8 id,int4 sz); ///< Search by \e name and/or \e id
public: public:
TypeFactory(Architecture *g); ///< Construct a factory TypeFactory(Architecture *g); ///< Construct a factory
void setupSizes(void); ///< Derive some size information from Architecture void setupSizes(void); ///< Derive some size information from Architecture

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,10 +15,10 @@
*/ */
#include "typegrp_ghidra.hh" #include "typegrp_ghidra.hh"
Datatype *TypeFactoryGhidra::findById(const string &n,uint8 id) Datatype *TypeFactoryGhidra::findById(const string &n,uint8 id,int4 sz)
{ {
Datatype *ct = TypeFactory::findById(n,id); // Try internal find Datatype *ct = TypeFactory::findById(n,id,sz); // Try internal find
if (ct != (Datatype *)0) return ct; if (ct != (Datatype *)0) return ct;
Document *doc; Document *doc;

View file

@ -29,7 +29,7 @@
/// converted into a Datatype object and cached in this object. /// converted into a Datatype object and cached in this object.
class TypeFactoryGhidra : public TypeFactory { class TypeFactoryGhidra : public TypeFactory {
protected: protected:
virtual Datatype *findById(const string &n,uint8 id); virtual Datatype *findById(const string &n,uint8 id,int4 sz);
public: public:
TypeFactoryGhidra(ArchitectureGhidra *g) : TypeFactory(g) {} ///< Constructor TypeFactoryGhidra(ArchitectureGhidra *g) : TypeFactory(g) {} ///< Constructor
virtual ~TypeFactoryGhidra(void) {} virtual ~TypeFactoryGhidra(void) {}

View file

@ -277,6 +277,7 @@ public class PcodeDataTypeManager {
// 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); return buildType(type, size);
} }
size = 1;
} }
else if (type.getLength() <= 0) { else if (type.getLength() <= 0) {
return buildType(type, size); return buildType(type, size);
@ -294,6 +295,9 @@ public class PcodeDataTypeManager {
if (id > 0) { if (id > 0) {
SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id); SpecXmlUtils.encodeUnsignedIntegerAttribute(resBuf, "id", id);
} }
if (type.getLength() <= 0 && size > 0) {
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "size", size);
}
} }
resBuf.append("/>"); resBuf.append("/>");
return resBuf; return resBuf;