Added spacebase references to the symbol linking process

This commit is contained in:
caheckman 2019-12-05 14:40:23 -05:00
parent c886f01587
commit 917d2492e4
5 changed files with 85 additions and 17 deletions

View file

@ -2450,25 +2450,56 @@ void ActionNameVars::lookForFuncParamNames(Funcdata &data,const vector<Varnode *
} }
} }
int4 ActionNameVars::apply(Funcdata &data) /// \brief Link symbols associated with a given \e spacebase Varnode
///
/// Look for PTRSUB ops which indicate a symbol reference within the address space
/// referred to by the \e spacebase Varnode. Decode any symbol reference and link it
/// to the appropriate HighVariable
/// \param vn is the given \e spacebase Varnode
/// \param data is the function containing the Varnode
/// \param namerec is used to store any recovered Symbol without a name
void ActionNameVars::linkSpacebaseSymbol(Varnode *vn,Funcdata &data,vector<Varnode *> &namerec)
{
if (!vn->isConstant() && !vn->isInput()) return;
list<PcodeOp *>::const_iterator iter;
for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) {
PcodeOp *op = *iter;
if (op->code() != CPUI_PTRSUB) continue;
Symbol *sym = data.linkSymbolReference(op->getIn(1));
if ((sym != (Symbol *)0) && sym->isNameUndefined())
namerec.push_back(vn);
}
}
void ActionNameVars::linkSymbols(Funcdata &data,vector<Varnode *> &namerec)
{ {
const AddrSpaceManager *manage = data.getArch(); const AddrSpaceManager *manage = data.getArch();
VarnodeLocSet::const_iterator iter,enditer; VarnodeLocSet::const_iterator iter,enditer;
AddrSpace *spc; AddrSpace *spc;
vector<Varnode *> namerec; // Name representatives of symbols that need names AddrSpace *constSpace = manage->getConstantSpace();
enditer = data.endLoc(constSpace);
for(iter=data.beginLoc(constSpace);iter!=enditer;++iter) {
Varnode *curvn = *iter;
if (curvn->getSymbolEntry() != (SymbolEntry *)0)
data.linkSymbol(curvn); // Special equate symbol
else if (curvn->isSpacebase())
linkSpacebaseSymbol(curvn, data, namerec);
}
for(int4 i=0;i<manage->numSpaces();++i) { // Build a list of nameable highs for(int4 i=0;i<manage->numSpaces();++i) { // Build a list of nameable highs
spc = manage->getSpace(i); spc = manage->getSpace(i);
if (spc == (AddrSpace *)0) continue; if (spc == (AddrSpace *)0) continue;
if (spc == constSpace) continue;
enditer = data.endLoc(spc); enditer = data.endLoc(spc);
for(iter=data.beginLoc(spc);iter!=enditer;++iter) { for(iter=data.beginLoc(spc);iter!=enditer;++iter) {
Varnode *curvn = *iter; Varnode *curvn = *iter;
if (curvn->isFree()) { if (curvn->isFree()) {
if (curvn->getSymbolEntry() != (SymbolEntry *)0)
data.linkSymbol(curvn); // Special equate symbol
continue; continue;
} }
if (curvn->isSpacebase())
linkSpacebaseSymbol(curvn, data, namerec);
Varnode *vn = curvn->getHigh()->getNameRepresentative(); Varnode *vn = curvn->getHigh()->getNameRepresentative();
if (vn != curvn) continue; // Hit each high only once if (vn != curvn) continue; // Hit each high only once
HighVariable *high = vn->getHigh(); HighVariable *high = vn->getHigh();
@ -2484,7 +2515,14 @@ int4 ActionNameVars::apply(Funcdata &data)
} }
} }
} }
}
int4 ActionNameVars::apply(Funcdata &data)
{
vector<Varnode *> namerec;
linkSymbols(data, namerec);
lookForRecommendedNames(data); // Make sure recommended names hit before subfunc lookForRecommendedNames(data); // Make sure recommended names hit before subfunc
lookForBadJumpTables(data); lookForBadJumpTables(data);
lookForFuncParamNames(data,namerec); lookForFuncParamNames(data,namerec);

View file

@ -454,6 +454,8 @@ class ActionNameVars : public Action {
static void lookForBadJumpTables(Funcdata &data); ///< Mark the switch variable for bad jump-tables static void lookForBadJumpTables(Funcdata &data); ///< Mark the switch variable for bad jump-tables
static void lookForRecommendedNames(Funcdata &data); ///< Try to apply names from unlocked symbols static void lookForRecommendedNames(Funcdata &data); ///< Try to apply names from unlocked symbols
static void lookForFuncParamNames(Funcdata &data,const vector<Varnode *> &varlist); static void lookForFuncParamNames(Funcdata &data,const vector<Varnode *> &varlist);
static void linkSpacebaseSymbol(Varnode *vn,Funcdata &data,vector<Varnode *> &namerec);
static void linkSymbols(Funcdata &data,vector<Varnode *> &namerec);
public: public:
ActionNameVars(const string &g) : Action(rule_onceperfunc,"namevars",g) {} ///< Constructor ActionNameVars(const string &g) : Action(rule_onceperfunc,"namevars",g) {} ///< Constructor
virtual Action *clone(const ActionGroupList &grouplist) const { virtual Action *clone(const ActionGroupList &grouplist) const {

View file

@ -383,6 +383,7 @@ public:
void calcNZMask(void); ///< Calculate \e non-zero masks for all Varnodes void calcNZMask(void); ///< Calculate \e non-zero masks for all Varnodes
void clearDeadOps(void) { obank.destroyDead(); } ///< Delete any dead PcodeOps void clearDeadOps(void) { obank.destroyDead(); } ///< Delete any dead PcodeOps
Symbol *linkSymbol(Varnode *vn); ///< Find or create Symbol associated with given Varnode Symbol *linkSymbol(Varnode *vn); ///< Find or create Symbol associated with given Varnode
Symbol *linkSymbolReference(Varnode *vn); ///< Discover and attach Symbol to a constant reference
void buildDynamicSymbol(Varnode *vn); ///< Build a \e dynamic Symbol associated with the given Varnode void buildDynamicSymbol(Varnode *vn); ///< Build a \e dynamic Symbol associated with the given Varnode
bool attemptDynamicMapping(SymbolEntry *entry,DynamicHash &dhash); bool attemptDynamicMapping(SymbolEntry *entry,DynamicHash &dhash);
Merge &getMerge(void) { return covermerge; } ///< Get the Merge object for \b this function Merge &getMerge(void) { return covermerge; } ///< Get the Merge object for \b this function

View file

@ -973,6 +973,35 @@ Symbol *Funcdata::linkSymbol(Varnode *vn)
return sym; return sym;
} }
/// A reference to a symbol (i.e. &varname) is typically stored as a PTRSUB operation, where the
/// first input Varnode is a \e spacebase Varnode indicating whether the symbol is on the \e stack or at
/// a \e global RAM location. The second input Varnode is a constant encoding the address of the symbol.
/// This method takes this constant Varnode, recovers the symbol it is referring to, and stores
/// on the HighVariable object attached to the Varnode.
/// \param vn is the constant Varnode (second input) to a PTRSUB operation
/// \return the symbol being referred to or null
Symbol *Funcdata::linkSymbolReference(Varnode *vn)
{
PcodeOp *op = vn->loneDescend();
Varnode *in0 = op->getIn(0);
TypePointer *ptype = (TypePointer *)in0->getHigh()->getType();
if (ptype->getMetatype() != TYPE_PTR) return (Symbol *)0;
TypeSpacebase *sb = (TypeSpacebase *)ptype->getPtrTo();
if (sb->getMetatype() != TYPE_SPACEBASE)
return (Symbol *)0;
Scope *scope = sb->getMap();
Address addr = sb->getAddress(vn->getOffset(),in0->getSize(),op->getAddr());
if (addr.isInvalid())
throw LowlevelError("Unable to generate proper address from spacebase");
SymbolEntry *entry = scope->queryContainer(addr,1,Address());
if (entry == (SymbolEntry *)0)
return (Symbol *)0;
int4 off = (int4)(addr.getOffset() - entry->getAddr().getOffset()) + entry->getOffset();
vn->getHigh()->setSymbol(entry->getSymbol(), off);
return entry->getSymbol();
}
/// If a Symbol is already attached, no change is made. Otherwise a special \e dynamic Symbol is /// If a Symbol is already attached, no change is made. Otherwise a special \e dynamic Symbol is
/// created that is associated with the Varnode via a hash of its local data-flow (rather /// created that is associated with the Varnode via a hash of its local data-flow (rather
/// than its storage address). /// than its storage address).

View file

@ -770,16 +770,11 @@ void PrintC::opPtrsub(const PcodeOp *op)
} }
} }
else if (ct->getMetatype() == TYPE_SPACEBASE) { else if (ct->getMetatype() == TYPE_SPACEBASE) {
TypeSpacebase *sb = (TypeSpacebase *)ct; HighVariable *high = op->getIn(1)->getHigh();
Scope *scope = sb->getMap(); Symbol *symbol = high->getSymbol();
Address addr = sb->getAddress(op->getIn(1)->getOffset(),in0->getSize(),op->getAddr());
if (addr.isInvalid())
throw LowlevelError("Unable to generate proper address from spacebase");
SymbolEntry *entry = scope->queryContainer(addr,1,Address());
Datatype *ct = (Datatype *)0;
arrayvalue = false; arrayvalue = false;
if (entry != (SymbolEntry *)0) { if (symbol != (Symbol *)0) {
ct = entry->getSymbol()->getType(); ct = symbol->getType();
// The '&' is dropped if the output type is an array // The '&' is dropped if the output type is an array
if (ct->getMetatype()==TYPE_ARRAY) { if (ct->getMetatype()==TYPE_ARRAY) {
arrayvalue = valueon; // If printing value, use [0] arrayvalue = valueon; // If printing value, use [0]
@ -795,18 +790,21 @@ void PrintC::opPtrsub(const PcodeOp *op)
if (arrayvalue) if (arrayvalue)
pushOp(&subscript,op); pushOp(&subscript,op);
} }
if (entry == (SymbolEntry *)0) if (symbol == (Symbol *)0) {
TypeSpacebase *sb = (TypeSpacebase *)ct;
Address addr = sb->getAddress(op->getIn(1)->getOffset(),in0->getSize(),op->getAddr());
pushUnnamedLocation(addr,(Varnode *)0,op); pushUnnamedLocation(addr,(Varnode *)0,op);
}
else { else {
int4 off = (int4)(addr.getOffset() - entry->getAddr().getOffset()) + entry->getOffset(); int4 off = high->getSymbolOffset();
if (off == 0) if (off == 0)
pushSymbol(entry->getSymbol(),(Varnode *)0,op); pushSymbol(symbol,(Varnode *)0,op);
else { else {
// If this "value" is getting used as a storage location // If this "value" is getting used as a storage location
// we can't use a cast in its description, so turn off // we can't use a cast in its description, so turn off
// casting when printing the partial symbol // casting when printing the partial symbol
// Datatype *exttype = ((mods & print_store_value)!=0) ? (Datatype *)0 : ct; // Datatype *exttype = ((mods & print_store_value)!=0) ? (Datatype *)0 : ct;
pushPartialSymbol(entry->getSymbol(),off,0,(Varnode *)0,op,(Datatype *)0); pushPartialSymbol(symbol,off,0,(Varnode *)0,op,(Datatype *)0);
} }
} }
if (arrayvalue) if (arrayvalue)