mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
This commit is contained in:
parent
8b2ea61e27
commit
8aed810d4a
10 changed files with 259 additions and 124 deletions
|
@ -231,6 +231,10 @@ Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype,
|
|||
care_uint_int = 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 ((reqbase->getMetatype()==TYPE_VOID)||(curtype->getMetatype()==TYPE_VOID))
|
||||
return (Datatype *)0; // Don't cast from or to VOID
|
||||
|
|
|
@ -311,12 +311,11 @@ void Datatype::saveXmlRef(ostream &s) const
|
|||
s << "<typeref";
|
||||
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
|
||||
a_v_u(s,"id",hashSize(id,size)); // Emit the size independent version of the id
|
||||
a_v_i(s,"size",size); // but also emit size of this instance
|
||||
}
|
||||
else {
|
||||
s << " id=\"0x" << hex << id << '\"';
|
||||
a_v_u(s,"id",id);
|
||||
}
|
||||
s << "/>";
|
||||
}
|
||||
|
@ -324,6 +323,21 @@ void Datatype::saveXmlRef(ostream &s) const
|
|||
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.
|
||||
/// Perform this check.
|
||||
/// \param offset is the given offset
|
||||
|
@ -443,6 +457,10 @@ uint8 Datatype::hashSize(uint8 id,int4 size)
|
|||
void TypeChar::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
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
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
a_v_b(s,"utf",true);
|
||||
|
@ -488,6 +510,10 @@ void TypeUnicode::saveXml(ostream &s) const
|
|||
void TypeVoid::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<void/>";
|
||||
}
|
||||
|
||||
|
@ -533,6 +559,10 @@ int4 TypePointer::compareDependency(const Datatype &op) const
|
|||
void TypePointer::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
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
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
a_v_i(s,"arraysize",arraysize);
|
||||
|
@ -830,6 +864,10 @@ int4 TypeEnum::compareDependency(const Datatype &op) const
|
|||
void TypeEnum::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
a_v(s,"enum","true");
|
||||
|
@ -1099,6 +1137,10 @@ int4 TypeStruct::compareDependency(const Datatype &op) const
|
|||
void TypeStruct::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
s << ">\n";
|
||||
|
@ -1326,6 +1368,10 @@ int4 TypeCode::compareDependency(const Datatype &op) const
|
|||
void TypeCode::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
s << ">\n";
|
||||
|
@ -1500,6 +1546,10 @@ Address TypeSpacebase::getAddress(uintb off,int4 sz,const Address &point) const
|
|||
void TypeSpacebase::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
if (typedefImm != (Datatype *)0) {
|
||||
saveXmlTypedef(s);
|
||||
return;
|
||||
}
|
||||
s << "<type";
|
||||
saveXmlBasic(s);
|
||||
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.
|
||||
/// \param n is the name 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
|
||||
Datatype *TypeFactory::findById(const string &n,uint8 id,int4 sz)
|
||||
|
||||
|
@ -1745,6 +1795,26 @@ Datatype *TypeFactory::findNoName(Datatype &ct)
|
|||
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.
|
||||
/// 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
|
||||
|
@ -1770,18 +1840,7 @@ Datatype *TypeFactory::findAdd(Datatype &ct)
|
|||
}
|
||||
|
||||
newtype = ct.clone(); // Add the new type to trees
|
||||
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);
|
||||
throw LowlevelError(s.str());
|
||||
}
|
||||
if (newtype->id!=0)
|
||||
nametree.insert(newtype);
|
||||
insert(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
|
||||
pair<DatatypeSet::iterator,bool> res = mark.insert(ct);
|
||||
if (!res.second) return; // Already inserted before
|
||||
if (ct->typedefImm != (Datatype *)0)
|
||||
orderRecurse(deporder,mark,ct->typedefImm);
|
||||
int4 size = ct->numDepend();
|
||||
for(int4 i=0;i<size;++i)
|
||||
orderRecurse(deporder,mark,ct->getDepend(i));
|
||||
|
@ -2074,6 +2135,32 @@ TypeCode *TypeFactory::getTypeCode(const string &nm)
|
|||
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
|
||||
/// an array, the TYPE_ARRAY property is stripped off, and a pointer to
|
||||
/// the array element data-type is returned.
|
||||
|
@ -2355,6 +2442,37 @@ void TypeFactory::saveXmlCoreTypes(ostream &s) const
|
|||
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)
|
||||
/// The new Datatype is added to \b this container
|
||||
/// \param el is the XML element
|
||||
|
@ -2366,9 +2484,12 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
|
|||
string metastring;
|
||||
Datatype *ct;
|
||||
|
||||
if (el->getNumAttributes() == 0) {
|
||||
char c = el->getName()[0];
|
||||
if (c != 't') {
|
||||
if (el->getName() == "void")
|
||||
return getTypeVoid(); // Automatically a coretype
|
||||
if (el->getName() == "def")
|
||||
return restoreTypedef(el);
|
||||
}
|
||||
metastring = el->getAttributeValue("metatype");
|
||||
type_metatype meta = string2metatype(metastring);
|
||||
|
|
|
@ -84,17 +84,21 @@ protected:
|
|||
type_metatype metatype; ///< Meta-type - type disregarding size
|
||||
uint4 flags; ///< Boolean properties of the type
|
||||
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 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 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 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; }
|
||||
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
|
||||
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
|
||||
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
|
||||
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'
|
||||
|
@ -111,6 +115,7 @@ public:
|
|||
uint8 getId(void) const { return id; } ///< Get the type id
|
||||
int4 getSize(void) const { return size; } ///< Get the type size
|
||||
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 Datatype *getSubType(uintb off,uintb *newoff) const; ///< Recover component data-type one-level down
|
||||
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 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 Datatype *clone(void) const=0; ///< Clone the data-type
|
||||
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 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
|
||||
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 *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
|
||||
void insert(Datatype *newtype); ///< Insert pointer into the cross-reference sets
|
||||
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
|
||||
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
|
||||
void clearCache(void); ///< Clear the common type cache
|
||||
TypeChar *getTypeChar(const string &n); ///< Create a default "char" type
|
||||
|
@ -452,6 +457,7 @@ public:
|
|||
TypeCode *getTypeCode(ProtoModel *model,Datatype *outtype,
|
||||
const vector<Datatype *> &intypes,
|
||||
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
|
||||
Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form
|
||||
void dependentOrder(vector<Datatype *> &deporder) const; ///< Place all data-types in dependency order
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue