mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Refactor ParamEntry look-up allowing "contained by" discovery
This commit is contained in:
parent
ef12c20829
commit
12d3da029b
13 changed files with 690 additions and 286 deletions
|
@ -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 ¶mtrial(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 ¶mtrial(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 ¶mtrial(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 ¶mtrial(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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue