mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-1518 Decompiler support for unions
This commit is contained in:
parent
53e2c4dc4f
commit
3fdbbbb231
65 changed files with 5119 additions and 1068 deletions
|
@ -828,13 +828,8 @@ bool Funcdata::syncVarnodesWithSymbols(const ScopeLocal *lm,bool typesyes)
|
|||
fl = entry->getAllFlags();
|
||||
if (entry->getSize() >= vnexemplar->getSize()) {
|
||||
if (typesyes) {
|
||||
uintb off = (vnexemplar->getOffset() - entry->getAddr().getOffset()) + entry->getOffset();
|
||||
Datatype *cur = entry->getSymbol()->getType();
|
||||
do {
|
||||
ct = cur;
|
||||
cur = cur->getSubType(off,&off);
|
||||
} while(cur != (Datatype *)0);
|
||||
if ((ct->getSize() != vnexemplar->getSize())||(ct->getMetatype() == TYPE_UNKNOWN))
|
||||
ct = entry->getSizedType(vnexemplar->getAddr(), vnexemplar->getSize());
|
||||
if (ct != (Datatype *)0 && ct->getMetatype() == TYPE_UNKNOWN)
|
||||
ct = (Datatype *)0;
|
||||
}
|
||||
}
|
||||
|
@ -863,6 +858,52 @@ bool Funcdata::syncVarnodesWithSymbols(const ScopeLocal *lm,bool typesyes)
|
|||
return updateoccurred;
|
||||
}
|
||||
|
||||
/// If the Varnode is a partial Symbol with \e union data-type, the best description of the Varnode's
|
||||
/// data-type is delayed until data-type propagation is started.
|
||||
/// We attempt to resolve this description and also lay down any facing resolutions for the Varnode
|
||||
/// \param vn is the given Varnode
|
||||
/// \return the best data-type or null
|
||||
Datatype *Funcdata::checkSymbolType(Varnode *vn)
|
||||
|
||||
{
|
||||
if (vn->isTypeLock()) return vn->getType();
|
||||
SymbolEntry *entry = vn->getSymbolEntry();
|
||||
Symbol *sym = entry->getSymbol();
|
||||
if (sym->getType()->getMetatype() != TYPE_UNION)
|
||||
return (Datatype *)0;
|
||||
TypeUnion *unionType = (TypeUnion *)sym->getType();
|
||||
int4 off = (int4)(vn->getOffset() - entry->getAddr().getOffset()) + entry->getOffset();
|
||||
if (off == 0 && unionType->getSize() == vn->getSize())
|
||||
return (Datatype *)0;
|
||||
const TypeField *finalField = (const TypeField *)0;
|
||||
uintb finalOff = 0;
|
||||
list<PcodeOp *>::const_iterator iter;
|
||||
for(iter=vn->beginDescend();iter!=vn->endDescend();++iter) {
|
||||
PcodeOp *op = *iter;
|
||||
const TypeField *field = unionType->resolveTruncation(off, op, op->getSlot(vn),off);
|
||||
if (field != (const TypeField *)0) {
|
||||
finalField = field;
|
||||
finalOff = off;
|
||||
}
|
||||
}
|
||||
if (vn->isWritten()) {
|
||||
const TypeField *field = unionType->resolveTruncation(off, vn->getDef(), -1, off);
|
||||
if (field != (const TypeField *)0) {
|
||||
finalField = field;
|
||||
finalOff = off;
|
||||
}
|
||||
}
|
||||
if (finalField != (const TypeField *)0) { // If any use of the Varnode resolves to a specific field
|
||||
// Try to truncate down to a final data-type to assign to the Varnode
|
||||
Datatype *ct = finalField->type;
|
||||
while(ct != (Datatype *)0 && (finalOff != 0 || ct->getSize() != vn->getSize())) {
|
||||
ct = ct->getSubType(finalOff, &finalOff);
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
return (Datatype *)0;
|
||||
}
|
||||
|
||||
/// A Varnode overlaps the given SymbolEntry. Make sure the Varnode is part of the variable
|
||||
/// underlying the Symbol. If not, remap things so that the Varnode maps to a distinct Symbol.
|
||||
/// In either case, attach the appropriate Symbol to the Varnode
|
||||
|
@ -1175,10 +1216,14 @@ bool Funcdata::attemptDynamicMapping(SymbolEntry *entry,DynamicHash &dhash)
|
|||
if (sym->getScope() != localmap)
|
||||
throw LowlevelError("Cannot currently have a dynamic symbol outside the local scope");
|
||||
dhash.clear();
|
||||
int4 category = sym->getCategory();
|
||||
if (category == Symbol::union_facet) {
|
||||
return applyUnionFacet(entry, dhash);
|
||||
}
|
||||
Varnode *vn = dhash.findVarnode(this,entry->getFirstUseAddress(),entry->getHash());
|
||||
if (vn == (Varnode *)0) return false;
|
||||
if (entry->getSymbol()->getCategory() == 1) { // Is this an equate symbol
|
||||
if (vn->mapentry != entry) { // Check we haven't marked this before
|
||||
if (category == Symbol::equate) { // Is this an equate symbol
|
||||
if (vn->mapentry != entry) { // Check we haven't marked this before
|
||||
vn->setSymbolEntry(entry);
|
||||
return true;
|
||||
}
|
||||
|
@ -1202,12 +1247,15 @@ bool Funcdata::attemptDynamicMappingLate(SymbolEntry *entry,DynamicHash &dhash)
|
|||
|
||||
{
|
||||
dhash.clear();
|
||||
Symbol *sym = entry->getSymbol();
|
||||
if (sym->getCategory() == Symbol::union_facet) {
|
||||
return applyUnionFacet(entry, dhash);
|
||||
}
|
||||
Varnode *vn = dhash.findVarnode(this,entry->getFirstUseAddress(),entry->getHash());
|
||||
if (vn == (Varnode *)0)
|
||||
return false;
|
||||
if (vn->getSymbolEntry() == entry) return false; // Already applied it
|
||||
Symbol *sym = entry->getSymbol();
|
||||
if (sym->getCategory() == 1) { // Equate symbol does not depend on size
|
||||
if (sym->getCategory() == Symbol::equate) { // Equate symbol does not depend on size
|
||||
vn->setSymbolEntry(entry);
|
||||
return true;
|
||||
}
|
||||
|
@ -1406,6 +1454,28 @@ void Funcdata::coverVarnodes(SymbolEntry *entry,vector<Varnode *> &list)
|
|||
}
|
||||
}
|
||||
|
||||
/// \brief Cache information from a UnionFacetSymbol
|
||||
///
|
||||
/// The symbol forces a particular union field resolution for the associated PcodeOp and slot,
|
||||
/// which are extracted from the given \e dynamic SymbolEntry. The resolution is cached
|
||||
/// in the \b unionMap so that it will get picked up by resolveInFlow() methods etc.
|
||||
/// \param entry is the given SymbolEntry
|
||||
/// \param dhash is preallocated storage for calculating the dynamic hash
|
||||
/// \return \b true if the UnionFacetSymbol is successfully cached
|
||||
bool Funcdata::applyUnionFacet(SymbolEntry *entry,DynamicHash &dhash)
|
||||
|
||||
{
|
||||
Symbol *sym = entry->getSymbol();
|
||||
PcodeOp *op = dhash.findOp(this, entry->getFirstUseAddress(), entry->getHash());
|
||||
if (op == (PcodeOp *)0)
|
||||
return false;
|
||||
int4 slot = DynamicHash::getSlotFromHash(entry->getHash());
|
||||
int4 fldNum = ((UnionFacetSymbol *)sym)->getFieldNumber();
|
||||
ResolvedUnion resolve(sym->getType(), fldNum, *glb->types);
|
||||
resolve.setLock(true);
|
||||
return setUnionField(sym->getType(),op,slot,resolve);
|
||||
}
|
||||
|
||||
/// Search for \e addrtied Varnodes whose storage falls in the global Scope, then
|
||||
/// build a new global Symbol if one didn't exist before.
|
||||
void Funcdata::mapGlobals(void)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue