mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Isolate property on Symbols
This commit is contained in:
parent
cdbee3fe39
commit
7fa8245f90
8 changed files with 155 additions and 23 deletions
|
@ -232,6 +232,21 @@ bool Symbol::isNameUndefined(void) const
|
|||
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
|
||||
SymbolEntry *Symbol::getFirstWholeMap(void) const
|
||||
|
||||
|
@ -262,6 +277,24 @@ SymbolEntry *Symbol::getMapEntry(const Address &addr) const
|
|||
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 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
|
||||
|
@ -313,18 +346,20 @@ void Symbol::saveXmlHeader(ostream &s) const
|
|||
a_v_b(s,"indirectstorage",true);
|
||||
if ((flags&Varnode::hiddenretparm)!=0)
|
||||
a_v_b(s,"hiddenretparm",true);
|
||||
if ((dispflags&isolate)!=0)
|
||||
a_v_b(s,"merge",false);
|
||||
int4 format = getDisplayFormat();
|
||||
if (format != 0) {
|
||||
s << " format=\"";
|
||||
if (format == Symbol::force_hex)
|
||||
if (format == force_hex)
|
||||
s << "hex\"";
|
||||
else if (format == Symbol::force_dec)
|
||||
else if (format == force_dec)
|
||||
s << "dec\"";
|
||||
else if (format == Symbol::force_char)
|
||||
else if (format == force_char)
|
||||
s << "char\"";
|
||||
else if (format == Symbol::force_oct)
|
||||
else if (format == force_oct)
|
||||
s << "oct\"";
|
||||
else if (format == Symbol::force_bin)
|
||||
else if (format == force_bin)
|
||||
s << "bin\"";
|
||||
else
|
||||
s << "hex\"";
|
||||
|
@ -355,15 +390,15 @@ void Symbol::restoreXmlHeader(const Element *el)
|
|||
if (attName == "format") {
|
||||
const string &formString(el->getAttributeValue(i));
|
||||
if (formString == "hex")
|
||||
dispflags |= Symbol::force_hex;
|
||||
dispflags |= force_hex;
|
||||
else if (formString == "dec")
|
||||
dispflags |= Symbol::force_dec;
|
||||
dispflags |= force_dec;
|
||||
else if (formString == "char")
|
||||
dispflags |= Symbol::force_char;
|
||||
dispflags |= force_char;
|
||||
else if (formString == "oct")
|
||||
dispflags |= Symbol::force_oct;
|
||||
dispflags |= force_oct;
|
||||
else if (formString == "bin")
|
||||
dispflags |= Symbol::force_bin;
|
||||
dispflags |= force_bin;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
|
@ -385,6 +420,14 @@ void Symbol::restoreXmlHeader(const Element *el)
|
|||
flags |= Varnode::indirectstorage;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (attName == "merge") {
|
||||
if (!xml_readbool(el->getAttributeValue(i))) {
|
||||
dispflags |= isolate;
|
||||
flags |= Varnode::typelock;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (attName == "name")
|
||||
name = el->getAttributeValue(i);
|
||||
|
|
|
@ -181,7 +181,8 @@ public:
|
|||
force_bin = 4, ///< Force binary printing of constant symbol
|
||||
force_char = 5, ///< Force integer to be printed as a character constant
|
||||
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
|
||||
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 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 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
|
||||
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
|
||||
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
|
||||
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
|
||||
void saveXmlHeader(ostream &s) const; ///< Save basic Symbol properties as XML attributes
|
||||
void restoreXmlHeader(const Element *el); ///< Restore basic Symbol properties from XML
|
||||
|
|
|
@ -115,6 +115,7 @@ void IfaceDecompCapability::registerCommands(IfaceStatus *status)
|
|||
status->registerCom(new IfcRename(),"rename");
|
||||
status->registerCom(new IfcRetype(),"retype");
|
||||
status->registerCom(new IfcRemove(),"remove");
|
||||
status->registerCom(new IfcIsolate(),"isolate");
|
||||
status->registerCom(new IfcLockPrototype(),"prototype","lock");
|
||||
status->registerCom(new IfcUnlockPrototype(),"prototype","unlock");
|
||||
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)
|
||||
|
||||
{ // Return varnode identified by input stream
|
||||
|
|
|
@ -304,6 +304,11 @@ public:
|
|||
virtual void execute(istream &s);
|
||||
};
|
||||
|
||||
class IfcIsolate : public IfaceDecompCommand {
|
||||
public:
|
||||
virtual void execute(istream &s);
|
||||
};
|
||||
|
||||
class IfcRemove : public IfaceDecompCommand {
|
||||
public:
|
||||
virtual void execute(istream &s);
|
||||
|
|
|
@ -102,15 +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 (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;
|
||||
}
|
||||
|
@ -145,6 +145,14 @@ bool Merge::mergeTestAdjacent(HighVariable *high_out,HighVariable *high_in)
|
|||
Varnode *vn = high_in->getInputVarnode();
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -837,10 +845,14 @@ void Merge::mergeMultiEntry(void)
|
|||
if (newHigh == high) continue; // Varnodes already merged
|
||||
updateHigh(newHigh);
|
||||
if (!mergeTestRequired(high, newHigh)) {
|
||||
symbol->setMergeProblems();
|
||||
newHigh->setUnmerged();
|
||||
conflictCount += 1;
|
||||
continue;
|
||||
}
|
||||
if (!merge(high,newHigh,false)) { // Attempt the merge
|
||||
symbol->setMergeProblems();
|
||||
newHigh->setUnmerged();
|
||||
conflictCount += 1;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1639,6 +1639,21 @@ void PrintC::pushSymbol(const Symbol *sym,const Varnode *vn,const PcodeOp *op)
|
|||
else
|
||||
tokenColor = EmitXml::var_color;
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -2180,14 +2195,19 @@ bool PrintC::emitScopeVarDecls(const Scope *scope,int4 cat)
|
|||
MapIterator iter = scope->begin();
|
||||
MapIterator enditer = scope->end();
|
||||
for(;iter!=enditer;++iter) {
|
||||
if ((*iter)->isPiece()) continue; // Don't do a partial entry
|
||||
Symbol *sym = (*iter)->getSymbol();
|
||||
const SymbolEntry *entry = *iter;
|
||||
if (entry->isPiece()) continue; // Don't do a partial entry
|
||||
Symbol *sym = entry->getSymbol();
|
||||
if (sym->getCategory() != cat) continue;
|
||||
if (sym->getName().size() == 0) continue;
|
||||
if (dynamic_cast<FunctionSymbol *>(sym) != (FunctionSymbol *)0)
|
||||
continue;
|
||||
if (dynamic_cast<LabSymbol *>(sym) != (LabSymbol *)0)
|
||||
continue;
|
||||
if (sym->isMultiEntry()) {
|
||||
if (sym->getFirstWholeMap() != entry)
|
||||
continue; // Only emit the first SymbolEntry for declaration of multi-entry Symbol
|
||||
}
|
||||
notempty = true;
|
||||
emitVarDeclStatement(sym);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
/// this method is called again.
|
||||
/// \param tp is the data-type to set
|
||||
|
|
|
@ -49,7 +49,8 @@ public:
|
|||
symboldirty = 8, ///< The symbol attachment is dirty
|
||||
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
|
||||
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:
|
||||
friend class Varnode;
|
||||
|
@ -79,10 +80,12 @@ private:
|
|||
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 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:
|
||||
HighVariable(Varnode *vn); ///< Construct a HighVariable with a single member Varnode
|
||||
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 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
|
||||
|
@ -111,6 +114,7 @@ public:
|
|||
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
|
||||
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.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue