mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +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
|
||||
}
|
||||
|
||||
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"); }
|
||||
|
|
|
@ -38,12 +38,11 @@ public interface ParamList {
|
|||
* Given a list of datatypes, calculate the storage locations used for passing those datatypes
|
||||
* @param prog is the active progra
|
||||
* @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 addAutoParams if true add/process auto-parameters
|
||||
*/
|
||||
public void assignMap(Program prog, DataType[] proto, boolean isinput,
|
||||
ArrayList<VariableStorage> res, boolean addAutoParams);
|
||||
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
|
||||
boolean addAutoParams);
|
||||
|
||||
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
|
||||
public void assignMap(Program prog, DataType[] proto, boolean isinput,
|
||||
ArrayList<VariableStorage> res, boolean addAutoParams) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (isinput) {
|
||||
if (addAutoParams && res.size() == 2) { // Check for hidden parameters defined by the output list
|
||||
DataTypeManager dtm = prog.getDataTypeManager();
|
||||
Pointer pointer = dtm.getPointer(proto[0]);
|
||||
VariableStorage store = assignAddress(prog, pointer, status, true, false);
|
||||
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);
|
||||
}
|
||||
if (addAutoParams && res.size() == 2) { // Check for hidden parameters defined by the output list
|
||||
DataTypeManager dtm = prog.getDataTypeManager();
|
||||
Pointer pointer = dtm.getPointer(proto[0]);
|
||||
VariableStorage store = assignAddress(prog, pointer, status, true, false);
|
||||
res.set(1, store);
|
||||
}
|
||||
else {
|
||||
VariableStorage store = assignAddress(prog, proto[0], status, false, false);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -279,11 +272,12 @@ public class ParamListStandard implements ParamList {
|
|||
throw new XmlParseException(
|
||||
"<pentry> in the join space not allowed in <group> tag");
|
||||
}
|
||||
if (count > 1) {
|
||||
ParamEntry.orderWithinGroup(pe.get(pe.size() - 2), lastEntry);
|
||||
if (count > 2) {
|
||||
ParamEntry.orderWithinGroup(pe.get(pe.size() - 3), lastEntry);
|
||||
}
|
||||
}
|
||||
// Check that all entries in the group are distinguishable
|
||||
for (int i = 1; i < count; ++i) {
|
||||
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);
|
||||
|
|
|
@ -24,11 +24,23 @@ import ghidra.util.exception.InvalidInputException;
|
|||
import ghidra.xml.XmlParseException;
|
||||
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
|
||||
public void assignMap(Program prog, DataType[] proto, boolean isinput,
|
||||
ArrayList<VariableStorage> res, boolean addAutoParams) {
|
||||
public void assignMap(Program prog, DataType[] proto, ArrayList<VariableStorage> res,
|
||||
boolean addAutoParams) {
|
||||
|
||||
int[] status = new int[numgroup];
|
||||
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 {
|
||||
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) {
|
||||
ParamEntry.orderWithinGroup(entry[i - 1], entry[i]);
|
||||
if (i > 1) {
|
||||
ParamEntry.orderWithinGroup(entry[i - 2], entry[i]);
|
||||
for (int j = 0; j < i; ++j) {
|
||||
ParamEntry.orderWithinGroup(entry[j], entry[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ public class PrototypeModel {
|
|||
DataType[] arr = new DataType[1];
|
||||
arr[0] = clone;
|
||||
ArrayList<VariableStorage> res = new ArrayList<>();
|
||||
outputParams.assignMap(program, arr, false, res, false);
|
||||
outputParams.assignMap(program, arr, res, false);
|
||||
if (res.size() > 0) {
|
||||
return res.get(0);
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ public class PrototypeModel {
|
|||
}
|
||||
|
||||
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) {
|
||||
if (params != null && i < params.length) {
|
||||
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<>();
|
||||
outputParams.assignMap(program, dataTypes, false, res, addAutoParams);
|
||||
inputParams.assignMap(program, dataTypes, true, res, addAutoParams);
|
||||
outputParams.assignMap(program, dataTypes, res, addAutoParams);
|
||||
inputParams.assignMap(program, dataTypes, res, addAutoParams);
|
||||
VariableStorage[] finalres = new VariableStorage[res.size()];
|
||||
res.toArray(finalres);
|
||||
|
||||
|
@ -351,7 +351,7 @@ public class PrototypeModel {
|
|||
}
|
||||
else if (strategy.equals("register")) {
|
||||
inputParams = new ParamListStandard();
|
||||
outputParams = new ParamListStandard();
|
||||
outputParams = new ParamListRegisterOut();
|
||||
inputListType = InputListType.REGISTER;
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue