diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc index a24ebaf589..3f7a2bf653 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/ifacedecomp.cc @@ -3163,6 +3163,9 @@ void IfcLoadTestFile::execute(istream &s) s >> filename; dcp->testCollection = new FunctionTestCollection(status); dcp->testCollection->loadTest(filename); +#ifdef OPACTION_DEBUG + dcp->conf->setDebugStream(status->fileoptr); +#endif *status->optr << filename << " test successfully loaded: " << dcp->conf->getDescription() << endl; } diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc index 0474aa60fd..126c473963 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.cc @@ -16,6 +16,11 @@ #include "type.hh" #include "funcdata.hh" +sub_metatype Datatype::base2sub[11] = { + SUB_STRUCT, SUB_ARRAY, SUB_PTR, SUB_FLOAT, SUB_CODE, SUB_BOOL, + SUB_UINT_PLAIN, SUB_INT_PLAIN, SUB_UNKNOWN, SUB_SPACEBASE, SUB_VOID +}; + // Some default routines for displaying data /// Display an array of bytes as a hex dump at a given address. @@ -138,7 +143,9 @@ Datatype *Datatype::nearestArrayedComponentBackward(uintb off,uintb *newoff,int4 int4 Datatype::compare(const Datatype &op,int4 level) const { - return compareDependency(op); + if (size != op.size) return (op.size - size); + if (submeta != op.submeta) return (submeta < op.submeta) ? -1 : 1; + return 0; } /// Sort data-types for the main TypeFactory container. The sort needs to be based on @@ -152,15 +159,7 @@ int4 Datatype::compareDependency(const Datatype &op) const { if (size != op.size) return (op.size-size); - if (metatype != op.metatype) return (metatype < op.metatype) ? -1 : 1; - uint4 fl = flags & (~coretype); - uint4 opfl = op.flags & (~coretype); - // We need to be careful here, we compare flags so that enum types are more specific than base int or uint, - // we also want UTF16 and UTF32 to be more specific than int, BUT - // we don't want char to be more specific than int1 because char is the default size 1 integer type. - fl ^= chartype; - opfl ^= chartype; - if (fl != opfl) return (opfl < fl) ? -1 : 1; + if (submeta != op.submeta) return (submeta < op.submeta) ? -1 : 1; return 0; } @@ -381,6 +380,7 @@ void Datatype::restoreXmlBasic(const Element *el) if (size < 0) throw LowlevelError("Bad size for type "+name); metatype = string2metatype( el->getAttributeValue("metatype") ); + submeta = base2sub[metatype]; id = 0; for(int4 i=0;igetNumAttributes();++i) { const string &attribName( el->getAttributeName(i) ); @@ -454,6 +454,13 @@ uint8 Datatype::hashSize(uint8 id,int4 size) return id; } +void TypeChar::restoreXml(const Element *el,TypeFactory &typegrp) + +{ + restoreXmlBasic(el); + submeta = (metatype == TYPE_INT) ? SUB_INT_CHAR : SUB_UINT_CHAR; +} + void TypeChar::saveXml(ostream &s) const { @@ -486,12 +493,14 @@ void TypeUnicode::restoreXml(const Element *el,TypeFactory &typegrp) restoreXmlBasic(el); // Get endianness flag from architecture, rather than specific type encoding setflags(); + submeta = (metatype == TYPE_INT) ? SUB_INT_UNICODE : SUB_UINT_UNICODE; } TypeUnicode::TypeUnicode(const string &nm,int4 sz,type_metatype m) : TypeBase(sz,m,nm) { setflags(); // Set special unicode UTF flags + submeta = (m == TYPE_INT) ? SUB_INT_UNICODE : SUB_UINT_UNICODE; } void TypeUnicode::saveXml(ostream &s) const @@ -527,12 +536,10 @@ void TypePointer::printRaw(ostream &s) const int4 TypePointer::compare(const Datatype &op,int4 level) const { - TypePointer *tp; - - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; + int4 res = Datatype::compare(op,level); + if (res != 0) return res; // Both must be pointers - tp = (TypePointer *) &op; + TypePointer *tp = (TypePointer *) &op; if (wordsize != tp->wordsize) return (wordsize < tp->wordsize) ? -1 : 1; level -= 1; if (level < 0) { @@ -545,12 +552,10 @@ int4 TypePointer::compare(const Datatype &op,int4 level) const int4 TypePointer::compareDependency(const Datatype &op) const { - TypePointer *tp; - - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; + int4 res = Datatype::compareDependency(op); + if (res != 0) return res; // Both must be pointers - tp = (TypePointer *) &op; + TypePointer *tp = (TypePointer *) &op; if (wordsize != tp->wordsize) return (wordsize < tp->wordsize) ? -1 : 1; if (ptrto == tp->ptrto) return 0; return (ptrto < tp->ptrto) ? -1 : 1; // Compare the absolute pointers @@ -636,27 +641,23 @@ void TypeArray::printRaw(ostream &s) const int4 TypeArray::compare(const Datatype &op,int4 level) const { - TypeArray *ta; - - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; + int4 res = Datatype::compare(op,level); + if (res != 0) return res; level -= 1; if (level < 0) { if (id == op.getId()) return 0; return (id < op.getId()) ? -1 : 1; } - ta = (TypeArray *) &op; // Both must be arrays + TypeArray *ta = (TypeArray *) &op; // Both must be arrays return arrayof->compare(*ta->arrayof,level); // Compare array elements } int4 TypeArray::compareDependency(const Datatype &op) const { - TypeArray *ta; - - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; - ta = (TypeArray *) &op; // Both must be arrays + int4 res = Datatype::compareDependency(op); + if (res != 0) return res; + TypeArray *ta = (TypeArray *) &op; // Both must be arrays if (arrayof == ta->arrayof) return 0; return (arrayof < ta->arrayof) ? -1 : 1; } @@ -886,6 +887,7 @@ void TypeEnum::restoreXml(const Element *el,TypeFactory &typegrp) { restoreXmlBasic(el); + submeta = (metatype == TYPE_INT) ? SUB_INT_ENUM : SUB_UINT_ENUM; const List &list(el->getChildren()); List::const_iterator iter; map nmap; @@ -1067,9 +1069,8 @@ Datatype *TypeStruct::nearestArrayedComponentForward(uintb off,uintb *newoff,int int4 TypeStruct::compare(const Datatype &op,int4 level) const { - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; - + int4 res = Datatype::compare(op,level); + if (res != 0) return res; const TypeStruct *ts = (const TypeStruct *)&op; vector::const_iterator iter1,iter2; @@ -1109,9 +1110,8 @@ int4 TypeStruct::compare(const Datatype &op,int4 level) const int4 TypeStruct::compareDependency(const Datatype &op) const { - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; - + int4 res = Datatype::compareDependency(op); + if (res != 0) return res; const TypeStruct *ts = (const TypeStruct *)&op; vector::const_iterator iter1,iter2; @@ -1269,9 +1269,6 @@ void TypeCode::setProperties(bool isConstructor,bool isDestructor) int4 TypeCode::compareBasic(const TypeCode *op) const { - if (size != op->getSize()) return (op->getSize() < size) ? -1 : 1; - if (metatype != op->getMetatype()) return (metatype < op->getMetatype()) ? -1 : 1; - if (proto == (FuncProto *)0) { if (op->proto == (FuncProto *)0) return 0; return 1; @@ -1312,8 +1309,10 @@ Datatype *TypeCode::getSubType(uintb off,uintb *newoff) const int4 TypeCode::compare(const Datatype &op,int4 level) const { + int4 res = Datatype::compare(op,level); + if (res != 0) return res; const TypeCode *tc = (const TypeCode *)&op; - int4 res = compareBasic(tc); + res = compareBasic(tc); if (res != 2) return res; level -= 1; @@ -1342,8 +1341,10 @@ int4 TypeCode::compare(const Datatype &op,int4 level) const int4 TypeCode::compareDependency(const Datatype &op) const { + int4 res = Datatype::compareDependency(op); + if (res != 0) return res; const TypeCode *tc = (const TypeCode *)&op; - int4 res = compareBasic(tc); + res = compareBasic(tc); if (res != 2) return res; int4 nump = proto->numParams(); @@ -1518,8 +1519,8 @@ int4 TypeSpacebase::compare(const Datatype &op,int4 level) const int4 TypeSpacebase::compareDependency(const Datatype &op) const { - if (size != op.getSize()) return (op.getSize()-size); - if (metatype != op.getMetatype()) return (metatype < op.getMetatype()) ? -1 : 1; + int4 res = Datatype::compareDependency(op); + if (res != 0) return res; TypeSpacebase *tsb = (TypeSpacebase *) &op; if (spaceid != tsb->spaceid) return (spaceid < tsb->spaceid) ? -1:1; if (localframe.isInvalid()) return 0; // Global space base diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh index 660cb0d0b2..b6aee62aca 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/type.hh @@ -45,6 +45,26 @@ enum type_metatype { TYPE_STRUCT = 0 ///< Structure data-type, made up of component datatypes }; +enum sub_metatype { + SUB_VOID = 16, ///< Compare as a TYPE_VOID + SUB_SPACEBASE = 15, ///< Compare as a TYPE_SPACEBASE + SUB_UNKNOWN = 14, ///< Compare as a TYPE_UNKNOWN + SUB_INT_CHAR = 13, ///< Signed 1-byte character, sub-type of TYPE_INT + SUB_UINT_CHAR = 12, ///< Unsigned 1-byte character, sub-type of TYPE_UINT + SUB_INT_PLAIN = 11, ///< Compare as a plain TYPE_INT + SUB_UINT_PLAIN = 10, ///< Compare as a plain TYPE_UINT + SUB_INT_ENUM = 9, ///< Signed enum, sub-type of TYPE_INT + SUB_UINT_ENUM = 8, ///< Unsigned enum, sub-type of TYPE_UINT + SUB_INT_UNICODE = 7, ///< Signed wide character, sub-type of TYPE_INT + SUB_UINT_UNICODE = 6, ///< Unsigned wide character, sub-type of TYPE_UINT + SUB_BOOL = 5, ///< Compare as TYPE_BOOL + SUB_CODE = 4, ///< Compare as TYPE_CODE + SUB_FLOAT = 3, ///< Compare as TYPE_FLOAT + + SUB_PTR = 2, ///< Compare as TYPE_PTR + SUB_ARRAY = 1, ///< Compare as TYPE_ARRAY + SUB_STRUCT = 0 ///< Compare as TYPE_STRUCT +}; /// Convert type \b meta-type to name extern void metatype2string(type_metatype metatype,string &res); @@ -61,6 +81,7 @@ struct DatatypeCompare; /// Used for symbols, function prototypes, type propagation etc. class Datatype { protected: + static sub_metatype base2sub[11]; /// Boolean properties of datatypes enum { coretype = 1, ///< This is a basic type which will never be redefined @@ -82,6 +103,7 @@ protected: int4 size; ///< Size (of variable holding a value of this type) string name; ///< Name of type type_metatype metatype; ///< Meta-type - type disregarding size + sub_metatype submeta; ///< Sub-type of of the meta-type, for comparisons 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 @@ -94,11 +116,12 @@ protected: 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; typedefImm=op.typedefImm; } + Datatype(const Datatype &op) { size = op.size; name=op.name; metatype=op.metatype; submeta=op.submeta; 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; typedefImm=(Datatype *)0; } + Datatype(int4 s,type_metatype m) { size=s; metatype=m; submeta=base2sub[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; typedefImm=(Datatype *)0; } + Datatype(int4 s,type_metatype m,const string &n) { name=n; size=s; metatype=m; submeta=base2sub[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' @@ -186,11 +209,12 @@ public: class TypeChar : public TypeBase { protected: friend class TypeFactory; + virtual void restoreXml(const Element *el,TypeFactory &typegrp); public: /// Construct TypeChar copying properties from another data-type TypeChar(const TypeChar &op) : TypeBase(op) { flags |= Datatype::chartype; } /// Construct a char (always 1-byte) given a name - TypeChar(const string &n) : TypeBase(1,TYPE_INT,n) { flags |= Datatype::chartype; } + TypeChar(const string &n) : TypeBase(1,TYPE_INT,n) { flags |= Datatype::chartype; submeta = SUB_INT_CHAR; } virtual Datatype *clone(void) const { return new TypeChar(*this); } virtual void saveXml(ostream &s) const; }; @@ -298,9 +322,11 @@ public: /// Construct from another TypeEnum TypeEnum(const TypeEnum &op); /// Construct from a size and meta-type (TYPE_INT or TYPE_UINT) - TypeEnum(int4 s,type_metatype m) : TypeBase(s,m) { flags |= enumtype; } + TypeEnum(int4 s,type_metatype m) : TypeBase(s,m) { + flags |= enumtype; submeta = (m==TYPE_INT) ? SUB_INT_ENUM : SUB_UINT_ENUM; } /// Construct from a size, meta-type, and name - TypeEnum(int4 s,type_metatype m,const string &nm) : TypeBase(s,m,nm) { flags |= enumtype; } + TypeEnum(int4 s,type_metatype m,const string &nm) : TypeBase(s,m,nm) { + flags |= enumtype; submeta = (m==TYPE_INT) ? SUB_INT_ENUM : SUB_UINT_ENUM; } map::const_iterator beginEnum(void) const { return namemap.begin(); } ///< Beginning of name map map::const_iterator endEnum(void) const { return namemap.end(); } ///< End of name map bool getMatches(uintb val,vector &matchname) const; ///< Recover the named representation diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc index 133d993103..104b5d2338 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/typeop.cc @@ -1714,6 +1714,8 @@ Datatype *TypeOpPtrsub::getOutputToken(const PcodeOp *op,CastStrategy *castStrat Datatype *rettype = ptype->downChain(offset,false,*tlst); if ((offset==0)&&(rettype != (Datatype *)0)) return rettype; + rettype = tlst->getBase(1, TYPE_UNKNOWN); + return tlst->getTypePointer(op->getOut()->getSize(), rettype, ptype->getWordSize()); } return TypeOp::getOutputToken(op,castStrategy); }