Refactor TypeStruct and TypeCode restoration

This commit is contained in:
caheckman 2021-11-16 12:14:34 -05:00
parent c53334038d
commit e4451fcd49
10 changed files with 204 additions and 145 deletions

View file

@ -78,7 +78,6 @@ private:
bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); }
public:
ParamEntry(int4 grp) { group=grp; } ///< Constructor for use with restoreXml
ParamEntry(type_metatype t,int4 grp,int4 grpsize,const Address &loc,int4 sz,int4 mnsz,int4 align,bool normalstack);
int4 getGroup(void) const { return group; } ///< Get the group id \b this belongs to
int4 getGroupSize(void) const { return groupsize; } ///< Get the number of groups occupied by \b this
int4 getSize(void) const { return size; } ///< Get the size of the memory range in bytes.

View file

@ -3212,7 +3212,7 @@ void IfcLoadTestFile::execute(istream &s)
*status->optr << filename << " test successfully loaded: " << dcp->conf->getDescription() << endl;
}
/// \class IfaceListTestCommands
/// \class IfcListTestCommands
/// \brief List all the script commands in the current test: `list test commands`
void IfcListTestCommands::execute(istream &s)
@ -3224,7 +3224,7 @@ void IfcListTestCommands::execute(istream &s)
}
}
/// \class IfcExecuteTestCommands
/// \class IfcExecuteTestCommand
/// \brief Execute a specified range of the test script: `execute test command <#>-<#>
void IfcExecuteTestCommand::execute(istream &s)

View file

@ -46,10 +46,6 @@ public:
CallGraph *cgraph; ///< Call-graph information for the program
FunctionTestCollection *testCollection; ///< Executable environment from a datatest
map<Funcdata*,PrototypePieces> prototypePieces;
void storePrototypePieces( Funcdata *fd_in, PrototypePieces pp_in ) { prototypePieces.insert(pair<Funcdata*,PrototypePieces>(fd_in,pp_in)); }
PrototypePieces findPrototypePieces( Funcdata *fd_in ) { return (*prototypePieces.find(fd_in)).second; }
#ifdef CPUI_RULECOMPILE
string experimental_file; // File containing experimental rules
#endif

View file

@ -106,7 +106,7 @@ public:
warning = 8, ///< Warning has been generated for this op
incidental_copy = 0x10, ///< Treat this as \e incidental for parameter recovery algorithms
is_cpool_transformed = 0x20, ///< Have we checked for cpool transforms
stop_propagation = 40 ///< Stop propagation into output from descendants
stop_propagation = 0x40 ///< Stop propagation into output from descendants
};
private:
TypeOp *opcode; ///< Pointer to class providing behavioral details of the operation

View file

@ -1591,7 +1591,7 @@ void PrintC::pushConstant(uintb val,const Datatype *ct,
clear();
throw LowlevelError("Cannot have a constant of type void");
case TYPE_PTR:
case TYPE_PTRSTRUCT:
case TYPE_PTRREL:
if (option_NULL&&(val==0)) { // A null pointer
pushAtom(Atom(nullToken,vartoken,EmitXml::var_color,op,vn));
return;

View file

@ -1859,7 +1859,7 @@ int4 RuleDoubleShift::applyOp(PcodeOp *op,Funcdata &data)
}
/// \class RuleDoubleArithShift
/// \brief Simplify two sequential INT_SRIGHT: `(x s>> #c) s>> #d => x s>> saturate(#c + #d)`
/// \brief Simplify two sequential INT_SRIGHT: `(x s>> c) s>> d => x s>> saturate(c + d)`
///
/// Division optimization in particular can produce a sequence of signed right shifts.
/// The shift amounts add up to the point where the sign bit has saturated the entire result.
@ -5300,8 +5300,8 @@ Varnode *RuleSLess2Zero::getHiBit(PcodeOp *op)
/// Forms include:
/// - `0 s< V * -1 => V s< 0`
/// - `V * -1 s< 0 => 0 s< V`
/// - `-1 s< SUB(V,#hi) => -1 s< V`
/// - `SUB(V,#hi) s< 0 => V s< 0`
/// - `-1 s< SUB(V,hi) => -1 s< V`
/// - `SUB(V,hi) s< 0 => V s< 0`
/// - `-1 s< ~V => V s< 0`
/// - `~V s< 0 => -1 s< V`
/// - `(V & 0xf000) s< 0 => V s< 0`
@ -7171,9 +7171,9 @@ int4 RuleDivTermAdd2::applyOp(PcodeOp *op,Funcdata &data)
/// \brief Check for INT_(S)RIGHT and/or SUBPIECE followed by INT_MULT
///
/// Look for the forms:
/// - `sub(ext(X) * #y,#c)` or
/// - `sub(ext(X) * #y,#c) >> n` or
/// - `(ext(X) * #y) >> n`
/// - `sub(ext(X) * y,c)` or
/// - `sub(ext(X) * y,c) >> n` or
/// - `(ext(X) * y) >> n`
///
/// Looks for truncation/multiplication consistent with an optimized division. The
/// truncation can come as either a SUBPIECE operation and/or right shifts.

View file

@ -1512,7 +1512,6 @@ bool ConsistencyChecker::testSizeRestrictions(void)
/// Update truncated Varnodes given complete size information. Print errors
/// for any invalid truncation constructions.
/// \param isbigendian is \b true if the SLEIGH spec is big endian
/// \return \b true if there are no invalid truncations
bool ConsistencyChecker::testTruncations(void)

View file

@ -997,6 +997,7 @@ bool SubvariableFlow::createCompareBridge(PcodeOp *op,ReplaceVarnode *inrvn,int4
/// \param mask is the set of bits holding the logical value (within a bigger value)
/// \param slot is the input slot to the operation
/// \param constvn is the original constant
/// \return the new constant variable node
SubvariableFlow::ReplaceVarnode *SubvariableFlow::addConstant(ReplaceOp *rop,uintb mask,
uint4 slot,Varnode *constvn)
{
@ -1018,6 +1019,13 @@ SubvariableFlow::ReplaceVarnode *SubvariableFlow::addConstant(ReplaceOp *rop,uin
return res;
}
/// \brief Add a new constant variable node as an input to a logical operation.
///
/// The constant is new and isn't associated with a constant in the original graph.
/// \param rop is the logical operation taking the constant as input
/// \param slot is the input slot to the operation
/// \param val is the constant value
/// \return the new constant variable node
SubvariableFlow::ReplaceVarnode *SubvariableFlow::addNewConstant(ReplaceOp *rop,uint4 slot,uintb val)
{

View file

@ -16,6 +16,8 @@
#include "type.hh"
#include "funcdata.hh"
/// The base propagation ordering associated with each meta-type.
/// The array elements correspond to the ordering of #type_metatype.
sub_metatype Datatype::base2sub[13] = {
SUB_STRUCT, SUB_PARTIALSTRUCT, SUB_ARRAY, SUB_PTRREL, SUB_PTR, SUB_FLOAT, SUB_CODE, SUB_BOOL,
SUB_UINT_PLAIN, SUB_INT_PLAIN, SUB_UNKNOWN, SUB_SPACEBASE, SUB_VOID
@ -176,8 +178,8 @@ void metatype2string(type_metatype metatype,string &res)
case TYPE_PTR:
res = "ptr";
break;
case TYPE_PTRSTRUCT:
res = "ptrstruct";
case TYPE_PTRREL:
res = "ptrrel";
break;
case TYPE_ARRAY:
res = "array";
@ -226,8 +228,8 @@ type_metatype string2metatype(const string &metastring)
return TYPE_PTR;
else if (metastring=="part")
return TYPE_PARTIALSTRUCT;
else if (metastring=="ptrstruct")
return TYPE_PTRSTRUCT;
else if (metastring=="ptrrel")
return TYPE_PTRREL;
break;
case 'a':
if (metastring=="array")
@ -412,15 +414,6 @@ void Datatype::restoreXmlBasic(const Element *el)
}
}
/// Restore a Datatype object from an XML element
/// \param el is the XML element
/// \param typegrp is the underlying TypeFactory that will hold the new object
void Datatype::restoreXml(const Element *el,TypeFactory &typegrp)
{
restoreXmlBasic(el);
}
/// If a type id is explicitly provided for a data-type, this routine is used
/// to produce an id based on a hash of the name. IDs produced this way will
/// have their sign-bit set to distinguish it from other IDs.
@ -456,6 +449,9 @@ uint8 Datatype::hashSize(uint8 id,int4 size)
return id;
}
/// Parse a \<type> tag for attributes of the character data-type
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypeChar::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -489,6 +485,9 @@ void TypeUnicode::setflags(void)
flags |= Datatype::chartype; // This ultimately should be UTF8 but we default to basic char
}
/// Parse a \<type> tag for properties of the data-type
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypeUnicode::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -577,6 +576,9 @@ void TypePointer::saveXml(ostream &s) const
s << "</type>";
}
/// Parse a \<type> tag with a child describing the data-type being pointed to
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypePointer::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -598,7 +600,7 @@ void TypePointer::calcSubmeta(void)
{
if (ptrto->getMetatype() == TYPE_STRUCT) {
if (ptrto->numDepend() > 1 || ptrto->isIncompleteStruct())
if (ptrto->numDepend() > 1 || ptrto->isIncomplete())
submeta = SUB_PTR_STRUCT;
else
submeta = SUB_PTR;
@ -745,6 +747,9 @@ void TypeArray::saveXml(ostream &s) const
s << "</type>";
}
/// Parse a \<type> tag with a child describing the array element data-type.
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypeArray::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -925,6 +930,9 @@ void TypeEnum::saveXml(ostream &s) const
s << "</type>";
}
/// Parse a \<type> tag with children describing each specific enumeration value.
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypeEnum::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -1198,10 +1206,12 @@ void TypeStruct::saveXml(ostream &s) const
s << "</type>";
}
void TypeStruct::restoreXml(const Element *el,TypeFactory &typegrp)
/// Children of the structure element describe each field.
/// \param el is the root structure element
/// \param typegrp is the factory owning the new structure
void TypeStruct::restoreFields(const Element *el,TypeFactory &typegrp)
{
restoreXmlBasic(el);
const List &list(el->getChildren());
List::const_iterator iter;
int4 maxoffset = 0;
@ -1224,11 +1234,14 @@ void TypeStruct::restoreXml(const Element *el,TypeFactory &typegrp)
if (maxoffset > size)
throw LowlevelError("Size too small for fields of structure "+name);
if (size == 0) // We can restore an incomplete structure, indicated by 0 size
flags |= struct_incomplete;
flags |= type_incomplete;
else
flags &= ~(uint4)struct_incomplete; // Otherwise the structure is complete
markComplete(); // Otherwise the structure is complete
}
/// Parse a \<type> tag with children describing the data-type being pointed to and the parent data-type.
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypePointerRel::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -1284,7 +1297,7 @@ void TypePointerRel::saveXml(ostream &s) const
{
s << "<type";
saveXmlBasic(TYPE_PTRSTRUCT,s); // Override the metatype for XML
saveXmlBasic(TYPE_PTRREL,s); // Override the metatype for XML
if (wordsize != 1)
a_v_i(s,"wordsize",wordsize);
s << ">\n";
@ -1349,9 +1362,9 @@ Datatype *TypePointerRel::getPtrTo(Datatype *base,int4 off,TypeFactory &typegrp)
/// \param intypes is the list of input parameters
/// \param dotdotdot is true if the prototype takes variable arguments
/// \param voidtype is the reference "void" data-type
void TypeCode::set(TypeFactory *tfact,ProtoModel *model,
Datatype *outtype,const vector<Datatype *> &intypes,
bool dotdotdot,Datatype *voidtype)
void TypeCode::setPrototype(TypeFactory *tfact,ProtoModel *model,
Datatype *outtype,const vector<Datatype *> &intypes,
bool dotdotdot,Datatype *voidtype)
{
factory = tfact;
flags |= variable_length;
@ -1373,6 +1386,24 @@ void TypeCode::set(TypeFactory *tfact,ProtoModel *model,
proto->setOutputLock(true);
}
/// The prototype is copied in.
/// \param typegrp is the factory owning \b this
/// \param fp is the prototype to set (may be null)
void TypeCode::setPrototype(TypeFactory *typegrp,const FuncProto *fp)
{
if (proto != (FuncProto *)0) {
delete proto;
proto = (FuncProto *)0;
factory = (TypeFactory *)0;
}
if (fp != (const FuncProto *)0) {
factory = typegrp;
proto = new FuncProto();
proto->copy(*fp);
}
}
TypeCode::TypeCode(const TypeCode &op) : Datatype(op)
{
@ -1384,11 +1415,12 @@ TypeCode::TypeCode(const TypeCode &op) : Datatype(op)
}
}
TypeCode::TypeCode(const string &nm) : Datatype(1,TYPE_CODE,nm)
TypeCode::TypeCode(void) : Datatype(1,TYPE_CODE)
{
proto = (FuncProto *)0;
factory = (TypeFactory *)0;
flags |= type_incomplete;
}
TypeCode::~TypeCode(void)
@ -1408,17 +1440,6 @@ void TypeCode::printRaw(ostream &s) const
s << "()";
}
/// Assuming \b this has an underlying function prototype, set some of its boolean properties
/// \param isConstructor toggles whether the function is a constructor
/// \param isDestructor toggles whether the function is a destructor
void TypeCode::setProperties(bool isConstructor,bool isDestructor)
{
proto->setConstructor(isConstructor);
proto->setDestructor(isDestructor);
}
/// Compare basic characteristics of \b this with another TypeCode, not including the prototype
/// - -1 or 1 if -this- and -op- are different in surface characteristics
/// - 0 if they are exactly equal and have no parameters
@ -1540,27 +1561,38 @@ void TypeCode::saveXml(ostream &s) const
s << "</type>";
}
void TypeCode::restoreXml(const Element *el,TypeFactory &typegrp)
/// \param el is the root XML element describing the code object
void TypeCode::restoreStub(const Element *el)
{
if (!el->getChildren().empty()) {
// Traditionally a <prototype> tag implies variable length, without a "varlength" attribute
flags |= variable_length;
}
restoreXmlBasic(el);
}
/// A single child element indicates a full function prototype.
/// \param el is the root XML tag describing the code object
/// \param isConstructor is \b true if the prototype is a constructor
/// \param isDestructor is \b true if the prototype is a destructor
/// \param typegrp is the factory owning the code object
void TypeCode::restorePrototype(const Element *el,bool isConstructor,bool isDestructor,TypeFactory &typegrp)
{
const List &list(el->getChildren());
List::const_iterator iter;
iter = list.begin();
if (iter != list.end()) {
// Traditionally a <prototype> tag implies variable length, without a "varlength" attribute
flags |= variable_length;
Architecture *glb = typegrp.getArch();
factory = &typegrp;
proto = new FuncProto();
proto->setInternal( glb->defaultfp, typegrp.getTypeVoid() );
proto->restoreXml(*iter,glb);
proto->setConstructor(isConstructor);
proto->setDestructor(isDestructor);
}
restoreXmlBasic(el);
if (proto != (FuncProto *)0) {
delete proto;
proto = (FuncProto *)0;
}
if (iter == list.end()) return; // No underlying prototype
Architecture *glb = typegrp.getArch();
factory = &typegrp;
proto = new FuncProto();
proto->setInternal( glb->defaultfp, typegrp.getTypeVoid() );
proto->restoreXml(*iter,glb);
markComplete();
}
/// This data-type can index either a local or the global scope
@ -1718,6 +1750,9 @@ void TypeSpacebase::saveXml(ostream &s) const
s << "</type>";
}
/// Parse the \<type> tag.
/// \param el is the root XML element
/// \param typegrp is the factory owning \b this data-type
void TypeSpacebase::restoreXml(const Element *el,TypeFactory &typegrp)
{
@ -2036,7 +2071,7 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,
{
int4 offset,cursize,curalign;
if (!ot->isIncompleteStruct())
if (!ot->isIncomplete())
throw LowlevelError("Can only set fields on an incomplete structure");
offset = 0;
vector<TypeField>::iterator iter;
@ -2078,8 +2113,8 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,
tree.erase(ot);
ot->setFields(fd);
ot->flags &= ~(uint4)Datatype::struct_incomplete;
ot->flags |= (flags & (Datatype::opaque_string | Datatype::variable_length | Datatype::struct_incomplete));
ot->flags &= ~(uint4)Datatype::type_incomplete;
ot->flags |= (flags & (Datatype::opaque_string | Datatype::variable_length | Datatype::type_incomplete));
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
@ -2092,6 +2127,23 @@ bool TypeFactory::setFields(vector<TypeField> &fd,TypeStruct *ot,int4 fixedsize,
return true;
}
/// The given prototype is copied into the given code data-type
/// This method should only be used on an incomplete TypeCode. It will mark the TypeCode as complete.
/// \param fp is the given prototype to copy
/// \param newCode is the given code data-type
/// \param flags are additional flags to transfer into the code data-type
void TypeFactory::setPrototype(const FuncProto *fp,TypeCode *newCode,uint4 flags)
{
if (!newCode->isIncomplete())
throw LowlevelError("Can only set prototype on incomplete data-type");
tree.erase(newCode);
newCode->setPrototype(this,fp);
newCode->flags &= ~(uint4)Datatype::type_incomplete;
newCode->flags |= (flags & (Datatype::variable_length | Datatype::type_incomplete));
tree.insert(newCode);
}
/// Set the list of enumeration values and identifiers for a TypeEnum
/// Fill in any values for any names that weren't explicitly assigned
/// and check for duplicates.
@ -2284,7 +2336,8 @@ TypeCode *TypeFactory::getTypeCode(void)
Datatype *ct = typecache[1][TYPE_CODE-TYPE_FLOAT];
if (ct != (Datatype *)0)
return (TypeCode *)ct;
TypeCode tmp("");
TypeCode tmp; // A generic code object
tmp.markComplete(); // which is considered complete
return (TypeCode *) findAdd(tmp);
}
@ -2296,8 +2349,10 @@ TypeCode *TypeFactory::getTypeCode(const string &nm)
{
if (nm.size()==0) return getTypeCode();
TypeCode tmp(nm);
TypeCode tmp; // Generic code data-type
tmp.name = nm; // with a name
tmp.id = Datatype::hashName(nm);
tmp.markComplete(); // considered complete
return (TypeCode *) findAdd(tmp);
}
@ -2445,7 +2500,8 @@ TypeStruct *TypeFactory::getTypeStruct(const string &n)
{
// We should probably strip offsets here
// But I am currently choosing not to
TypeStruct tmp(n);
TypeStruct tmp;
tmp.name = n;
tmp.id = Datatype::hashName(n);
return (TypeStruct *) findAdd(tmp);
}
@ -2483,8 +2539,9 @@ TypeCode *TypeFactory::getTypeCode(ProtoModel *model,Datatype *outtype,
const vector<Datatype *> &intypes,
bool dotdotdot)
{
TypeCode tc(""); // getFuncdata type with no name
tc.set(this,model,outtype,intypes,dotdotdot,getTypeVoid());
TypeCode tc; // getFuncdata type with no name
tc.setPrototype(this,model,outtype,intypes,dotdotdot,getTypeVoid());
tc.markComplete();
return (TypeCode *) findAdd(tc);
}
@ -2609,10 +2666,7 @@ Datatype *TypeFactory::restoreXmlTypeWithCodeFlags(const Element *el,bool isCons
const Element *subel = *iter;
if (subel->getAttributeValue("metatype") != "code")
throw LowlevelError("Special type restoreXml does not see code");
TypeCode tc("");
tc.restoreXml(subel,*this);
tc.setProperties(isConstructor,isDestructor); // Add in flags
tp.ptrto = findAdd(tc); // THEN add to container
tp.ptrto = restoreCode(subel, isConstructor, isDestructor, false);
return findAdd(tp);
}
@ -2701,49 +2755,27 @@ Datatype *TypeFactory::restoreTypedef(const Element *el)
return getTypedef(defedType, nm, id);
}
/// If necessary create a stub object before parsing the field descriptions, to deal with recursive definitions
/// \param el is the XML element describing the structure
/// \param forcecore is \b true if the data-type is considered core
/// \return the newly minted structure data-type
Datatype* TypeFactory::restoreStruct(const Element *el,bool forcecore)
{
string structname = el->getAttributeValue("name");
TypeStruct ts(structname);
int4 num = el->getNumAttributes();
uint8 newid = 0;
int4 structsize = 0;
bool isVarLength = false;
for(int4 i = 0;i < num;++i) {
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 (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);
Datatype *ct = findByIdLocal(structname,newid);
TypeStruct ts;
ts.restoreXmlBasic(el);
if (forcecore)
ts.flags |= Datatype::coretype;
Datatype *ct = findByIdLocal(ts.name,ts.id);
if (ct == (Datatype*)0) {
ts.id = newid;
ts.size = structsize; // Include size if we have it, so arrays can be defined without knowing struct fields
ct = findAdd(ts); // Create stub to allow recursive definitions
}
else if (ct->getMetatype() != TYPE_STRUCT)
throw LowlevelError("Trying to redefine type: " + structname);
ts.restoreXml(el,*this);
if (forcecore)
ts.flags |= Datatype::coretype;
if (!ct->isIncompleteStruct()) { // Structure of this name was already present
throw LowlevelError("Trying to redefine type: " + ts.name);
ts.restoreFields(el,*this);
if (!ct->isIncomplete()) { // Structure of this name was already present
if (0 != ct->compareDependency(ts))
throw LowlevelError("Redefinition of structure: " + structname);
throw LowlevelError("Redefinition of structure: " + ts.name);
}
else { // If structure is a placeholder stub
if (!setFields(ts.field,(TypeStruct*)ct,ts.size,ts.flags)) // Define structure now by copying fields
@ -2752,6 +2784,36 @@ Datatype* TypeFactory::restoreStruct(const Element *el,bool forcecore)
return ct;
}
/// If necessary create a stub object before parsing the prototype description, to deal with recursive definitions
/// \param el is the XML element describing the code object
/// \param isConstructor is \b true if any prototype should be treated as a constructor
/// \param isDestructor is \b true if any prototype should be treated as a destructor
/// \param forcecore is \b true if the data-type is considered core
/// \return the newly minted code data-type
Datatype *TypeFactory::restoreCode(const Element *el,bool isConstructor,bool isDestructor,bool forcecore)
{
TypeCode tc;
tc.restoreStub(el);
if (forcecore)
tc.flags |= Datatype::coretype;
Datatype *ct = findByIdLocal(tc.name,tc.id);
if (ct == (Datatype *)0) {
ct = findAdd(tc); // Create stub to allow recursive definitions
}
else if (ct->getMetatype() != TYPE_CODE)
throw LowlevelError("Trying to redefine type: " + tc.name);
tc.restorePrototype(el, isConstructor, isDestructor, *this);
if (!ct->isIncomplete()) { // Code data-type of this name was already present
if (0 != ct->compareDependency(tc))
throw LowlevelError("Redefinition of code data-type: " + tc.name);
}
else { // If there was a placeholder stub
setPrototype(tc.proto, (TypeCode *)ct, tc.flags);
}
return ct;
}
/// 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
@ -2804,13 +2866,7 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
}
break;
case TYPE_CODE:
{
TypeCode tc("");
tc.restoreXml(el,*this);
if (forcecore)
tc.flags |= Datatype::coretype;
ct = findAdd(tc);
}
ct = restoreCode(el,false, false, forcecore);
break;
default:
for(int4 i=0;i<el->getNumAttributes();++i) {
@ -2844,7 +2900,7 @@ Datatype *TypeFactory::restoreXmlTypeNoRef(const Element *el,bool forcecore)
}
{
TypeBase tb(0,TYPE_UNKNOWN);
tb.restoreXml(el,*this);
tb.restoreXmlBasic(el);
if (forcecore)
tb.flags |= Datatype::coretype;
ct = findAdd(tb);

View file

@ -27,9 +27,7 @@ extern void print_data(ostream &s,uint1 *buffer,int4 size,const Address &baseadd
//extern bool print_string(ostream &s,uint1 *buffer,int4 size);
/// The core meta-types supported by the decompiler. These are sizeless templates
/// for the elements making up the type algebra. Ordering is important: The lower
/// the number, the more \b specific the type, in calculations involving the generality
/// of a type.
/// for the elements making up the type algebra.
enum type_metatype {
TYPE_VOID = 12, ///< Standard "void" type, absence of type
TYPE_SPACEBASE = 11, ///< Placeholder for symbol/type look-up calculations
@ -41,12 +39,14 @@ enum type_metatype {
TYPE_FLOAT = 5, ///< Floating-point
TYPE_PTR = 4, ///< Pointer data-type
TYPE_PTRSTRUCT = 3, ///< Pointer into a structure data-type (specialization of TYPE_PTR)
TYPE_PTRREL = 3, ///< Pointer relative to another data-type (specialization of TYPE_PTR)
TYPE_ARRAY = 2, ///< Array data-type, made up of a sequence of "element" datatype
TYPE_PARTIALSTRUCT = 1, ///< Part of a structure, stored separately from the whole
TYPE_STRUCT = 0 ///< Structure data-type, made up of component datatypes
};
/// Specializations of the core meta-types. Each enumeration is associated with a specific #type_metatype.
/// Ordering is important: The lower the number, the more \b specific the data-type, affecting propagation.
enum sub_metatype {
SUB_VOID = 20, ///< Compare as a TYPE_VOID
SUB_SPACEBASE = 19, ///< Compare as a TYPE_SPACEBASE
@ -104,7 +104,7 @@ protected:
variable_length = 128, ///< May be other structures with same name different lengths
has_stripped = 0x100, ///< Datatype has a stripped form for formal declarations
is_ptrrel = 0x200, ///< Datatype is a TypePointerRel
struct_incomplete = 0x400, ///< Set if \b this (recursive) structure has not been fully defined yet
type_incomplete = 0x400, ///< Set if \b this (recursive) data-type has not been fully defined yet
};
friend class TypeFactory;
friend struct DatatypeCompare;
@ -118,7 +118,7 @@ protected:
void restoreXmlBasic(const Element *el); ///< Recover basic data-type properties
void saveXmlBasic(type_metatype meta,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
void markComplete(void) { flags &= ~(uint4)type_incomplete; } ///< Mark \b this data-type as completely defined
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
@ -128,8 +128,6 @@ public:
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; 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; 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'
@ -144,7 +142,7 @@ public:
bool isPointerRel(void) const { return ((flags & is_ptrrel)!=0); } ///< Is \b this a TypePointerRel
bool isFormalPointerRel(void) const { return (flags & (is_ptrrel | has_stripped))==is_ptrrel; } ///< Is \b this a non-ephemeral TypePointerRel
bool hasStripped(void) const { return (flags & has_stripped)!=0; } ///< Return \b true if \b this has a stripped form
bool isIncompleteStruct(void) const { return (flags & struct_incomplete)!=0; } ///< Is \b this an incompletely defined struct
bool isIncomplete(void) const { return (flags & type_incomplete)!=0; } ///< Is \b this an incompletely defined data-type
uint4 getInheritable(void) const { return (flags & coretype); } ///< Get properties pointers inherit
type_metatype getMetatype(void) const { return metatype; } ///< Get the type \b meta-type
sub_metatype getSubMeta(void) const { return submeta; } ///< Get the \b sub-metatype
@ -213,7 +211,7 @@ public:
/// Construct TypeBase from a size and meta-type
TypeBase(int4 s,type_metatype m) : Datatype(s,m) {}
/// Construct TypeBase from a size, meta-type, and name
TypeBase(int4 s,type_metatype m,const string &n) : Datatype(s,m,n) {}
TypeBase(int4 s,type_metatype m,const string &n) : Datatype(s,m) { name = n; }
virtual Datatype *clone(void) const { return new TypeBase(*this); }
};
@ -223,7 +221,7 @@ public:
class TypeChar : public TypeBase {
protected:
friend class TypeFactory;
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this char data-type from an XML element
public:
/// Construct TypeChar copying properties from another data-type
TypeChar(const TypeChar &op) : TypeBase(op) { flags |= Datatype::chartype; }
@ -240,7 +238,7 @@ class TypeUnicode : public TypeBase { // Unicode character type
void setflags(void); ///< Set unicode property flags
protected:
friend class TypeFactory;
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this unicode data-type from an XML element
public:
TypeUnicode(void) : TypeBase(0,TYPE_INT) {} ///< For use with restoreXml
TypeUnicode(const TypeUnicode &op) : TypeBase(op) {} ///< Construct from another TypeUnicode
@ -260,7 +258,7 @@ public:
/// Construct from another TypeVoid
TypeVoid(const TypeVoid &op) : Datatype(op) { flags |= Datatype::coretype; }
/// Constructor
TypeVoid(void) : Datatype(0,TYPE_VOID,"void") { flags |= Datatype::coretype; }
TypeVoid(void) : Datatype(0,TYPE_VOID) { name = "void"; flags |= Datatype::coretype; }
virtual Datatype *clone(void) const { return new TypeVoid(*this); }
virtual void saveXml(ostream &s) const;
};
@ -271,7 +269,7 @@ protected:
friend class TypeFactory;
Datatype *ptrto; ///< Type being pointed to
uint4 wordsize; ///< What size unit does the pointer address
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this pointer data-type from an XML element
void calcSubmeta(void); ///< Calculate specific submeta for \b this pointer
/// Internal constructor for use with restoreXml
TypePointer(void) : Datatype(0,TYPE_PTR) { ptrto = (Datatype *)0; wordsize=1; }
@ -301,7 +299,7 @@ protected:
friend class TypeFactory;
Datatype *arrayof; ///< type of which we have an array
int4 arraysize; ///< Number of elements in the array
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this array from an XML element
/// Internal constructor for restoreXml
TypeArray(void) : Datatype(0,TYPE_ARRAY) { arraysize = 0; arrayof = (Datatype *)0; }
public:
@ -334,7 +332,7 @@ protected:
map<uintb,string> namemap; ///< Map from integer to name
vector<uintb> masklist; ///< Masks for each bitfield within the enum
void setNameMap(const map<uintb,string> &nmap); ///< Establish the value -> name map
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this enum data-type from an XML element
public:
/// Construct from another TypeEnum
TypeEnum(const TypeEnum &op);
@ -361,10 +359,10 @@ protected:
void setFields(const vector<TypeField> &fd); ///< Establish fields for \b this
int4 getFieldIter(int4 off) const; ///< Get index into field list
int4 getLowerBoundField(int4 off) const; ///< Get index of last field before or equal to given offset
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreFields(const Element *el,TypeFactory &typegrp); ///< Restore fields from XML description
public:
TypeStruct(const TypeStruct &op); ///< Construct from another TypeStruct
TypeStruct(const string &n) : Datatype(0,TYPE_STRUCT,n) { flags |= struct_incomplete; } ///< Construct incomplete/empty TypeStruct from a name
TypeStruct(void) : Datatype(0,TYPE_STRUCT) { flags |= type_incomplete; } ///< Construct incomplete/empty TypeStruct
vector<TypeField>::const_iterator beginField(void) const { return field.begin(); } ///< Beginning of fields
vector<TypeField>::const_iterator endField(void) const { return field.end(); } ///< End of fields
const TypeField *getField(int4 off,int4 sz,int4 *newoff) const; ///< Get field based on offset
@ -391,7 +389,7 @@ protected:
Datatype *parent; ///< Parent structure or array which \b this is pointing into
int4 offset; ///< Byte offset within the parent where \b this points to
void cacheStrippedType(TypeFactory &typegrp);
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this relative pointer data-type from an XML element
/// Internal constructor for restoreXml
TypePointerRel(void) : TypePointer() { offset = 0; parent = (Datatype *)0; stripped = (TypePointer *)0; submeta = SUB_PTRREL; }
public:
@ -429,16 +427,17 @@ protected:
friend class TypeFactory;
FuncProto *proto; ///< If non-null, this describes the prototype of the underlying function
TypeFactory *factory; ///< Factory owning \b this
void set(TypeFactory *tfact,ProtoModel *model,
Datatype *outtype,const vector<Datatype *> &intypes,
bool dotdotdot,Datatype *voidtype); ///< Establish a function pointer
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void setPrototype(TypeFactory *tfact,ProtoModel *model,
Datatype *outtype,const vector<Datatype *> &intypes,
bool dotdotdot,Datatype *voidtype); ///< Establish a function pointer
void setPrototype(TypeFactory *typegrp,const FuncProto *fp); ///< Set a particular function prototype on \b this
void restoreStub(const Element *el); ///< Restore stub of data-type without the full prototype
void restorePrototype(const Element *el,bool isConstructor,bool isDestructor,TypeFactory &typegrp); ///< Restore any prototype description
public:
TypeCode(const TypeCode &op); ///< Construct from another TypeCode
TypeCode(const string &nm); ///< Construct from a name
TypeCode(void); ///< Construct an incomplete TypeCode
int4 compareBasic(const TypeCode *op) const; ///< Compare surface characteristics of two TypeCodes
const FuncProto *getPrototype(void) const { return proto; } ///< Get the function prototype
void setProperties(bool isConstructor,bool isDestructor); ///< Set additional function properties
virtual ~TypeCode(void);
virtual void printRaw(ostream &s) const;
virtual Datatype *getSubType(uintb off,uintb *newoff) const;
@ -458,7 +457,7 @@ class TypeSpacebase : public Datatype {
AddrSpace *spaceid; ///< The address space we are treating as a structure
Address localframe; ///< Address of function whose symbol table is indexed (or INVALID for "global")
Architecture *glb; ///< Architecture for accessing symbol table
virtual void restoreXml(const Element *el,TypeFactory &typegrp);
void restoreXml(const Element *el,TypeFactory &typegrp); ///< Restore \b this spacebase data-type from an XML element
public:
/// Construct from another TypeSpacebase
TypeSpacebase(const TypeSpacebase &op) : Datatype(op) {
@ -496,6 +495,7 @@ class TypeFactory {
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 *restoreStruct(const Element *el,bool forcecore); ///< Restore a \<type> XML tag describing a structure
Datatype *restoreCode(const Element *el,bool isConstructor,bool isDestructor,bool forcecore); ///< Restore XML tag describing a code object
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
@ -519,6 +519,7 @@ public:
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<TypeField> &fd,TypeStruct *ot,int4 fixedsize,uint4 flags); ///< Set fields on a TypeStruct
void setPrototype(const FuncProto *fp,TypeCode *newCode,uint4 flags); ///< Set the prototype on a TypeCode
bool setEnumValues(const vector<string> &namelist,
const vector<uintb> &vallist,
const vector<bool> &assignlist,