Isolate property on Symbols

This commit is contained in:
caheckman 2019-12-13 15:45:14 -05:00
parent cdbee3fe39
commit 7fa8245f90
8 changed files with 155 additions and 23 deletions

View file

@ -232,6 +232,21 @@ bool Symbol::isNameUndefined(void) const
return ((name.size()==15)&&(0==name.compare(0,7,"$$undef"))); return ((name.size()==15)&&(0==name.compare(0,7,"$$undef")));
} }
/// If the given value is \b true, any Varnodes that map directly to \b this Symbol,
/// will not be speculatively merged with other Varnodes. (Required merges will still happen).
/// \param val is the given boolean value
void Symbol::setIsolated(bool val)
{
if (val) {
dispflags |= isolate;
flags |= Varnode::typelock; // Isolated Symbol must be typelocked
checkSizeTypeLock();
}
else
dispflags &= ~((uint4)isolate);
}
/// \return the first SymbolEntry /// \return the first SymbolEntry
SymbolEntry *Symbol::getFirstWholeMap(void) const SymbolEntry *Symbol::getFirstWholeMap(void) const
@ -262,6 +277,24 @@ SymbolEntry *Symbol::getMapEntry(const Address &addr) const
return (SymbolEntry *)0; return (SymbolEntry *)0;
} }
/// Among all the SymbolEntrys that map \b this entire Symbol, calculate
/// the position of the given SymbolEntry within the list.
/// \param entry is the given SymbolEntry
/// \return its position within the list or -1 if it is not in the list
int4 Symbol::getMapEntryPosition(const SymbolEntry *entry) const
{
int4 pos = 0;
for(int4 i=0;i<mapentry.size();++i) {
const SymbolEntry *tmp = &(*mapentry[i]);
if (tmp == entry)
return pos;
if (entry->getSize() == type->getSize())
pos += 1;
}
return -1;
}
/// A value of 0 means the base Symbol name is visible and not overridden in the given use scope. /// A value of 0 means the base Symbol name is visible and not overridden in the given use scope.
/// A value of 1 means the base name may be overridden, but the parent scope name is not. /// A value of 1 means the base name may be overridden, but the parent scope name is not.
/// The minimual number of names that distinguishes \b this Symbol uniquely within the /// The minimual number of names that distinguishes \b this Symbol uniquely within the
@ -313,18 +346,20 @@ void Symbol::saveXmlHeader(ostream &s) const
a_v_b(s,"indirectstorage",true); a_v_b(s,"indirectstorage",true);
if ((flags&Varnode::hiddenretparm)!=0) if ((flags&Varnode::hiddenretparm)!=0)
a_v_b(s,"hiddenretparm",true); a_v_b(s,"hiddenretparm",true);
if ((dispflags&isolate)!=0)
a_v_b(s,"merge",false);
int4 format = getDisplayFormat(); int4 format = getDisplayFormat();
if (format != 0) { if (format != 0) {
s << " format=\""; s << " format=\"";
if (format == Symbol::force_hex) if (format == force_hex)
s << "hex\""; s << "hex\"";
else if (format == Symbol::force_dec) else if (format == force_dec)
s << "dec\""; s << "dec\"";
else if (format == Symbol::force_char) else if (format == force_char)
s << "char\""; s << "char\"";
else if (format == Symbol::force_oct) else if (format == force_oct)
s << "oct\""; s << "oct\"";
else if (format == Symbol::force_bin) else if (format == force_bin)
s << "bin\""; s << "bin\"";
else else
s << "hex\""; s << "hex\"";
@ -355,15 +390,15 @@ void Symbol::restoreXmlHeader(const Element *el)
if (attName == "format") { if (attName == "format") {
const string &formString(el->getAttributeValue(i)); const string &formString(el->getAttributeValue(i));
if (formString == "hex") if (formString == "hex")
dispflags |= Symbol::force_hex; dispflags |= force_hex;
else if (formString == "dec") else if (formString == "dec")
dispflags |= Symbol::force_dec; dispflags |= force_dec;
else if (formString == "char") else if (formString == "char")
dispflags |= Symbol::force_char; dispflags |= force_char;
else if (formString == "oct") else if (formString == "oct")
dispflags |= Symbol::force_oct; dispflags |= force_oct;
else if (formString == "bin") else if (formString == "bin")
dispflags |= Symbol::force_bin; dispflags |= force_bin;
} }
break; break;
case 'h': case 'h':
@ -385,6 +420,14 @@ void Symbol::restoreXmlHeader(const Element *el)
flags |= Varnode::indirectstorage; flags |= Varnode::indirectstorage;
} }
break; break;
case 'm':
if (attName == "merge") {
if (!xml_readbool(el->getAttributeValue(i))) {
dispflags |= isolate;
flags |= Varnode::typelock;
}
}
break;
case 'n': case 'n':
if (attName == "name") if (attName == "name")
name = el->getAttributeValue(i); name = el->getAttributeValue(i);

View file

@ -181,7 +181,8 @@ public:
force_bin = 4, ///< Force binary printing of constant symbol force_bin = 4, ///< Force binary printing of constant symbol
force_char = 5, ///< Force integer to be printed as a character constant force_char = 5, ///< Force integer to be printed as a character constant
size_typelock = 8, ///< Only the size of the symbol is typelocked size_typelock = 8, ///< Only the size of the symbol is typelocked
isolate = 16 ///< Symbol should not speculatively merge automatically isolate = 16, ///< Symbol should not speculatively merge automatically
merge_problems = 32 ///< Set if some SymbolEntrys did not get merged
}; };
/// \brief Construct given a name and data-type /// \brief Construct given a name and data-type
Symbol(Scope *sc,const string &nm,Datatype *ct) Symbol(Scope *sc,const string &nm,Datatype *ct)
@ -203,11 +204,17 @@ public:
bool isIndirectStorage(void) const { return ((flags&Varnode::indirectstorage)!=0); } ///< Is storage really a pointer to the true Symbol bool isIndirectStorage(void) const { return ((flags&Varnode::indirectstorage)!=0); } ///< Is storage really a pointer to the true Symbol
bool isHiddenReturn(void) const { return ((flags&Varnode::hiddenretparm)!=0); } ///< Is this a reference to the function return value bool isHiddenReturn(void) const { return ((flags&Varnode::hiddenretparm)!=0); } ///< Is this a reference to the function return value
bool isNameUndefined(void) const; ///< Does \b this have an undefined name bool isNameUndefined(void) const; ///< Does \b this have an undefined name
bool isMultiEntry(void) const { return (wholeCount > 1); } ///< Does \b this have more than one \e entire mapping
bool hasMergeProblems(void) const { return ((dispflags & merge_problems)!=0); } ///< Were some SymbolEntrys not merged
void setMergeProblems(void) { dispflags |= merge_problems; } ///< Mark that some SymbolEntrys could not be merged
bool isIsolated(void) const { return ((dispflags & isolate)!=0); } ///< Return \b true if \b this is isolated from speculative merging
void setIsolated(bool val); ///< Set whether \b this Symbol should be speculatively merged
Scope *getScope(void) const { return scope; } ///< Get the scope owning \b this Symbol Scope *getScope(void) const { return scope; } ///< Get the scope owning \b this Symbol
SymbolEntry *getFirstWholeMap(void) const; ///< Get the first entire mapping of the symbol SymbolEntry *getFirstWholeMap(void) const; ///< Get the first entire mapping of the symbol
SymbolEntry *getMapEntry(const Address &addr) const; ///< Get first mapping of the symbol that contains the given Address SymbolEntry *getMapEntry(const Address &addr) const; ///< Get first mapping of the symbol that contains the given Address
int4 numEntries(void) const { return mapentry.size(); } ///< Return the number of SymbolEntrys int4 numEntries(void) const { return mapentry.size(); } ///< Return the number of SymbolEntrys
SymbolEntry *getMapEntry(int4 i) const { return &(*mapentry[i]); } ///< Return the i-th SymbolEntry for \b this Symbol SymbolEntry *getMapEntry(int4 i) const { return &(*mapentry[i]); } ///< Return the i-th SymbolEntry for \b this Symbol
int4 getMapEntryPosition(const SymbolEntry *entry) const; ///< Position of given SymbolEntry within \b this multi-entry Symbol
int4 getResolutionDepth(const Scope *useScope) const; ///< Get the number of scope names to print to resolve symbol in given context int4 getResolutionDepth(const Scope *useScope) const; ///< Get the number of scope names to print to resolve symbol in given context
void saveXmlHeader(ostream &s) const; ///< Save basic Symbol properties as XML attributes void saveXmlHeader(ostream &s) const; ///< Save basic Symbol properties as XML attributes
void restoreXmlHeader(const Element *el); ///< Restore basic Symbol properties from XML void restoreXmlHeader(const Element *el); ///< Restore basic Symbol properties from XML

View file

@ -115,6 +115,7 @@ void IfaceDecompCapability::registerCommands(IfaceStatus *status)
status->registerCom(new IfcRename(),"rename"); status->registerCom(new IfcRename(),"rename");
status->registerCom(new IfcRetype(),"retype"); status->registerCom(new IfcRetype(),"retype");
status->registerCom(new IfcRemove(),"remove"); status->registerCom(new IfcRemove(),"remove");
status->registerCom(new IfcIsolate(),"isolate");
status->registerCom(new IfcLockPrototype(),"prototype","lock"); status->registerCom(new IfcLockPrototype(),"prototype","lock");
status->registerCom(new IfcUnlockPrototype(),"prototype","unlock"); status->registerCom(new IfcUnlockPrototype(),"prototype","unlock");
status->registerCom(new IfcCommentInstr(),"comment","instruction"); status->registerCom(new IfcCommentInstr(),"comment","instruction");
@ -1057,6 +1058,32 @@ void IfcRetype::execute(istream &s)
} }
} }
void IfcIsolate::execute(istream &s)
{
string name;
s >> ws >> name;
if (name.size()==0)
throw IfaceParseError("Must specify name of symbol");
Symbol *sym;
vector<Symbol *> symList;
if (dcp->fd != (Funcdata *)0)
dcp->fd->getScopeLocal()->queryByName(name,symList);
else
dcp->conf->symboltab->getGlobalScope()->queryByName(name,symList);
if (symList.empty())
throw IfaceExecutionError("No symbol named: "+name);
if (symList.size() > 1)
throw IfaceExecutionError("More than one symbol named : "+name);
else
sym = symList[0];
sym->setIsolated(true);
}
static Varnode *iface_read_varnode(IfaceDecompData *dcp,istream &s) static Varnode *iface_read_varnode(IfaceDecompData *dcp,istream &s)
{ // Return varnode identified by input stream { // Return varnode identified by input stream

View file

@ -304,6 +304,11 @@ public:
virtual void execute(istream &s); virtual void execute(istream &s);
}; };
class IfcIsolate : public IfaceDecompCommand {
public:
virtual void execute(istream &s);
};
class IfcRemove : public IfaceDecompCommand { class IfcRemove : public IfaceDecompCommand {
public: public:
virtual void execute(istream &s); virtual void execute(istream &s);

View file

@ -102,15 +102,15 @@ bool Merge::mergeTestRequired(HighVariable *high_out,HighVariable *high_in)
} }
else if (high_out->isExtraOut()) else if (high_out->isExtraOut())
return false; return false;
if (high_in->isMapped() && high_out->isMapped()) {
Symbol *symbolIn = high_in->getSymbol(); Symbol *symbolIn = high_in->getSymbol();
Symbol *symbolOut = high_out->getSymbol(); Symbol *symbolOut = high_out->getSymbol();
if (symbolIn != (Symbol *) 0 && symbolOut != (Symbol *) 0) { if (symbolIn != (Symbol *) 0 && symbolOut != (Symbol *) 0) {
if (symbolIn != symbolOut) return false; // Map to different symbols if (symbolIn != symbolOut)
return false; // Map to different symbols
if (high_in->getSymbolOffset() != high_out->getSymbolOffset()) if (high_in->getSymbolOffset() != high_out->getSymbolOffset())
return false; // Map to different parts of same symbol return false; // Map to different parts of same symbol
} }
}
return true; return true;
} }
@ -145,6 +145,14 @@ bool Merge::mergeTestAdjacent(HighVariable *high_out,HighVariable *high_in)
Varnode *vn = high_in->getInputVarnode(); Varnode *vn = high_in->getInputVarnode();
if (vn->isIllegalInput()&&(!vn->isIndirectOnly())) return false; if (vn->isIllegalInput()&&(!vn->isIndirectOnly())) return false;
} }
Symbol *symbol = high_in->getSymbol();
if (symbol != (Symbol *)0)
if (symbol->isIsolated())
return false;
symbol = high_out->getSymbol();
if (symbol != (Symbol *)0)
if (symbol->isIsolated())
return false;
return true; return true;
} }
@ -837,10 +845,14 @@ void Merge::mergeMultiEntry(void)
if (newHigh == high) continue; // Varnodes already merged if (newHigh == high) continue; // Varnodes already merged
updateHigh(newHigh); updateHigh(newHigh);
if (!mergeTestRequired(high, newHigh)) { if (!mergeTestRequired(high, newHigh)) {
symbol->setMergeProblems();
newHigh->setUnmerged();
conflictCount += 1; conflictCount += 1;
continue; continue;
} }
if (!merge(high,newHigh,false)) { // Attempt the merge if (!merge(high,newHigh,false)) { // Attempt the merge
symbol->setMergeProblems();
newHigh->setUnmerged();
conflictCount += 1; conflictCount += 1;
continue; continue;
} }

View file

@ -1639,6 +1639,21 @@ void PrintC::pushSymbol(const Symbol *sym,const Varnode *vn,const PcodeOp *op)
else else
tokenColor = EmitXml::var_color; tokenColor = EmitXml::var_color;
// FIXME: resolve scopes // FIXME: resolve scopes
if (sym->hasMergeProblems() && vn != (Varnode *)0) {
HighVariable *high = vn->getHigh();
if (high->isUnmerged()) {
ostringstream s;
s << sym->getName();
SymbolEntry *entry = high->getSymbolEntry();
if (entry != (SymbolEntry *)0) {
s << '$' << dec << entry->getSymbol()->getMapEntryPosition(entry);
}
else
s << "$$";
pushAtom(Atom(s.str(),vartoken,tokenColor,op,vn));
return;
}
}
pushAtom(Atom(sym->getName(),vartoken,tokenColor,op,vn)); pushAtom(Atom(sym->getName(),vartoken,tokenColor,op,vn));
} }
@ -2180,14 +2195,19 @@ bool PrintC::emitScopeVarDecls(const Scope *scope,int4 cat)
MapIterator iter = scope->begin(); MapIterator iter = scope->begin();
MapIterator enditer = scope->end(); MapIterator enditer = scope->end();
for(;iter!=enditer;++iter) { for(;iter!=enditer;++iter) {
if ((*iter)->isPiece()) continue; // Don't do a partial entry const SymbolEntry *entry = *iter;
Symbol *sym = (*iter)->getSymbol(); if (entry->isPiece()) continue; // Don't do a partial entry
Symbol *sym = entry->getSymbol();
if (sym->getCategory() != cat) continue; if (sym->getCategory() != cat) continue;
if (sym->getName().size() == 0) continue; if (sym->getName().size() == 0) continue;
if (dynamic_cast<FunctionSymbol *>(sym) != (FunctionSymbol *)0) if (dynamic_cast<FunctionSymbol *>(sym) != (FunctionSymbol *)0)
continue; continue;
if (dynamic_cast<LabSymbol *>(sym) != (LabSymbol *)0) if (dynamic_cast<LabSymbol *>(sym) != (LabSymbol *)0)
continue; continue;
if (sym->isMultiEntry()) {
if (sym->getFirstWholeMap() != entry)
continue; // Only emit the first SymbolEntry for declaration of multi-entry Symbol
}
notempty = true; notempty = true;
emitVarDeclStatement(sym); emitVarDeclStatement(sym);
} }

View file

@ -262,6 +262,20 @@ void HighVariable::remove(Varnode *vn)
} }
} }
/// Assuming there is a Symbol attached to \b this, run through the Varnode members
/// until we find one with a SymbolEntry corresponding to the Symbol and return it.
/// \return the SymbolEntry that mapped the Symbol to \b this or null if no Symbol is attached
SymbolEntry *HighVariable::getSymbolEntry(void) const
{
for(int4 i=0;i<inst.size();++i) {
SymbolEntry *entry = inst[i]->getSymbolEntry();
if (entry != (SymbolEntry *)0 && entry->getSymbol() == symbol)
return entry;
}
return (SymbolEntry *)0;
}
/// The data-type its dirtying mechanism is disabled. The data-type will not change, unless /// The data-type its dirtying mechanism is disabled. The data-type will not change, unless
/// this method is called again. /// this method is called again.
/// \param tp is the data-type to set /// \param tp is the data-type to set

View file

@ -49,7 +49,8 @@ public:
symboldirty = 8, ///< The symbol attachment is dirty symboldirty = 8, ///< The symbol attachment is dirty
copy_in1 = 8, ///< There exists at least 1 COPY into \b this HighVariable from other HighVariables copy_in1 = 8, ///< There exists at least 1 COPY into \b this HighVariable from other HighVariables
copy_in2 = 16, ///< There exists at least 2 COPYs into \b this HighVariable from other HighVariables copy_in2 = 16, ///< There exists at least 2 COPYs into \b this HighVariable from other HighVariables
type_finalized = 32 ///< Set if a final data-type is locked in and dirtying is disabled type_finalized = 32, ///< Set if a final data-type is locked in and dirtying is disabled
unmerged = 64 ///< Set if part of a multi-entry Symbol but did not get merged with other SymbolEntrys
}; };
private: private:
friend class Varnode; friend class Varnode;
@ -79,10 +80,12 @@ private:
void flagsDirty(void) const { highflags |= HighVariable::flagsdirty; } ///< Mark the boolean properties as \e dirty void flagsDirty(void) const { highflags |= HighVariable::flagsdirty; } ///< Mark the boolean properties as \e dirty
void coverDirty(void) const { highflags |= HighVariable::coverdirty; } ///< Mark the cover as \e dirty void coverDirty(void) const { highflags |= HighVariable::coverdirty; } ///< Mark the cover as \e dirty
void typeDirty(void) const { highflags |= HighVariable::typedirty; } ///< Mark the data-type as \e dirty void typeDirty(void) const { highflags |= HighVariable::typedirty; } ///< Mark the data-type as \e dirty
void setUnmerged(void) const { highflags |= unmerged; } ///< Mark \b this as having merge problems
public: public:
HighVariable(Varnode *vn); ///< Construct a HighVariable with a single member Varnode HighVariable(Varnode *vn); ///< Construct a HighVariable with a single member Varnode
Datatype *getType(void) const { updateType(); return type; } ///< Get the data-type Datatype *getType(void) const { updateType(); return type; } ///< Get the data-type
Symbol *getSymbol(void) const { updateSymbol(); return symbol; } ///< Get the Symbol associated with \b this Symbol *getSymbol(void) const { updateSymbol(); return symbol; } ///< Get the Symbol associated with \b this or null
SymbolEntry *getSymbolEntry(void) const; /// Get the SymbolEntry mapping to \b this or null
int4 getSymbolOffset(void) const { return symboloffset; } ///< Get the Symbol offset associated with \b this int4 getSymbolOffset(void) const { return symboloffset; } ///< Get the Symbol offset associated with \b this
int4 numInstances(void) const { return inst.size(); } ///< Get the number of member Varnodes \b this has int4 numInstances(void) const { return inst.size(); } ///< Get the number of member Varnodes \b this has
Varnode *getInstance(int4 i) const { return inst[i]; } ///< Get the i-th member Varnode Varnode *getInstance(int4 i) const { return inst[i]; } ///< Get the i-th member Varnode
@ -111,6 +114,7 @@ public:
void setMark(void) const { flags |= Varnode::mark; } ///< Set the mark on this variable void setMark(void) const { flags |= Varnode::mark; } ///< Set the mark on this variable
void clearMark(void) const { flags &= ~Varnode::mark; } ///< Clear the mark on this variable void clearMark(void) const { flags &= ~Varnode::mark; } ///< Clear the mark on this variable
bool isMark(void) const { return ((flags&Varnode::mark)!=0); } ///< Return \b true if \b this is marked bool isMark(void) const { return ((flags&Varnode::mark)!=0); } ///< Return \b true if \b this is marked
bool isUnmerged(void) const { return ((highflags&unmerged)!=0); } ///< Return \b true if \b this has merge problems
/// \brief Determine if \b this HighVariable has an associated cover. /// \brief Determine if \b this HighVariable has an associated cover.
/// ///