mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Added spacebase references to the symbol linking process
This commit is contained in:
parent
c886f01587
commit
917d2492e4
5 changed files with 85 additions and 17 deletions
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue