mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GP-1404_RiscvCspecParsing'
This commit is contained in:
commit
6f969ddf73
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
|
||||
}
|
||||
|
||||
void ParamListStandard::assignMap(const vector<Datatype *> &proto,bool isinput,TypeFactory &typefactory,
|
||||
vector<ParameterPieces> &res) const
|
||||
void ParamListStandard::assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
||||
|
||||
{
|
||||
vector<int4> status(numgroup,0);
|
||||
|
||||
if (isinput) {
|
||||
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().flags |= ParameterPieces::hiddenretparm;
|
||||
if (res.back().addr.isInvalid())
|
||||
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;
|
||||
}
|
||||
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().flags |= ParameterPieces::hiddenretparm;
|
||||
if (res.back().addr.isInvalid())
|
||||
throw ParamUnassignedError("Cannot assign parameter address for " + res.back().type->getName());
|
||||
}
|
||||
else {
|
||||
for(int4 i=1;i<proto.size();++i) {
|
||||
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());
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1210,40 +1196,21 @@ ParamList *ParamListStandard::clone(void) const
|
|||
return res;
|
||||
}
|
||||
|
||||
void ParamListStandardOut::assignMap(const vector<Datatype *> &proto,bool isinput,
|
||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
||||
void ParamListRegisterOut::assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const
|
||||
|
||||
{
|
||||
vector<int4> status(numgroup,0);
|
||||
|
||||
// This is always an output list so we ignore -isinput-
|
||||
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().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
|
||||
|
@ -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;
|
||||
|
@ -1335,31 +1302,21 @@ bool ParamListStandardOut::possibleParam(const Address &loc,int4 size) const
|
|||
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);
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1390,6 +1347,65 @@ ParamList *ParamListRegister::clone(void) const
|
|||
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.
|
||||
/// Duplicate entries are eliminated. Containing entries subsume what
|
||||
/// they contain.
|
||||
|
@ -1884,7 +1900,7 @@ void ProtoModel::buildParamList(const string &strategy)
|
|||
}
|
||||
else if (strategy == "register") {
|
||||
input = new ParamListRegister();
|
||||
output = new ParamListStandardOut();
|
||||
output = new ParamListRegisterOut();
|
||||
}
|
||||
else
|
||||
throw LowlevelError("Unknown strategy type: "+strategy);
|
||||
|
@ -1985,7 +2001,7 @@ void ProtoModel::assignParameterStorage(const vector<Datatype *> &typelist,vecto
|
|||
{
|
||||
if (ignoreOutputError) {
|
||||
try {
|
||||
output->assignMap(typelist,false,*glb->types,res);
|
||||
output->assignMap(typelist,*glb->types,res);
|
||||
}
|
||||
catch(ParamUnassignedError &err) {
|
||||
res.clear();
|
||||
|
@ -1996,9 +2012,9 @@ void ProtoModel::assignParameterStorage(const vector<Datatype *> &typelist,vecto
|
|||
}
|
||||
}
|
||||
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
|
||||
|
|
|
@ -355,6 +355,7 @@ public:
|
|||
p_standard, ///< Standard input parameter model
|
||||
p_standard_out, ///< Standard output (return value) 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)
|
||||
};
|
||||
virtual ~ParamList(void) {} ///< Destructor
|
||||
|
@ -364,11 +365,9 @@ public:
|
|||
///
|
||||
/// 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 isinput is \b true for the input prototype, \b false for output prototype
|
||||
/// \param typefactory is the TypeFactory (for constructing pointers)
|
||||
/// \param res will contain the storage locations corresponding to the datatypes
|
||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const=0;
|
||||
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const=0;
|
||||
|
||||
/// \brief Given an unordered list of storage locations, calculate a function prototype
|
||||
///
|
||||
|
@ -530,8 +529,7 @@ public:
|
|||
virtual ~ParamListStandard(void);
|
||||
const list<ParamEntry> &getEntry(void) const { return entry; } ///< Get the list of parameter entries
|
||||
virtual uint4 getType(void) const { return p_standard; }
|
||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||
virtual void fillinMap(ParamActive *active) 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;
|
||||
|
@ -548,20 +546,19 @@ public:
|
|||
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,
|
||||
/// at most 1 of which will be chosen for a given function. Order only matters in that the
|
||||
/// first ParamEntry that fits is used. 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 ParamListStandard {
|
||||
/// 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. This models a simple strategy
|
||||
/// for selecting a storage location. When assigning based on data-type (assignMap), the first list
|
||||
/// entry that fits is chosen. When assigning from a set of actively used locations (fillinMap),
|
||||
/// this class chooses the location that is the closest fitting match to an entry in the resource list.
|
||||
class ParamListRegisterOut : public ParamListStandard {
|
||||
public:
|
||||
ParamListStandardOut(void) : ParamListStandard() {} ///< Constructor
|
||||
ParamListStandardOut(const ParamListStandardOut &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
||||
virtual uint4 getType(void) const { return p_standard_out; }
|
||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||
ParamListRegisterOut(void) : ParamListStandard() {} ///< Constructor
|
||||
ParamListRegisterOut(const ParamListRegisterOut &op2) : ParamListStandard(op2) {} ///< Copy constructor
|
||||
virtual uint4 getType(void) const { return p_register_out; }
|
||||
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
|
||||
virtual void fillinMap(ParamActive *active) const;
|
||||
virtual bool possibleParam(const Address &loc,int4 size) const;
|
||||
virtual void restoreXml(const Element *el,const AddrSpaceManager *manage,vector<EffectRecord> &effectlist,bool normalstack);
|
||||
|
@ -584,6 +581,24 @@ public:
|
|||
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
|
||||
///
|
||||
/// 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 finalize(void) { populateResolver(); } ///< Fold-ins are finished, finalize \b this
|
||||
virtual uint4 getType(void) const { return p_merged; }
|
||||
virtual void assignMap(const vector<Datatype *> &proto,bool isinput,
|
||||
TypeFactory &typefactory,vector<ParameterPieces> &res) const {
|
||||
virtual void assignMap(const vector<Datatype *> &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const {
|
||||
throw LowlevelError("Cannot assign prototype before model has been resolved"); }
|
||||
virtual void fillinMap(ParamActive *active) const {
|
||||
throw LowlevelError("Cannot determine prototype before model has been resolved"); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue