Basic multi-entry merge capability

This commit is contained in:
caheckman 2019-12-11 09:47:51 -05:00
parent 76d0f12bd3
commit b99772a784
8 changed files with 123 additions and 6 deletions

View file

@ -102,6 +102,15 @@ bool Merge::mergeTestRequired(HighVariable *high_out,HighVariable *high_in)
}
else if (high_out->isExtraOut())
return false;
if (high_in->isMapped() && high_out->isMapped()) {
Symbol *symbolIn = high_in->getSymbol();
Symbol *symbolOut = high_out->getSymbol();
if (symbolIn != (Symbol *)0 && symbolOut != (Symbol *)0) {
if (symbolIn != symbolOut) return false; // Map to different symbols
if (high_in->getSymbolOffset() != high_out->getSymbolOffset())
return false; // Map to different parts of same symbol
}
}
return true;
}
@ -151,9 +160,6 @@ bool Merge::mergeTestSpeculative(HighVariable *high_out,HighVariable *high_in)
{
if (!mergeTestAdjacent(high_out,high_in)) return false;
// Don't merge a mapped variable speculatively
if (high_out->isMapped()) return false;
if (high_in->isMapped()) return false;
// Don't merge anything with a global speculatively
if (high_out->isPersist()) return false;
if (high_in->isPersist()) return false;
@ -268,7 +274,7 @@ void Merge::mergeOpcode(OpCode opc)
vn2 = op->getIn(j);
if (!mergeTestBasic(vn2)) continue;
if (mergeTestRequired(vn1->getHigh(),vn2->getHigh()))
merge(vn1->getHigh(),vn2->getHigh(),false);
merge(vn1->getHigh(),vn2->getHigh(),true); // Treat as speculative
}
}
}
@ -798,6 +804,61 @@ void Merge::mergeMarker(void)
}
}
/// \brief Merge together Varnodes mapped to SymbolEntrys from the same Symbol
///
/// Symbols that have more than one SymbolEntry may attach to more than one Varnode.
/// These Varnodes need to be merged to properly represent a single variable.
void Merge::mergeMultiEntry(void)
{
SymbolNameTree::const_iterator iter = data.getScopeLocal()->beginMultiEntry();
SymbolNameTree::const_iterator enditer = data.getScopeLocal()->endMultiEntry();
for(;iter!=enditer;++iter) {
vector<Varnode *> mergeList;
Symbol *symbol = *iter;
int4 numEntries = symbol->numEntries();
int4 mergeCount = 0;
int4 skipCount = 0;
int4 conflictCount = 0;
for(int4 i=0;i<numEntries;++i) {
int4 prevSize = mergeList.size();
data.findLinkedVarnodes(symbol->getMapEntry(i), mergeList);
if (mergeList.size() == prevSize)
skipCount += 1; // Did not discover any Varnodes corresponding to a particular SymbolEntry
}
if (mergeList.empty()) continue;
HighVariable *high = mergeList[0]->getHigh();
Datatype *ct = high->getType();
updateHigh(high);
for(int4 i=0;i<mergeList.size();++i) {
HighVariable *newHigh = mergeList[i]->getHigh();
if (newHigh == high) continue; // Varnodes already merged
updateHigh(newHigh);
if (!mergeTestRequired(high, newHigh)) {
conflictCount += 1;
continue;
}
if (!merge(high,newHigh,false)) { // Attempt the merge
conflictCount += 1;
continue;
}
mergeCount += 1;
}
if (skipCount != 0 || conflictCount !=0) {
ostringstream s;
s << "Unable to";
if (mergeCount != 0)
s << " fully";
s << " merge symbol: " << symbol->getName();
if (skipCount > 0)
s << " -- Some instance varnodes not found.";
if (conflictCount > 0)
s << " -- Some merges are forbidden";
data.warningHeader(s.str());
}
}
}
/// \brief Speculatively merge Varnodes that are input/output to the same p-code op
///
/// If a single p-code op has an input and output HighVariable that share the same data-type,