mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Breaking out ParamListRegisterOut
This commit is contained in:
parent
f235e46adc
commit
a00de6cbac
7 changed files with 224 additions and 146 deletions
|
@ -583,49 +583,35 @@ Address ParamListStandard::assignAddress(const Datatype *tp,vector<int4> &status
|
||||||
return Address(); // Return invalid address to indicated we could not assign anything
|
return Address(); // Return invalid address to indicated we could not assign anything
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParamListStandard::assignMap(const vector<Datatype *> &proto,bool isinput,TypeFactory &typefactory,
|
void ParamListStandard::assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
||||||
vector<ParameterPieces> &res) const
|
|
||||||
|
|
||||||
{
|
{
|
||||||
vector<int4> status(numgroup,0);
|
vector<int4> status(numgroup,0);
|
||||||
|
|
||||||
if (isinput) {
|
if (res.size() == 2) { // Check for hidden parameters defined by the output list
|
||||||
if (res.size()==2) { // Check for hidden parameters defined by the output list
|
res.back().addr = assignAddress(res.back().type,status); // Reserve first param for hidden ret value
|
||||||
res.back().addr = assignAddress(res.back().type,status); // Reserve first param for hidden ret value
|
res.back().flags |= ParameterPieces::hiddenretparm;
|
||||||
res.back().flags |= ParameterPieces::hiddenretparm;
|
if (res.back().addr.isInvalid())
|
||||||
if (res.back().addr.isInvalid())
|
throw ParamUnassignedError("Cannot assign parameter address for " + res.back().type->getName());
|
||||||
throw ParamUnassignedError("Cannot assign parameter address for " + res.back().type->getName());
|
|
||||||
}
|
|
||||||
for(int4 i=1;i<proto.size();++i) {
|
|
||||||
res.emplace_back();
|
|
||||||
if ((pointermax != 0)&&(proto[i]->getSize() > pointermax)) { // Datatype is too big
|
|
||||||
// Assume datatype is stored elsewhere and only the pointer is passed
|
|
||||||
AddrSpace *spc = spacebase;
|
|
||||||
if (spc == (AddrSpace *)0)
|
|
||||||
spc = typefactory.getArch()->getDefaultDataSpace();
|
|
||||||
int4 pointersize = spc->getAddrSize();
|
|
||||||
int4 wordsize = spc->getWordSize();
|
|
||||||
Datatype *pointertp = typefactory.getTypePointer(pointersize,proto[i],wordsize);
|
|
||||||
res.back().addr = assignAddress(pointertp,status);
|
|
||||||
res.back().type = pointertp;
|
|
||||||
res.back().flags = ParameterPieces::indirectstorage;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
res.back().addr = assignAddress(proto[i],status);
|
|
||||||
if (res.back().addr.isInvalid())
|
|
||||||
throw ParamUnassignedError("Cannot assign parameter address for " + proto[i]->getName());
|
|
||||||
res.back().type = proto[i];
|
|
||||||
res.back().flags = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
for(int4 i=1;i<proto.size();++i) {
|
||||||
res.emplace_back();
|
res.emplace_back();
|
||||||
if (proto[0]->getMetatype() != TYPE_VOID) {
|
if ((pointermax != 0) && (proto[i]->getSize() > pointermax)) { // Datatype is too big
|
||||||
res.back().addr = assignAddress(proto[0],status);
|
// Assume datatype is stored elsewhere and only the pointer is passed
|
||||||
if (res.back().addr.isInvalid())
|
AddrSpace *spc = spacebase;
|
||||||
throw ParamUnassignedError("Cannot assign parameter address for " + proto[0]->getName());
|
if (spc == (AddrSpace*)0) spc = typefactory.getArch()->getDefaultDataSpace();
|
||||||
|
int4 pointersize = spc->getAddrSize();
|
||||||
|
int4 wordsize = spc->getWordSize();
|
||||||
|
Datatype *pointertp = typefactory.getTypePointer(pointersize,proto[i],wordsize);
|
||||||
|
res.back().addr = assignAddress(pointertp,status);
|
||||||
|
res.back().type = pointertp;
|
||||||
|
res.back().flags = ParameterPieces::indirectstorage;
|
||||||
}
|
}
|
||||||
res.back().type = proto[0];
|
else
|
||||||
|
res.back().addr = assignAddress(proto[i],status);
|
||||||
|
if (res.back().addr.isInvalid())
|
||||||
|
throw ParamUnassignedError("Cannot assign parameter address for " + proto[i]->getName());
|
||||||
|
res.back().type = proto[i];
|
||||||
res.back().flags = 0;
|
res.back().flags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1210,40 +1196,21 @@ ParamList *ParamListStandard::clone(void) const
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParamListStandardOut::assignMap(const vector<Datatype *> &proto,bool isinput,
|
void ParamListRegisterOut::assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
||||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
|
||||||
{
|
{
|
||||||
vector<int4> status(numgroup,0);
|
vector<int4> status(numgroup,0);
|
||||||
|
|
||||||
// This is always an output list so we ignore -isinput-
|
|
||||||
res.emplace_back();
|
res.emplace_back();
|
||||||
|
if (proto[0]->getMetatype() != TYPE_VOID) {
|
||||||
|
res.back().addr = assignAddress(proto[0],status);
|
||||||
|
if (res.back().addr.isInvalid())
|
||||||
|
throw ParamUnassignedError("Cannot assign parameter address for " + proto[0]->getName());
|
||||||
|
}
|
||||||
res.back().type = proto[0];
|
res.back().type = proto[0];
|
||||||
res.back().flags = 0;
|
res.back().flags = 0;
|
||||||
if (proto[0]->getMetatype() == TYPE_VOID) {
|
|
||||||
return; // Leave the address as invalid
|
|
||||||
}
|
|
||||||
res.back().addr = assignAddress(proto[0],status);
|
|
||||||
if (res.back().addr.isInvalid()) { // Could not assign an address (too big)
|
|
||||||
AddrSpace *spc = spacebase;
|
|
||||||
if (spc == (AddrSpace *)0)
|
|
||||||
spc = typefactory.getArch()->getDefaultDataSpace();
|
|
||||||
int4 pointersize = spc->getAddrSize();
|
|
||||||
int4 wordsize = spc->getWordSize();
|
|
||||||
Datatype *pointertp = typefactory.getTypePointer(pointersize, proto[0], wordsize);
|
|
||||||
res.back().addr = assignAddress(pointertp,status);
|
|
||||||
if (res.back().addr.isInvalid())
|
|
||||||
throw ParamUnassignedError("Cannot assign return value as a pointer");
|
|
||||||
res.back().type = pointertp;
|
|
||||||
res.back().flags = ParameterPieces::indirectstorage;
|
|
||||||
|
|
||||||
res.emplace_back(); // Add extra storage location in the input params
|
|
||||||
res.back().type = pointertp; // that holds a pointer to where the return value should be stored
|
|
||||||
// leave its address invalid, to be filled in by the input list assignMap
|
|
||||||
res.back().flags = ParameterPieces::hiddenretparm; // Mark it as special
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParamListStandardOut::fillinMap(ParamActive *active) const
|
void ParamListRegisterOut::fillinMap(ParamActive *active) const
|
||||||
|
|
||||||
{
|
{
|
||||||
if (active->getNumTrials() == 0) return; // No trials to check
|
if (active->getNumTrials() == 0) return; // No trials to check
|
||||||
|
@ -1324,7 +1291,7 @@ void ParamListStandardOut::fillinMap(ParamActive *active) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParamListStandardOut::possibleParam(const Address &loc,int4 size) const
|
bool ParamListRegisterOut::possibleParam(const Address &loc,int4 size) const
|
||||||
|
|
||||||
{
|
{
|
||||||
list<ParamEntry>::const_iterator iter;
|
list<ParamEntry>::const_iterator iter;
|
||||||
|
@ -1335,31 +1302,21 @@ bool ParamListStandardOut::possibleParam(const Address &loc,int4 size) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParamListStandardOut::restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack)
|
void ParamListRegisterOut::restoreXml(const Element *el,const AddrSpaceManager *manage,
|
||||||
|
vector<EffectRecord> &effectlist,bool normalstack)
|
||||||
{
|
{
|
||||||
ParamListStandard::restoreXml(el,manage,effectlist,normalstack);
|
ParamListStandard::restoreXml(el,manage,effectlist,normalstack);
|
||||||
// Check for double precision entries
|
|
||||||
list<ParamEntry>::iterator iter;
|
list<ParamEntry>::iterator iter;
|
||||||
ParamEntry *previous1 = (ParamEntry *)0;
|
|
||||||
ParamEntry *previous2 = (ParamEntry *)0;
|
|
||||||
for(iter=entry.begin();iter!=entry.end();++iter) {
|
for(iter=entry.begin();iter!=entry.end();++iter) {
|
||||||
ParamEntry &curEntry(*iter);
|
ParamEntry &curEntry(*iter);
|
||||||
curEntry.extraChecks(entry);
|
curEntry.extraChecks(entry);
|
||||||
if (previous1 != (ParamEntry *)0) {
|
|
||||||
ParamEntry::orderWithinGroup(*previous1, curEntry);
|
|
||||||
if (previous2 != (ParamEntry *)0)
|
|
||||||
ParamEntry::orderWithinGroup(*previous2, curEntry);
|
|
||||||
}
|
|
||||||
previous2 = previous1;
|
|
||||||
previous1 = &curEntry;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamList *ParamListStandardOut::clone(void) const
|
ParamList *ParamListRegisterOut::clone(void) const
|
||||||
|
|
||||||
{
|
{
|
||||||
ParamList *res = new ParamListStandardOut(*this);
|
ParamList *res = new ParamListRegisterOut(*this);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1390,6 +1347,65 @@ ParamList *ParamListRegister::clone(void) const
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParamListStandardOut::assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
||||||
|
|
||||||
|
{
|
||||||
|
vector<int4> status(numgroup,0);
|
||||||
|
|
||||||
|
res.emplace_back();
|
||||||
|
res.back().type = proto[0];
|
||||||
|
res.back().flags = 0;
|
||||||
|
if (proto[0]->getMetatype() == TYPE_VOID) {
|
||||||
|
return; // Leave the address as invalid
|
||||||
|
}
|
||||||
|
res.back().addr = assignAddress(proto[0],status);
|
||||||
|
if (res.back().addr.isInvalid()) { // Could not assign an address (too big)
|
||||||
|
AddrSpace *spc = spacebase;
|
||||||
|
if (spc == (AddrSpace *)0)
|
||||||
|
spc = typefactory.getArch()->getDefaultDataSpace();
|
||||||
|
int4 pointersize = spc->getAddrSize();
|
||||||
|
int4 wordsize = spc->getWordSize();
|
||||||
|
Datatype *pointertp = typefactory.getTypePointer(pointersize, proto[0], wordsize);
|
||||||
|
res.back().addr = assignAddress(pointertp,status);
|
||||||
|
if (res.back().addr.isInvalid())
|
||||||
|
throw ParamUnassignedError("Cannot assign return value as a pointer");
|
||||||
|
res.back().type = pointertp;
|
||||||
|
res.back().flags = ParameterPieces::indirectstorage;
|
||||||
|
|
||||||
|
res.emplace_back(); // Add extra storage location in the input params
|
||||||
|
res.back().type = pointertp; // that holds a pointer to where the return value should be stored
|
||||||
|
// leave its address invalid, to be filled in by the input list assignMap
|
||||||
|
res.back().flags = ParameterPieces::hiddenretparm; // Mark it as special
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParamListStandardOut::restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack)
|
||||||
|
|
||||||
|
{
|
||||||
|
ParamListRegisterOut::restoreXml(el,manage,effectlist,normalstack);
|
||||||
|
// Check for double precision entries
|
||||||
|
list<ParamEntry>::iterator iter;
|
||||||
|
ParamEntry *previous1 = (ParamEntry *)0;
|
||||||
|
ParamEntry *previous2 = (ParamEntry *)0;
|
||||||
|
for(iter=entry.begin();iter!=entry.end();++iter) {
|
||||||
|
ParamEntry &curEntry(*iter);
|
||||||
|
if (previous1 != (ParamEntry *)0) {
|
||||||
|
ParamEntry::orderWithinGroup(*previous1, curEntry);
|
||||||
|
if (previous2 != (ParamEntry *)0)
|
||||||
|
ParamEntry::orderWithinGroup(*previous2, curEntry);
|
||||||
|
}
|
||||||
|
previous2 = previous1;
|
||||||
|
previous1 = &curEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParamList *ParamListStandardOut::clone(void) const
|
||||||
|
|
||||||
|
{
|
||||||
|
ParamList *res = new ParamListStandardOut( *this );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/// The given set of parameter entries are folded into \b this set.
|
/// The given set of parameter entries are folded into \b this set.
|
||||||
/// Duplicate entries are eliminated. Containing entries subsume what
|
/// Duplicate entries are eliminated. Containing entries subsume what
|
||||||
/// they contain.
|
/// they contain.
|
||||||
|
@ -1884,7 +1900,7 @@ void ProtoModel::buildParamList(const string &strategy)
|
||||||
}
|
}
|
||||||
else if (strategy == "register") {
|
else if (strategy == "register") {
|
||||||
input = new ParamListRegister();
|
input = new ParamListRegister();
|
||||||
output = new ParamListStandardOut();
|
output = new ParamListRegisterOut();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw LowlevelError("Unknown strategy type: "+strategy);
|
throw LowlevelError("Unknown strategy type: "+strategy);
|
||||||
|
@ -1985,7 +2001,7 @@ void ProtoModel::assignParameterStorage(const vector<Datatype *> &typelist,vecto
|
||||||
{
|
{
|
||||||
if (ignoreOutputError) {
|
if (ignoreOutputError) {
|
||||||
try {
|
try {
|
||||||
output->assignMap(typelist,false,*glb->types,res);
|
output->assignMap(typelist,*glb->types,res);
|
||||||
}
|
}
|
||||||
catch(ParamUnassignedError &err) {
|
catch(ParamUnassignedError &err) {
|
||||||
res.clear();
|
res.clear();
|
||||||
|
@ -1996,9 +2012,9 @@ void ProtoModel::assignParameterStorage(const vector<Datatype *> &typelist,vecto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
output->assignMap(typelist,false,*glb->types,res);
|
output->assignMap(typelist,*glb->types,res);
|
||||||
}
|
}
|
||||||
input->assignMap(typelist,true,*glb->types,res);
|
input->assignMap(typelist,*glb->types,res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Look up an effect from the given EffectRecord list
|
/// \brief Look up an effect from the given EffectRecord list
|
||||||
|
|
|
@ -355,6 +355,7 @@ public:
|
||||||
p_standard, ///< Standard input parameter model
|
p_standard, ///< Standard input parameter model
|
||||||
p_standard_out, ///< Standard output (return value) model
|
p_standard_out, ///< Standard output (return value) model
|
||||||
p_register, ///< Unordered parameter passing locations model
|
p_register, ///< Unordered parameter passing locations model
|
||||||
|
p_register_out, ///< Multiple possible return value locations model
|
||||||
p_merged ///< A merged model (multiple models merged together)
|
p_merged ///< A merged model (multiple models merged together)
|
||||||
};
|
};
|
||||||
virtual ~ParamList(void) {} ///< Destructor
|
virtual ~ParamList(void) {} ///< Destructor
|
||||||
|
@ -364,11 +365,9 @@ public:
|
||||||
///
|
///
|
||||||
/// If we know the function prototype, recover how parameters are actually stored using the model.
|
/// If we know the function prototype, recover how parameters are actually stored using the model.
|
||||||
/// \param proto is the ordered list of data-types
|
/// \param proto is the ordered list of data-types
|
||||||
/// \param isinput is \b true for the input prototype, \b false for output prototype
|
|
||||||
/// \param typefactory is the TypeFactory (for constructing pointers)
|
/// \param typefactory is the TypeFactory (for constructing pointers)
|
||||||
/// \param res will contain the storage locations corresponding to the datatypes
|
/// \param res will contain the storage locations corresponding to the datatypes
|
||||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const=0;
|
||||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const=0;
|
|
||||||
|
|
||||||
/// \brief Given an unordered list of storage locations, calculate a function prototype
|
/// \brief Given an unordered list of storage locations, calculate a function prototype
|
||||||
///
|
///
|
||||||
|
@ -530,8 +529,7 @@ public:
|
||||||
virtual ~ParamListStandard(void);
|
virtual ~ParamListStandard(void);
|
||||||
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
||||||
virtual uint4 getType(void) const { return p_standard; }
|
virtual uint4 getType(void) const { return p_standard; }
|
||||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
|
||||||
virtual void fillinMap(ParamActive *active) const;
|
virtual void fillinMap(ParamActive *active) const;
|
||||||
virtual bool checkJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const;
|
virtual bool checkJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const;
|
||||||
virtual bool checkSplit(const Address &loc,int4 size,int4 splitpoint) const;
|
virtual bool checkSplit(const Address &loc,int4 size,int4 splitpoint) const;
|
||||||
|
@ -548,20 +546,19 @@ public:
|
||||||
virtual ParamList *clone(void) const;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A standard model for passing back return values from a function
|
/// \brief A model for passing back return values from a function
|
||||||
///
|
///
|
||||||
/// This models a resource list of potential storage locations for a return value,
|
/// This is a resource list of potential storage locations for a return value,
|
||||||
/// at most 1 of which will be chosen for a given function. Order only matters in that the
|
/// at most 1 of which will be chosen for a given function. This models a simple strategy
|
||||||
/// first ParamEntry that fits is used. If no entry fits, the return value is
|
/// for selecting a storage location. When assigning based on data-type (assignMap), the first list
|
||||||
/// converted to a pointer data-type, storage allocation is attempted again, and the
|
/// entry that fits is chosen. When assigning from a set of actively used locations (fillinMap),
|
||||||
/// return value is marked as a \e hidden return parameter to inform the input model.
|
/// this class chooses the location that is the closest fitting match to an entry in the resource list.
|
||||||
class ParamListStandardOut : public ParamListStandard {
|
class ParamListRegisterOut : public ParamListStandard {
|
||||||
public:
|
public:
|
||||||
ParamListStandardOut(void) : ParamListStandard() {} ///< Constructor
|
ParamListRegisterOut(void) : ParamListStandard() {} ///< Constructor
|
||||||
ParamListStandardOut(const ParamListStandardOut &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
ParamListRegisterOut(const ParamListRegisterOut &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
||||||
virtual uint4 getType(void) const { return p_standard_out; }
|
virtual uint4 getType(void) const { return p_register_out; }
|
||||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
|
||||||
virtual void fillinMap(ParamActive *active) const;
|
virtual void fillinMap(ParamActive *active) const;
|
||||||
virtual bool possibleParam(const Address &loc,int4 size) const;
|
virtual bool possibleParam(const Address &loc,int4 size) const;
|
||||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
||||||
|
@ -584,6 +581,24 @@ public:
|
||||||
virtual ParamList *clone(void) const;
|
virtual ParamList *clone(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A standard model for returning output parameters from a function
|
||||||
|
///
|
||||||
|
/// This has a more involved assignment strategy than its parent class.
|
||||||
|
/// Entries in the resource list are treated as a \e group, meaning that only one can
|
||||||
|
/// fit the desired storage size and type attributes of the return value. If no entry
|
||||||
|
/// fits, the return value is converted to a pointer data-type, storage allocation is
|
||||||
|
/// attempted again, and the return value is marked as a \e hidden return parameter
|
||||||
|
/// to inform the input model.
|
||||||
|
class ParamListStandardOut : public ParamListRegisterOut {
|
||||||
|
public:
|
||||||
|
ParamListStandardOut(void) : ParamListRegisterOut() {} ///< Constructor for use with restoreXml()
|
||||||
|
ParamListStandardOut(const ParamListStandardOut &op2) : ParamListRegisterOut(op2) {} ///< Copy constructor
|
||||||
|
virtual uint4 getType(void) const { return p_standard_out; }
|
||||||
|
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||||
|
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
||||||
|
virtual ParamList *clone(void) const;
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief A union of other input parameter passing models
|
/// \brief A union of other input parameter passing models
|
||||||
///
|
///
|
||||||
/// This model is viewed as a union of a constituent set of resource lists.
|
/// This model is viewed as a union of a constituent set of resource lists.
|
||||||
|
@ -599,8 +614,7 @@ public:
|
||||||
void foldIn(const ParamListStandard &op2); ///< Add another model to the union
|
void foldIn(const ParamListStandard &op2); ///< Add another model to the union
|
||||||
void finalize(void) { populateResolver(); } ///< Fold-ins are finished, finalize \b this
|
void finalize(void) { populateResolver(); } ///< Fold-ins are finished, finalize \b this
|
||||||
virtual uint4 getType(void) const { return p_merged; }
|
virtual uint4 getType(void) const { return p_merged; }
|
||||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const {
|
||||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const {
|
|
||||||
throw LowlevelError("Cannot assign prototype before model has been resolved"); }
|
throw LowlevelError("Cannot assign prototype before model has been resolved"); }
|
||||||
virtual void fillinMap(ParamActive *active) const {
|
virtual void fillinMap(ParamActive *active) const {
|
||||||
throw LowlevelError("Cannot determine prototype before model has been resolved"); }
|
throw LowlevelError("Cannot determine prototype before model has been resolved"); }
|
||||||
|
|
|
@ -38,12 +38,11 @@ public interface ParamList {
|
||||||
* Given a list of datatypes, calculate the storage locations used for passing those datatypes
|
* Given a list of datatypes, calculate the storage locations used for passing those datatypes
|
||||||
* @param prog is the active progra
|
* @param prog is the active progra
|
||||||
* @param proto is the list of datatypes
|
* @param proto is the list of datatypes
|
||||||
* @param isinput is true if this parameter list is being processed for input arguments, false for output
|
|
||||||
* @param res is the vector for holding the VariableStorage corresponding to datatypes
|
* @param res is the vector for holding the VariableStorage corresponding to datatypes
|
||||||
* @param addAutoParams if true add/process auto-parameters
|
* @param addAutoParams if true add/process auto-parameters
|
||||||
*/
|
*/
|
||||||
public void assignMap(Program prog, DataType[] proto, boolean isinput,
|
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
|
||||||
ArrayList<VariableStorage> res, boolean addAutoParams);
|
boolean addAutoParams);
|
||||||
|
|
||||||
public void saveXml(StringBuilder buffer, boolean isInput);
|
public void saveXml(StringBuilder buffer, boolean isInput);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.program.model.lang;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.listing.VariableStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of resources describing possible storage locations for a function's return value,
|
||||||
|
* and a strategy for selecting a storage location based on data-types in a function signature.
|
||||||
|
*
|
||||||
|
* The assignment strategy for this class is to take the first storage location in the list
|
||||||
|
* that fits for the given function signature's return data-type.
|
||||||
|
*/
|
||||||
|
public class ParamListRegisterOut extends ParamListStandard {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
|
||||||
|
boolean addAutoParams) {
|
||||||
|
int[] status = new int[numgroup];
|
||||||
|
for (int i = 0; i < numgroup; ++i) {
|
||||||
|
status[i] = 0;
|
||||||
|
}
|
||||||
|
VariableStorage store = assignAddress(prog, proto[0], status, false, false);
|
||||||
|
res.add(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -143,37 +143,30 @@ public class ParamListStandard implements ParamList {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignMap(Program prog, DataType[] proto, boolean isinput,
|
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
|
||||||
ArrayList<VariableStorage> res, boolean addAutoParams) {
|
boolean addAutoParams) {
|
||||||
int[] status = new int[numgroup];
|
int[] status = new int[numgroup];
|
||||||
for (int i = 0; i < numgroup; ++i) {
|
for (int i = 0; i < numgroup; ++i) {
|
||||||
status[i] = 0;
|
status[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isinput) {
|
if (addAutoParams && res.size() == 2) { // Check for hidden parameters defined by the output list
|
||||||
if (addAutoParams && res.size() == 2) { // Check for hidden parameters defined by the output list
|
DataTypeManager dtm = prog.getDataTypeManager();
|
||||||
DataTypeManager dtm = prog.getDataTypeManager();
|
Pointer pointer = dtm.getPointer(proto[0]);
|
||||||
Pointer pointer = dtm.getPointer(proto[0]);
|
VariableStorage store = assignAddress(prog, pointer, status, true, false);
|
||||||
VariableStorage store = assignAddress(prog, pointer, status, true, false);
|
res.set(1, store);
|
||||||
res.set(1, store);
|
|
||||||
}
|
|
||||||
for (int i = 1; i < proto.length; ++i) {
|
|
||||||
VariableStorage store;
|
|
||||||
if ((pointermax != 0) && (proto[i] != null) &&
|
|
||||||
(proto[i].getLength() > pointermax)) { // DataType is too big
|
|
||||||
// Assume datatype is stored elsewhere and only the pointer is passed
|
|
||||||
DataTypeManager dtm = prog.getDataTypeManager();
|
|
||||||
Pointer pointer = dtm.getPointer(proto[i]);
|
|
||||||
store = assignAddress(prog, pointer, status, false, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
store = assignAddress(prog, proto[i], status, false, false);
|
|
||||||
}
|
|
||||||
res.add(store);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
for (int i = 1; i < proto.length; ++i) {
|
||||||
VariableStorage store = assignAddress(prog, proto[0], status, false, false);
|
VariableStorage store;
|
||||||
|
if ((pointermax != 0) && (proto[i] != null) && (proto[i].getLength() > pointermax)) { // DataType is too big
|
||||||
|
// Assume datatype is stored elsewhere and only the pointer is passed
|
||||||
|
DataTypeManager dtm = prog.getDataTypeManager();
|
||||||
|
Pointer pointer = dtm.getPointer(proto[i]);
|
||||||
|
store = assignAddress(prog, pointer, status, false, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
store = assignAddress(prog, proto[i], status, false, false);
|
||||||
|
}
|
||||||
res.add(store);
|
res.add(store);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,11 +272,12 @@ public class ParamListStandard implements ParamList {
|
||||||
throw new XmlParseException(
|
throw new XmlParseException(
|
||||||
"<pentry> in the join space not allowed in <group> tag");
|
"<pentry> in the join space not allowed in <group> tag");
|
||||||
}
|
}
|
||||||
if (count > 1) {
|
}
|
||||||
ParamEntry.orderWithinGroup(pe.get(pe.size() - 2), lastEntry);
|
// Check that all entries in the group are distinguishable
|
||||||
if (count > 2) {
|
for (int i = 1; i < count; ++i) {
|
||||||
ParamEntry.orderWithinGroup(pe.get(pe.size() - 3), lastEntry);
|
ParamEntry curEntry = pe.get(pe.size() - 1 - i);
|
||||||
}
|
for (int j = 0; j < i; ++i) {
|
||||||
|
ParamEntry.orderWithinGroup(pe.get(pe.size() - 1 - j), curEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.end(el);
|
parser.end(el);
|
||||||
|
|
|
@ -24,11 +24,23 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.xml.XmlParseException;
|
import ghidra.xml.XmlParseException;
|
||||||
import ghidra.xml.XmlPullParser;
|
import ghidra.xml.XmlPullParser;
|
||||||
|
|
||||||
public class ParamListStandardOut extends ParamListStandard {
|
/**
|
||||||
|
* A list of resources describing possible storage locations for a function's return value,
|
||||||
|
* and a strategy for selecting a storage location based on data-types in a function signature.
|
||||||
|
*
|
||||||
|
* Similar to the parent class, when assigning storage, the first entry that matches the data-type
|
||||||
|
* is chosen. But if this instance fails to find a match (because the return value data-type is too
|
||||||
|
* big) the data-type is converted to a pointer and storage is assigned based on that pointer.
|
||||||
|
* Additionally, if configured, this instance will signal that a hidden input parameter is required
|
||||||
|
* to fully model where the large return value is stored.
|
||||||
|
*
|
||||||
|
* The resource list is checked to ensure entries are distinguishable.
|
||||||
|
*/
|
||||||
|
public class ParamListStandardOut extends ParamListRegisterOut {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignMap(Program prog, DataType[] proto, boolean isinput,
|
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
|
||||||
ArrayList<VariableStorage> res, boolean addAutoParams) {
|
boolean addAutoParams) {
|
||||||
|
|
||||||
int[] status = new int[numgroup];
|
int[] status = new int[numgroup];
|
||||||
for (int i = 0; i < numgroup; ++i) {
|
for (int i = 0; i < numgroup; ++i) {
|
||||||
|
@ -64,11 +76,10 @@ public class ParamListStandardOut extends ParamListStandard {
|
||||||
public void restoreXml(XmlPullParser parser, CompilerSpec cspec) throws XmlParseException {
|
public void restoreXml(XmlPullParser parser, CompilerSpec cspec) throws XmlParseException {
|
||||||
super.restoreXml(parser, cspec);
|
super.restoreXml(parser, cspec);
|
||||||
|
|
||||||
// ParamEntry tags in the output list are considered a group
|
// ParamEntry tags in the output list are considered a group. Check that entries are distinguishable.
|
||||||
for (int i = 1; i < entry.length; ++i) {
|
for (int i = 1; i < entry.length; ++i) {
|
||||||
ParamEntry.orderWithinGroup(entry[i - 1], entry[i]);
|
for (int j = 0; j < i; ++j) {
|
||||||
if (i > 1) {
|
ParamEntry.orderWithinGroup(entry[j], entry[i]);
|
||||||
ParamEntry.orderWithinGroup(entry[i - 2], entry[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ public class PrototypeModel {
|
||||||
DataType[] arr = new DataType[1];
|
DataType[] arr = new DataType[1];
|
||||||
arr[0] = clone;
|
arr[0] = clone;
|
||||||
ArrayList<VariableStorage> res = new ArrayList<>();
|
ArrayList<VariableStorage> res = new ArrayList<>();
|
||||||
outputParams.assignMap(program, arr, false, res, false);
|
outputParams.assignMap(program, arr, res, false);
|
||||||
if (res.size() > 0) {
|
if (res.size() > 0) {
|
||||||
return res.get(0);
|
return res.get(0);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ public class PrototypeModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
DataType arr[] = new DataType[argIndex + 2];
|
DataType arr[] = new DataType[argIndex + 2];
|
||||||
arr[0] = DataType.VOID; // Assume the return type is void
|
arr[0] = VoidDataType.dataType; // Assume the return type is void
|
||||||
for (int i = 0; i < argIndex; ++i) {
|
for (int i = 0; i < argIndex; ++i) {
|
||||||
if (params != null && i < params.length) {
|
if (params != null && i < params.length) {
|
||||||
arr[i + 1] = params[i].getDataType(); // Copy in current types if we have them
|
arr[i + 1] = params[i].getDataType(); // Copy in current types if we have them
|
||||||
|
@ -291,8 +291,8 @@ public class PrototypeModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<VariableStorage> res = new ArrayList<>();
|
ArrayList<VariableStorage> res = new ArrayList<>();
|
||||||
outputParams.assignMap(program, dataTypes, false, res, addAutoParams);
|
outputParams.assignMap(program, dataTypes, res, addAutoParams);
|
||||||
inputParams.assignMap(program, dataTypes, true, res, addAutoParams);
|
inputParams.assignMap(program, dataTypes, res, addAutoParams);
|
||||||
VariableStorage[] finalres = new VariableStorage[res.size()];
|
VariableStorage[] finalres = new VariableStorage[res.size()];
|
||||||
res.toArray(finalres);
|
res.toArray(finalres);
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ public class PrototypeModel {
|
||||||
}
|
}
|
||||||
else if (strategy.equals("register")) {
|
else if (strategy.equals("register")) {
|
||||||
inputParams = new ParamListStandard();
|
inputParams = new ParamListStandard();
|
||||||
outputParams = new ParamListStandard();
|
outputParams = new ParamListRegisterOut();
|
||||||
inputListType = InputListType.REGISTER;
|
inputListType = InputListType.REGISTER;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue