Refactor ParamEntry look-up allowing "contained by" discovery

This commit is contained in:
caheckman 2019-07-08 13:54:03 -04:00
parent ef12c20829
commit 12d3da029b
13 changed files with 690 additions and 286 deletions

View file

@ -71,6 +71,19 @@ bool ParamEntry::contains(const ParamEntry &op2) const
return true;
}
/// \param addr is the starting address of the potential containing range
/// \param sz is the number of bytes in the range
/// \return \b true if the entire ParamEntry fits inside the range
bool ParamEntry::containedBy(const Address &addr,int4 sz) const
{
if (spaceid != addr.getSpace()) return false;
if (addressbase < addr.getOffset()) return false;
uintb entryoff = addressbase + size-1;
uintb rangeoff = addr.getOffset() + sz-1;
return (entryoff <= rangeoff);
}
/// Check if the given memory range is contained in \b this.
/// If it is contained, return the endian aware offset of the containment.
/// I.e. if the least significant byte of the given range falls on the least significant
@ -379,17 +392,18 @@ void ParamEntry::restoreXml(const Element *el,const AddrSpaceManager *manage,boo
/// what portion(s) of the joined parameter are overlapped. This method sets flags on \b this
/// to indicate the overlap.
/// \param entry is the full parameter list to check for overlaps with \b this
void ParamEntry::extraChecks(vector<ParamEntry> &entry)
void ParamEntry::extraChecks(list<ParamEntry> &entry)
{
if (joinrec == (JoinRecord *)0) return; // Nothing to do if not multiprecision
if (joinrec->numPieces() != 2) return;
const VarnodeData &highPiece(joinrec->getPiece(0));
bool seenOnce = false;
for(int4 i=0;i<entry.size();++i) { // Search for high piece, used as whole/low in another entry
AddrSpace *spc = entry[i].getSpace();
uintb off = entry[i].getBase();
int4 sz = entry[i].getSize();
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) { // Search for high piece, used as whole/low in another entry
AddrSpace *spc = (*iter).getSpace();
uintb off = (*iter).getBase();
int4 sz = (*iter).getSize();
if ((highPiece.offset == off)&&(highPiece.space == spc)&&(highPiece.size == sz)) {
if (seenOnce) throw LowlevelError("Extra check hits twice");
seenOnce = true;
@ -410,21 +424,76 @@ ParamListStandard::ParamListStandard(const ParamListStandard &op2)
pointermax = op2.pointermax;
thisbeforeret = op2.thisbeforeret;
nonfloatgroup = op2.nonfloatgroup;
populateResolver();
}
ParamListStandard::~ParamListStandard(void)
{
for(int4 i=0;i<resolverMap.size();++i) {
ParamEntryResolver *resolver = resolverMap[i];
if (resolver != (ParamEntryResolver *)0)
delete resolver;
}
}
/// Find the (first) entry containing the given memory range
/// \param loc is the starting address of the range
/// \param size is the number of bytes in the range
/// \return the index of the matching ParamEntry or -1 if none exists
int4 ParamListStandard::findEntry(const Address &loc,int4 size) const
/// \return the pointer to the matching ParamEntry or null if no match exists
const ParamEntry *ParamListStandard::findEntry(const Address &loc,int4 size) const
{
for(int4 i=0;i<entry.size();++i) {
if (entry[i].getMinSize() > size) continue;
if (entry[i].justifiedContain(loc,size)==0) // Make sure the range is properly justified in entry
return i;
int4 index = loc.getSpace()->getIndex();
if (index >= resolverMap.size())
return (const ParamEntry *)0;
ParamEntryResolver *resolver = resolverMap[index];
if (resolver == (ParamEntryResolver *)0)
return (const ParamEntry *)0;
pair<ParamEntryResolver::const_iterator,ParamEntryResolver::const_iterator> res;
res = resolver->find(loc.getOffset());
while(res.first != res.second) {
const ParamEntry *testEntry = (*res.first).getParamEntry();
++res.first;
if (testEntry->getMinSize() > size) continue;
if (testEntry->justifiedContain(loc,size)==0) // Make sure the range is properly justified in entry
return testEntry;
}
return -1;
return (const ParamEntry *)0;
}
int4 ParamListStandard::characterizeAsParam(const Address &loc,int4 size) const
{
int4 index = loc.getSpace()->getIndex();
if (index >= resolverMap.size())
return 0;
ParamEntryResolver *resolver = resolverMap[index];
if (resolver == (ParamEntryResolver *)0)
return 0;
pair<ParamEntryResolver::const_iterator,ParamEntryResolver::const_iterator> iterpair;
iterpair = resolver->find(loc.getOffset());
int4 res = 0;
while(iterpair.first != iterpair.second) {
const ParamEntry *testEntry = (*iterpair.first).getParamEntry();
if (testEntry->getMinSize() <= size && testEntry->justifiedContain(loc, size)==0)
return 1;
if (testEntry->containedBy(loc, size))
res = 2;
++iterpair.first;
}
if (res != 2 && iterpair.first != resolver->end()) {
iterpair.second = resolver->find_end(loc.getOffset() + (size-1));
while(iterpair.first != iterpair.second) {
const ParamEntry *testEntry = (*iterpair.first).getParamEntry();
if (testEntry->containedBy(loc, size)) {
res = 2;
break;
}
++iterpair.first;
}
}
return res;
}
/// Given the next data-type and the status of previously allocated slots,
@ -437,17 +506,19 @@ int4 ParamListStandard::findEntry(const Address &loc,int4 size) const
Address ParamListStandard::assignAddress(const Datatype *tp,vector<int4> &status) const
{
for(int4 i=0;i<entry.size();++i) {
int4 grp = entry[i].getGroup();
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
const ParamEntry &curEntry( *iter );
int4 grp = curEntry.getGroup();
if (status[grp]<0) continue;
if ((entry[i].getType() != TYPE_UNKNOWN)&&
tp->getMetatype() != entry[i].getType())
if ((curEntry.getType() != TYPE_UNKNOWN)&&
tp->getMetatype() != curEntry.getType())
continue; // Wrong type
Address res = entry[i].getAddrBySlot(status[grp],tp->getSize());
Address res = curEntry.getAddrBySlot(status[grp],tp->getSize());
if (res.isInvalid()) continue; // If -tp- doesn't fit an invalid address is returned
if (entry[i].isExclusion()) {
int4 maxgrp = grp + entry[i].getGroupSize();
if (curEntry.isExclusion()) {
int4 maxgrp = grp + curEntry.getGroupSize();
for(int4 j=grp;j<maxgrp;++j) // For an exclusion entry
status[j] = -1; // some number of groups are taken up
}
@ -517,27 +588,26 @@ void ParamListStandard::buildTrialMap(ParamActive *active) const
for(int4 i=0;i<active->getNumTrials();++i) {
ParamTrial &paramtrial(active->getTrial(i));
int4 entslot = findEntry(paramtrial.getAddress(),paramtrial.getSize());
const ParamEntry *entrySlot = findEntry(paramtrial.getAddress(),paramtrial.getSize());
// Note: if a trial is "definitely not used" but there is a matching entry,
// we still include it in the map
if (entslot == -1)
if (entrySlot == (const ParamEntry *)0)
paramtrial.markNoUse();
else {
const ParamEntry *curentry = &(entry[entslot]);
paramtrial.setEntry( curentry, 0 ); // Keep track of entry recovered for this trial
paramtrial.setEntry( entrySlot, 0 ); // Keep track of entry recovered for this trial
if (curentry->getType() == TYPE_FLOAT)
if (entrySlot->getType() == TYPE_FLOAT)
seenfloattrial = true;
else
seeninttrial = true;
// Make sure we list that the entries group is marked
int4 grp = curentry->getGroup();
int4 grp = entrySlot->getGroup();
while(hitlist.size() <= grp)
hitlist.push_back((const ParamEntry *)0);
const ParamEntry *lastentry = hitlist[grp];
if (lastentry == (const ParamEntry *)0)
hitlist[grp] = curentry; // This is the first hit for this group
hitlist[grp] = entrySlot; // This is the first hit for this group
}
}
@ -548,8 +618,9 @@ void ParamListStandard::buildTrialMap(ParamActive *active) const
const ParamEntry *curentry = hitlist[i];
if (curentry == (const ParamEntry *)0) {
for(int4 j=0;j<entry.size();++j) {
curentry = &entry[j];
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
curentry = &(*iter);
if (curentry->getGroup() == i) break; // Find first entry of the missing group
}
if ((!seenfloattrial)&&(curentry->getType()==TYPE_FLOAT))
@ -749,13 +820,43 @@ void ParamListStandard::calcDelay(void)
{
maxdelay = 0;
for(int4 i=0;i<entry.size();++i) {
int4 delay = entry[i].getSpace()->getDelay();
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
int4 delay = (*iter).getSpace()->getDelay();
if (delay > maxdelay)
maxdelay = delay;
}
}
/// Enter all the ParamEntry objects into an interval map (based on address space)
void ParamListStandard::populateResolver(void)
{
int4 maxid = -1;
list<ParamEntry>::iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
int4 id = (*iter).getSpace()->getIndex();
if (id > maxid)
maxid = id;
}
resolverMap.resize(maxid+1, (ParamEntryResolver *)0);
int4 position = 0;
for(iter=entry.begin();iter!=entry.end();++iter) {
ParamEntry *paramEntry = &(*iter);
int4 spaceId = paramEntry->getSpace()->getIndex();
ParamEntryResolver *resolver = resolverMap[spaceId];
if (resolver == (ParamEntryResolver *)0) {
resolver = new ParamEntryResolver();
resolverMap[spaceId] = resolver;
}
uintb first = paramEntry->getBase();
uintb last = first + (paramEntry->getSize() - 1);
ParamEntryResolver::inittype initData(position,paramEntry);
position += 1;
resolver->insert(initData,first,last);
}
}
void ParamListStandard::fillinMap(ParamActive *active) const
{
@ -782,25 +883,24 @@ void ParamListStandard::fillinMap(ParamActive *active) const
bool ParamListStandard::checkJoin(const Address &hiaddr,int4 hisize,const Address &loaddr,int4 losize) const
{
int4 enthi = findEntry(hiaddr,hisize);
if (enthi < 0) return false;
int4 entlo = findEntry(loaddr,losize);
if (entlo < 0) return false;
const ParamEntry &entryhi( entry[ enthi ] );
const ParamEntry &entrylo( entry[ entlo ] );
if (entryhi.getGroup() == entrylo.getGroup()) {
if (entryhi.isExclusion()||entrylo.isExclusion()) return false;
const ParamEntry *entryHi = findEntry(hiaddr,hisize);
if (entryHi == (const ParamEntry *)0) return false;
const ParamEntry *entryLo = findEntry(loaddr,losize);
if (entryLo == (const ParamEntry *)0) return false;
if (entryHi->getGroup() == entryLo->getGroup()) {
if (entryHi->isExclusion()||entryLo->isExclusion()) return false;
if (!hiaddr.isContiguous(hisize,loaddr,losize)) return false;
if ((hiaddr.getOffset() % entryhi.getAlign()) != 0) return false;
if ((loaddr.getOffset() % entrylo.getAlign()) != 0) return false;
if ((hiaddr.getOffset() % entryHi->getAlign()) != 0) return false;
if ((loaddr.getOffset() % entryLo->getAlign()) != 0) return false;
return true;
}
else {
int4 sizesum = hisize + losize;
for(int4 i=0;i<entry.size();++i) {
if (entry[i].getSize() < sizesum) continue;
if (entry[i].justifiedContain(loaddr,losize)!=0) continue;
if (entry[i].justifiedContain(hiaddr,hisize)!=losize) continue;
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
if ((*iter).getSize() < sizesum) continue;
if ((*iter).justifiedContain(loaddr,losize)!=0) continue;
if ((*iter).justifiedContain(hiaddr,hisize)!=losize) continue;
return true;
}
}
@ -812,44 +912,77 @@ bool ParamListStandard::checkSplit(const Address &loc,int4 size,int4 splitpoint)
{
Address loc2 = loc + splitpoint;
int4 size2 = size - splitpoint;
int4 entnum = findEntry(loc,splitpoint);
if (entnum == -1) return false;
entnum = findEntry(loc2,size2);
if (entnum == -1) return false;
const ParamEntry *entryNum = findEntry(loc,splitpoint);
if (entryNum == (const ParamEntry *)0) return false;
entryNum = findEntry(loc2,size2);
if (entryNum == (const ParamEntry *)0) return false;
return true;
}
bool ParamListStandard::possibleParam(const Address &loc,int4 size) const
{
return (-1 != findEntry(loc,size));
return ((const ParamEntry *)0 != findEntry(loc,size));
}
bool ParamListStandard::possibleParamWithSlot(const Address &loc,int4 size,int4 &slot,int4 &slotsize) const
{
int4 num = findEntry(loc,size);
if (num == -1) return false;
const ParamEntry &curentry( entry[num] );
slot = curentry.getSlot(loc,0);
if (curentry.isExclusion()) {
slotsize = curentry.getGroupSize();
const ParamEntry *entryNum = findEntry(loc,size);
if (entryNum == (const ParamEntry *)0) return false;
slot = entryNum->getSlot(loc,0);
if (entryNum->isExclusion()) {
slotsize = entryNum->getGroupSize();
}
else {
slotsize = ((size-1) / curentry.getAlign()) + 1;
slotsize = ((size-1) / entryNum->getAlign()) + 1;
}
return true;
}
bool ParamListStandard::getBiggestContainedParam(const Address &loc,int4 size,VarnodeData &res) const
{
int4 index = loc.getSpace()->getIndex();
if (index >= resolverMap.size())
return false;
ParamEntryResolver *resolver = resolverMap[index];
if (resolver == (ParamEntryResolver *)0)
return false;
const ParamEntry *maxEntry = (const ParamEntry *)0;
ParamEntryResolver::const_iterator iter = resolver->find_begin(loc.getOffset());
ParamEntryResolver::const_iterator enditer = resolver->find_end(loc.getOffset() + (size-1));
while(iter != enditer) {
const ParamEntry *testEntry = (*iter).getParamEntry();
++iter;
if (testEntry->containedBy(loc, size)) {
if (maxEntry == (const ParamEntry *)0)
maxEntry = testEntry;
else if (testEntry->getSize() > maxEntry->getSize())
maxEntry = testEntry;
}
}
if (!maxEntry->isExclusion())
return false;
if (maxEntry != (const ParamEntry *)0) {
res.space = maxEntry->getSpace();
res.offset = maxEntry->getBase();
res.size = maxEntry->getSize();
return true;
}
return false;
}
bool ParamListStandard::unjustifiedContainer(const Address &loc,int4 size,VarnodeData &res) const
{
for(int4 i=0;i<entry.size();++i) {
if (entry[i].getMinSize() > size) continue;
int4 just = entry[i].justifiedContain(loc,size);
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
if ((*iter).getMinSize() > size) continue;
int4 just = (*iter).justifiedContain(loc,size);
if (just < 0) continue;
if (just == 0) return false;
entry[i].getContainer(loc,size,res);
(*iter).getContainer(loc,size,res);
return true;
}
return false;
@ -858,9 +991,10 @@ bool ParamListStandard::unjustifiedContainer(const Address &loc,int4 size,Varnod
OpCode ParamListStandard::assumedExtension(const Address &addr,int4 size,VarnodeData &res) const
{
for(int4 i=0;i<entry.size();++i) {
if (entry[i].getMinSize() > size) continue;
OpCode ext = entry[i].assumedExtension(addr,size,res);
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
if ((*iter).getMinSize() > size) continue;
OpCode ext = (*iter).assumedExtension(addr,size,res);
if (ext != CPUI_COPY)
return ext;
}
@ -870,11 +1004,11 @@ OpCode ParamListStandard::assumedExtension(const Address &addr,int4 size,Varnode
void ParamListStandard::getRangeList(AddrSpace *spc,RangeList &res) const
{
for(int4 i=0;i<entry.size();++i) {
const ParamEntry &pentry( entry[i] );
if (pentry.getSpace() != spc) continue;
uintb baseoff = pentry.getBase();
uintb endoff = baseoff + pentry.getSize() - 1;
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
if ((*iter).getSpace() != spc) continue;
uintb baseoff = (*iter).getBase();
uintb endoff = baseoff + (*iter).getSize() - 1;
res.insertRange(spc,baseoff,endoff);
}
}
@ -932,6 +1066,7 @@ void ParamListStandard::restoreXml(const Element *el,const AddrSpaceManager *man
}
}
calcDelay();
populateResolver();
}
ParamList *ParamListStandard::clone(void) const
@ -978,13 +1113,14 @@ void ParamListStandardOut::fillinMap(ParamActive *active) const
{
if (active->getNumTrials() == 0) return; // No trials to check
int4 bestentry = -1;
const ParamEntry *bestentry = (const ParamEntry *)0;
int4 bestcover = 0;
type_metatype bestmetatype = TYPE_PTR;
// Find entry which is best covered by the active trials
for(int4 i=0;i<entry.size();++i) {
const ParamEntry *curentry = &(entry[i]);
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
const ParamEntry *curentry = &(*iter);
bool putativematch = false;
for(int4 j=0;j<active->getNumTrials();++j) { // Evaluate all trials in terms of current ParamEntry
ParamTrial &paramtrial(active->getTrial(j));
@ -1022,24 +1158,23 @@ void ParamListStandardOut::fillinMap(ParamActive *active) const
// Prefer a more generic type restriction if we have it
// prefer the larger coverage
if ((k==active->getNumTrials())&&((curentry->getType() > bestmetatype)||(offmatch > bestcover))) {
bestentry = i;
bestentry = curentry;
bestcover = offmatch;
bestmetatype = curentry->getType();
}
}
if (bestentry==-1) {
if (bestentry==(const ParamEntry *)0) {
for(int4 i=0;i<active->getNumTrials();++i)
active->getTrial(i).markNoUse();
}
else {
const ParamEntry *curentry = &(entry[bestentry]);
for(int4 i=0;i<active->getNumTrials();++i) {
ParamTrial &paramtrial(active->getTrial(i));
if (paramtrial.isActive()) {
int4 res = curentry->justifiedContain(paramtrial.getAddress(),paramtrial.getSize());
int4 res = bestentry->justifiedContain(paramtrial.getAddress(),paramtrial.getSize());
if (res >= 0) {
paramtrial.markUsed(); // Only actives are ever marked used
paramtrial.setEntry(curentry,res);
paramtrial.setEntry(bestentry,res);
}
else {
paramtrial.markNoUse();
@ -1058,8 +1193,9 @@ void ParamListStandardOut::fillinMap(ParamActive *active) const
bool ParamListStandardOut::possibleParam(const Address &loc,int4 size) const
{
for(int4 i=0;i<entry.size();++i) {
if (entry[i].justifiedContain(loc,size)>=0)
list<ParamEntry>::const_iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
if ((*iter).justifiedContain(loc,size)>=0)
return true;
}
return false;
@ -1070,8 +1206,9 @@ void ParamListStandardOut::restoreXml(const Element *el,const AddrSpaceManager *
{
ParamListStandard::restoreXml(el,manage,effectlist,normalstack);
// Check for double precision entries
for(int4 i=0;i<entry.size();++i)
entry[i].extraChecks(entry);
list<ParamEntry>::iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter)
(*iter).extraChecks(entry);
}
ParamList *ParamListStandardOut::clone(void) const
@ -1089,12 +1226,11 @@ void ParamListRegister::fillinMap(ParamActive *active) const
// Mark anything active as used
for(int4 i=0;i<active->getNumTrials();++i) {
ParamTrial &paramtrial(active->getTrial(i));
int4 entslot = findEntry(paramtrial.getAddress(),paramtrial.getSize());
if (entslot == -1) // There may be no matching entry (if the model was recovered late)
const ParamEntry *entrySlot = findEntry(paramtrial.getAddress(),paramtrial.getSize());
if (entrySlot == (const ParamEntry *)0) // There may be no matching entry (if the model was recovered late)
paramtrial.markNoUse();
else {
const ParamEntry *curentry = &(entry[entslot]);
paramtrial.setEntry( curentry,0 ); // Keep track of entry recovered for this trial
paramtrial.setEntry( entrySlot,0 ); // Keep track of entry recovered for this trial
if (paramtrial.isActive())
paramtrial.markUsed();
}
@ -1123,30 +1259,31 @@ void ParamListMerged::foldIn(const ParamListStandard &op2)
}
if ((spacebase != op2.getSpacebase())&&(op2.getSpacebase() != (AddrSpace *)0))
throw LowlevelError("Cannot merge prototype models with different stacks");
for(int4 i=0;i<op2.getEntry().size();++i) {
const ParamEntry &opentry( op2.getEntry()[i] );
int4 j;
list<ParamEntry>::const_iterator iter2;
for(iter2=op2.getEntry().begin();iter2!=op2.getEntry().end();++iter2) {
const ParamEntry &opentry( *iter2 );
int4 typeint = 0;
for(j=0;j<entry.size();++j) {
if (entry[j].contains(opentry)) {
list<ParamEntry>::iterator iter;
for(iter=entry.begin();iter!=entry.end();++iter) {
if ((*iter).contains(opentry)) {
typeint = 2;
break;
}
if (opentry.contains( entry[j] )) {
if (opentry.contains( *iter )) {
typeint = 1;
break;
}
}
if (typeint==2) {
if (entry[j].getMinSize() != opentry.getMinSize())
if ((*iter).getMinSize() != opentry.getMinSize())
typeint = 0;
}
else if (typeint == 1) {
if (entry[j].getMinSize() != opentry.getMinSize())
if ((*iter).getMinSize() != opentry.getMinSize())
typeint = 0;
else
entry[j] = opentry; // Replace with the containing entry
*iter = opentry; // Replace with the containing entry
}
if (typeint == 0)
entry.push_back(opentry);
@ -2114,6 +2251,8 @@ void ProtoModelMerged::restoreXml(const Element *el)
foldIn(mymodel);
modellist.push_back(mymodel);
}
((ParamListMerged *)input)->finalize();
((ParamListMerged *)output)->finalize();
}
void ParameterBasic::setTypeLock(bool val)
@ -3239,6 +3378,44 @@ const VarnodeData &FuncProto::getLikelyTrash(int4 i) const
return likelytrash[i];
}
/// \brief Decide whether a given storage location could be, or could hold, an input parameter
///
/// If the input is locked, check if the location overlaps one of the current parameters.
/// Otherwise, check if the location overlaps an entry in the prototype model.
/// Return:
/// - 0 if the location neither contains or is contained by a parameter storage location
/// - 1 if the location is contained by a parameter storage location
/// - 2 if the location contains a parameter storage location
/// \param addr is the starting address of the given storage location
/// \param size is the number of bytes in the storage
/// \return the characterization code
int4 FuncProto::characterizeAsInputParam(const Address &addr,int4 size) const
{
if (!isDotdotdot()) { // If the proto is varargs, go straight to the model
if ((flags&voidinputlock)!=0) return 0;
int4 num = numParams();
if (num > 0) {
bool locktest = false; // Have tested against locked symbol
int4 characterCode = 0;
for(int4 i=0;i<num;++i) {
ProtoParameter *param = getParam(i);
if (!param->isTypeLocked()) continue;
locktest = true;
Address iaddr = param->getAddress();
// If the parameter already exists, the varnode must be justified in the parameter relative
// to the endianness of the space, irregardless of the forceleft flag
if (iaddr.justifiedContain(param->getSize(),addr,size,false)==0)
return 1;
if (iaddr.containedBy(param->getSize(), addr, size))
characterCode = 2;
}
if (locktest) return characterCode;
}
}
return model->characterizeAsInputParam(addr, size);
}
/// \brief Decide whether a given storage location could be an input parameter
///
/// If the input is locked, check if the location matches one of the current parameters.
@ -3336,6 +3513,41 @@ bool FuncProto::unjustifiedInputParam(const Address &addr,int4 size,VarnodeData
return model->unjustifiedInputParam(addr,size,res);
}
/// \brief Pass-back the biggest input parameter contained within the given range
///
/// \param loc is the starting address of the given range
/// \param size is the number of bytes in the range
/// \param res will hold the parameter storage description being passed back
/// \return \b true if there is at least one parameter contained in the range
bool FuncProto::getBiggestContainedInputParam(const Address &loc,int4 size,VarnodeData &res) const
{
if (!isDotdotdot()) { // If the proto is varargs, go straight to the model
if ((flags&voidinputlock)!=0) return false;
int4 num = numParams();
if (num > 0) {
bool locktest = false; // Have tested against locked symbol
res.size = 0;
for(int4 i=0;i<num;++i) {
ProtoParameter *param = getParam(i);
if (!param->isTypeLocked()) continue;
locktest = true;
Address iaddr = param->getAddress();
if (iaddr.containedBy(param->getSize(), loc, size)) {
if (param->getSize() > res.size) {
res.space = iaddr.getSpace();
res.offset = iaddr.getOffset();
res.size = param->getSize();
}
}
}
if (locktest)
return (res.size == 0);
}
}
return model->getBiggestContainedInputParam(loc,size,res);
}
/// \brief Decide if \b this can be safely restricted to match another prototype
///
/// Do \b this and another given function prototype share enough of