mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Refactor TypeStruct and TypeCode restoration
This commit is contained in:
parent
c53334038d
commit
e4451fcd49
10 changed files with 204 additions and 145 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
{
|
||||
|
|
|
@ -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,7 +1362,7 @@ 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,
|
||||
void TypeCode::setPrototype(TypeFactory *tfact,ProtoModel *model,
|
||||
Datatype *outtype,const vector<Datatype *> &intypes,
|
||||
bool dotdotdot,Datatype *voidtype)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
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);
|
||||
proto->setConstructor(isConstructor);
|
||||
proto->setDestructor(isDestructor);
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -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,
|
||||
void setPrototype(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 *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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue