Merge remote-tracking branch 'origin/GP-5262_AutoKilledByCall'

This commit is contained in:
Ryan Kurtz 2025-01-14 13:33:34 -05:00
commit 2589aae3a4
5 changed files with 49 additions and 38 deletions

View file

@ -586,6 +586,7 @@ ParamListStandard::ParamListStandard(const ParamListStandard &op2)
spacebase = op2.spacebase;
maxdelay = op2.maxdelay;
thisbeforeret = op2.thisbeforeret;
autoKilledByCall = op2.autoKilledByCall;
resourceStart = op2.resourceStart;
for(list<ModelRule>::const_iterator iter=op2.modelRules.begin();iter!=op2.modelRules.end();++iter) {
modelRules.emplace_back(*iter,&op2);
@ -1198,11 +1199,10 @@ void ParamListStandard::populateResolver(void)
/// \param effectlist holds any passed back effect records
/// \param groupid is the group to which the new ParamEntry is assigned
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
/// \param autokill is \b true if parameters are automatically added to the killedbycall list
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
/// \param grouped is \b true if the new ParamEntry is grouped with other entries
void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped)
int4 groupid,bool normalstack,bool splitFloat,bool grouped)
{
type_class lastClass = TYPECLASS_CLASS4;
if (!entry.empty()) {
@ -1221,7 +1221,7 @@ void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effec
AddrSpace *spc = entry.back().getSpace();
if (spc->getType() == IPTR_SPACEBASE)
spacebase = spc;
else if (autokill) // If a register parameter AND we automatically generate killedbycall
else if (autoKilledByCall) // If a register parameter AND we automatically generate killedbycall
effectlist.push_back(EffectRecord(entry.back(),EffectRecord::killedbycall));
int4 maxgroup = entry.back().getAllGroups().back() + 1;
@ -1236,17 +1236,16 @@ void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effec
/// \param effectlist holds any passed back effect records
/// \param groupid is the group to which all ParamEntry elements are assigned
/// \param normalstack is \b true if the parameters should be allocated from the front of the range
/// \param autokill is \b true if parameters are automatically added to the killedbycall list
/// \param splitFloat is \b true if floating-point parameters are in their own resource section
void ParamListStandard::parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat)
int4 groupid,bool normalstack,bool splitFloat)
{
int4 basegroup = numgroup;
ParamEntry *previous1 = (ParamEntry *)0;
ParamEntry *previous2 = (ParamEntry *)0;
uint4 elemId = decoder.openElement(ELEM_GROUP);
while(decoder.peekElement() != 0) {
parsePentry(decoder, effectlist, basegroup, normalstack, autokill, splitFloat, true);
parsePentry(decoder, effectlist, basegroup, normalstack, splitFloat, true);
ParamEntry &pentry( entry.back() );
if (pentry.getSpace()->getType() == IPTR_JOIN)
throw LowlevelError("<pentry> in the join space not allowed in <group> tag");
@ -1434,8 +1433,8 @@ void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist
spacebase = (AddrSpace *)0;
int4 pointermax = 0;
thisbeforeret = false;
autoKilledByCall = false;
bool splitFloat = true; // True if we should split FLOAT entries into their own resource section
bool autokilledbycall = false;
uint4 elemId = decoder.openElement();
for(;;) {
uint4 attribId = decoder.getNextAttributeId();
@ -1447,7 +1446,7 @@ void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist
thisbeforeret = decoder.readBool();
}
else if (attribId == ATTRIB_KILLEDBYCALL) {
autokilledbycall = decoder.readBool();
autoKilledByCall = decoder.readBool();
}
else if (attribId == ATTRIB_SEPARATEFLOAT) {
splitFloat = decoder.readBool();
@ -1457,10 +1456,10 @@ void ParamListStandard::decode(Decoder &decoder,vector<EffectRecord> &effectlist
uint4 subId = decoder.peekElement();
if (subId == 0) break;
if (subId == ELEM_PENTRY) {
parsePentry(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat, false);
parsePentry(decoder, effectlist, numgroup, normalstack, splitFloat, false);
}
else if (subId == ELEM_GROUP) {
parseGroup(decoder, effectlist, numgroup, normalstack, autokilledbycall, splitFloat);
parseGroup(decoder, effectlist, numgroup, normalstack, splitFloat);
}
else if (subId == ELEM_RULE) {
break;
@ -1599,6 +1598,8 @@ void ParamListStandardOut::initialize(void)
break;
}
}
if (useFillinFallback)
autoKilledByCall = true; // Legacy behavior if there are no rules
}
/// \brief Find the return value storage using the older \e fallback method
@ -3778,8 +3779,8 @@ void FuncProto::setModel(ProtoModel *m)
flags |= has_thisptr;
if (m->isConstructor())
flags |= is_constructor;
if (m->isAutoKillByCall())
flags |= auto_killbycall;
if (m->isAutoKilledByCall())
flags |= auto_killedbycall;
model = m;
}
else {
@ -4557,13 +4558,13 @@ void FuncProto::printRaw(const string &funcname,ostream &s) const
/// This assumes the storage location has already been determined to be contained
/// in standard return value location.
/// \return \b true if the location should be considered killed by call
bool FuncProto::isAutoKillByCall(void) const
bool FuncProto::isAutoKilledByCall(void) const
{
if ((flags & auto_killbycall)!=0)
return true; // The ProtoModel always does killbycall
if ((flags & auto_killedbycall)!=0)
return true; // The ProtoModel always does killedbycall
if (isOutputLocked())
return true; // A locked output location is killbycall by definition
return true; // A locked output location is killedbycall by definition
return false;
}

View file

@ -560,8 +560,8 @@ public:
/// \brief Return \b true if ParamEntry locations should automatically be considered killed by call
///
/// \return \b true if automatically assume killbycall
virtual bool isAutoKillByCall(void) const=0;
/// \return \b true if automatically assume \e killedbycall
virtual bool isAutoKilledByCall(void) const=0;
/// \brief Restore the model from an \<input> or \<output> element in the stream
///
@ -587,6 +587,7 @@ protected:
int4 numgroup; ///< Number of \e groups in this parameter convention
int4 maxdelay; ///< Maximum heritage delay across all parameters
bool thisbeforeret; ///< Does a \b this parameter come before a hidden return parameter
bool autoKilledByCall; ///< Are storage locations in \b this list automatically \e killed \e by \e call
vector<int4> resourceStart; ///< The starting group for each resource section
list<ParamEntry> entry; ///< The ordered list of parameter entries
vector<ParamEntryResolver *> resolverMap; ///< Map from space id to resolver
@ -605,9 +606,9 @@ protected:
void addResolverRange(AddrSpace *spc,uintb first,uintb last,ParamEntry *paramEntry,int4 position);
void populateResolver(void); ///< Build the ParamEntry resolver maps
void parsePentry(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat,bool grouped);
int4 groupid,bool normalstack,bool splitFloat,bool grouped);
void parseGroup(Decoder &decoder,vector<EffectRecord> &effectlist,
int4 groupid,bool normalstack,bool autokill,bool splitFloat);
int4 groupid,bool normalstack,bool splitFloat);
public:
ParamListStandard(void) {} ///< Construct for use with decode()
ParamListStandard(const ParamListStandard &op2); ///< Copy constructor
@ -634,7 +635,7 @@ public:
virtual bool isThisBeforeRetPointer(void) const { return thisbeforeret; }
virtual void getRangeList(AddrSpace *spc,RangeList &res) const;
virtual int4 getMaxDelay(void) const { return maxdelay; }
virtual bool isAutoKillByCall(void) const { return false; }
virtual bool isAutoKilledByCall(void) const { return autoKilledByCall; }
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};
@ -659,7 +660,6 @@ public:
virtual void assignMap(const PrototypePieces &proto,TypeFactory &typefactory,vector<ParameterPieces> &res) const;
virtual void fillinMap(ParamActive *active) const;
virtual bool possibleParam(const Address &loc,int4 size) const;
virtual bool isAutoKillByCall(void) const { return useFillinFallback; }
virtual void decode(Decoder &decoder,vector<EffectRecord> &effectlist,bool normalstack);
virtual ParamList *clone(void) const;
};
@ -995,7 +995,7 @@ public:
/// \brief Does \b this model automatically consider potential output locations as killed by call
///
/// \return \b true if output locations should be considered killed by call
bool isAutoKillByCall(void) const { return output->isAutoKillByCall(); }
bool isAutoKilledByCall(void) const { return output->isAutoKilledByCall(); }
/// \brief Is \b this a merged prototype model
///
@ -1350,7 +1350,7 @@ class FuncProto {
is_destructor = 0x400, ///< Function is an (object-oriented) destructor
has_thisptr= 0x800, ///< Function is a method with a 'this' pointer as an argument
is_override = 0x1000, ///< Set if \b this prototype is created to override a single call site
auto_killbycall = 0x2000 ///< Potential output storage should always be considered \e killed \e by \e call
auto_killedbycall = 0x2000 ///< Potential output storage should always be considered \e killed \e by \e call
};
ProtoModel *model; ///< Model of for \b this prototype
ProtoStore *store; ///< Storage interface for parameters
@ -1612,7 +1612,7 @@ public:
/// \return the active set of flags for \b this prototype
uint4 getComparableFlags(void) const { return (flags & (dotdotdot | is_constructor | is_destructor | has_thisptr )); }
bool isAutoKillByCall(void) const; ///< Is a potential output automatically considered \e killed \e by \e call
bool isAutoKilledByCall(void) const; ///< Is a potential output automatically considered \e killed \e by \e call
void encode(Encoder &encoder) const;
void decode(Decoder &decoder,Architecture *glb);

View file

@ -1470,7 +1470,7 @@ void Heritage::guardCalls(uint4 fl,const Address &addr,int4 size,vector<Varnode
ParamActive *active = fc->getActiveOutput();
int4 outputCharacter = fc->characterizeAsOutput(transAddr, size);
if (outputCharacter != ParamEntry::no_containment) {
if (effecttype != EffectRecord::killedbycall && fc->isAutoKillByCall())
if (effecttype != EffectRecord::killedbycall && fc->isAutoKilledByCall())
effecttype = EffectRecord::killedbycall;
if (outputCharacter == ParamEntry::contained_by) {
if (tryOutputOverlapGuard(fc, addr, transAddr, size, write))

View file

@ -205,8 +205,8 @@ class VarargsFilter : public QualifierFilter {
int4 firstPos; ///< Start of range to match (offset relative to first variable arg)
int4 lastPos; ///< End of range to match
public:
VarargsFilter(void) { firstPos = 0x80000000; lastPos = 0x7fffffff; }
VarargsFilter(int4 first,int4 last) { firstPos = first; lastPos = last; }
VarargsFilter(void) { firstPos = 0x80000000; lastPos = 0x7fffffff; } ///< Constructor for use with decode
VarargsFilter(int4 first,int4 last) { firstPos = first; lastPos = last; } ///< Constructor
virtual QualifierFilter *clone(void) const { return new VarargsFilter(firstPos,lastPos); }
virtual bool filter(const PrototypePieces &proto,int4 pos) const;
virtual void decode(Decoder &decoder);

View file

@ -42,6 +42,7 @@ public class ParamListStandard implements ParamList {
protected int numgroup; // Number of "groups" in this parameter convention
// protected int maxdelay;
protected boolean thisbeforeret; // Do hidden return pointers usurp the storage of the this pointer
protected boolean autoKilledByCall; // Is storage in this list automatically "killed by call"
protected boolean splitMetatype; // Are metatyped entries in separate resource sections
// protected int[] resourceStart; // The starting group for each resource section
protected ParamEntry[] entry;
@ -235,6 +236,7 @@ public class ParamListStandard implements ParamList {
if (thisbeforeret) {
encoder.writeBool(ATTRIB_THISBEFORERETPOINTER, true);
}
encoder.writeBool(ATTRIB_KILLEDBYCALL, autoKilledByCall);
if (isInput && !splitMetatype) {
encoder.writeBool(ATTRIB_SEPARATEFLOAT, false);
}
@ -298,7 +300,7 @@ public class ParamListStandard implements ParamList {
private void parseGroup(XmlPullParser parser, CompilerSpec cspec, ArrayList<ParamEntry> pe,
int groupid, boolean splitFloat) throws XmlParseException {
XmlElement el = parser.start("group");
XmlElement el = parser.start(ELEM_GROUP.name());
int basegroup = numgroup;
int count = 0;
while (parser.peek().isStart()) {
@ -327,17 +329,22 @@ public class ParamListStandard implements ParamList {
spacebase = null;
int pointermax = 0;
thisbeforeret = false;
autoKilledByCall = false;
splitMetatype = true;
XmlElement mainel = parser.start();
String attribute = mainel.getAttribute("pointermax");
String attribute = mainel.getAttribute(ATTRIB_POINTERMAX.name());
if (attribute != null) {
pointermax = SpecXmlUtils.decodeInt(attribute);
}
attribute = mainel.getAttribute("thisbeforeretpointer");
attribute = mainel.getAttribute(ATTRIB_THISBEFORERETPOINTER.name());
if (attribute != null) {
thisbeforeret = SpecXmlUtils.decodeBoolean(attribute);
}
attribute = mainel.getAttribute("separatefloat");
attribute = mainel.getAttribute(ATTRIB_KILLEDBYCALL.name());
if (attribute != null) {
autoKilledByCall = SpecXmlUtils.decodeBoolean(attribute);
}
attribute = mainel.getAttribute(ATTRIB_SEPARATEFLOAT.name());
if (attribute != null) {
splitMetatype = SpecXmlUtils.decodeBoolean(attribute);
}
@ -347,13 +354,13 @@ public class ParamListStandard implements ParamList {
if (!el.isStart()) {
break;
}
if (el.getName().equals("pentry")) {
if (el.getName().equals(ELEM_PENTRY.name())) {
parsePentry(parser, cspec, pe, numgroup, splitMetatype, false);
}
else if (el.getName().equals("group")) {
else if (el.getName().equals(ELEM_GROUP.name())) {
parseGroup(parser, cspec, pe, numgroup, splitMetatype);
}
else if (el.getName().equals("rule")) {
else if (el.getName().equals(ELEM_RULE.name())) {
break;
}
}
@ -366,7 +373,7 @@ public class ParamListStandard implements ParamList {
if (!subId.isStart()) {
break;
}
if (subId.getName().equals("rule")) {
if (subId.getName().equals(ELEM_RULE.name())) {
ModelRule rule = new ModelRule();
rule.restoreXml(parser, this);
rules.add(rule);
@ -482,6 +489,9 @@ public class ParamListStandard implements ParamList {
if (thisbeforeret != op2.thisbeforeret) {
return false;
}
if (autoKilledByCall != op2.autoKilledByCall) {
return false;
}
return true;
}