mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-2015 Adjustments to DynamicHash for "Force Union Field" action
This commit is contained in:
parent
bee69b2f38
commit
1bed9dac4d
5 changed files with 148 additions and 16 deletions
|
@ -19,7 +19,7 @@
|
|||
|
||||
// Table for how to hash opcodes, lumps certain operators (i.e. ADD SUB PTRADD PTRSUB) into one hash
|
||||
// zero indicates the operator should be skipped
|
||||
uint4 DynamicHash::transtable[] = {
|
||||
const uint4 DynamicHash::transtable[] = {
|
||||
0,
|
||||
CPUI_COPY, CPUI_LOAD, CPUI_STORE, CPUI_BRANCH, CPUI_CBRANCH, CPUI_BRANCHIND,
|
||||
|
||||
|
@ -199,11 +199,30 @@ void DynamicHash::clear(void)
|
|||
void DynamicHash::calcHash(const PcodeOp *op,int4 slot,uint4 method)
|
||||
|
||||
{
|
||||
const Varnode *root;
|
||||
|
||||
// slot may be from a hash unassociated with op
|
||||
// we need to check that slot indicates a valid Varnode
|
||||
if (slot < 0) {
|
||||
root = op->getOut();
|
||||
if (root == (const Varnode *)0) {
|
||||
hash = 0;
|
||||
addrresult = Address();
|
||||
return; // slot does not fit op
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (slot >= op->numInput()) {
|
||||
hash = 0;
|
||||
addrresult = Address();
|
||||
return; // slot does not fit op
|
||||
}
|
||||
root = op->getIn(slot);
|
||||
}
|
||||
vnproc = 0;
|
||||
opproc = 0;
|
||||
opedgeproc = 0;
|
||||
|
||||
const Varnode *root = (slot < 0) ? op->getOut() : op->getIn(slot);
|
||||
opedge.push_back(ToOpEdge(op,slot));
|
||||
switch(method) {
|
||||
case 4:
|
||||
|
@ -354,6 +373,32 @@ void DynamicHash::pieceTogetherHash(const Varnode *root,uint4 method)
|
|||
addrresult = op->getSeqNum().getAddr();
|
||||
}
|
||||
|
||||
/// For a DynamicHash on a PcodeOp, the op must not be a CAST or other skipped opcode.
|
||||
/// Test if the given op is a skip op, and if so follow data-flow indicated by the
|
||||
/// slot to another PcodeOp until we find one that isn't a skip op. Pass back the new PcodeOp
|
||||
/// and slot. Pass back null if the data-flow path ends.
|
||||
/// \param op is the given PcodeOp to modify
|
||||
/// \param slot is the slot to modify
|
||||
void DynamicHash::moveOffSkip(const PcodeOp *&op,int4 &slot)
|
||||
|
||||
{
|
||||
while(transtable[op->code()] == 0) {
|
||||
if (slot >= 0) {
|
||||
const Varnode *vn = op->getOut();
|
||||
op = vn->loneDescend();
|
||||
if (op == (PcodeOp*)0) {
|
||||
return; // Indicate the end of the data-flow path
|
||||
}
|
||||
slot = op->getSlot(vn);
|
||||
}
|
||||
else {
|
||||
const Varnode *vn = op->getIn(0);
|
||||
if (!vn->isWritten()) return; // Indicate the end of the data-flow path
|
||||
op = vn->getDef();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect the set of Varnodes at the same address as the given Varnode.
|
||||
/// Starting with method 0, increment the method and calculate hashes
|
||||
/// of the Varnodes until the given Varnode has a unique hash within the set.
|
||||
|
@ -424,6 +469,12 @@ void DynamicHash::uniqueHash(const Varnode *root,Funcdata *fd)
|
|||
addrresult = tmpaddr;
|
||||
}
|
||||
|
||||
/// Different hash methods are cycled through until a hash is found that distinguishes the given
|
||||
/// op from other PcodeOps at the same address. The final hash encoding and address of the PcodeOp are
|
||||
/// built for retrieval using getHash() and getAddress().
|
||||
/// \param op is the given PcodeOp
|
||||
/// \param slot is the particular slot to encode in the hash
|
||||
/// \param fd is the function containing the given PcodeOp
|
||||
void DynamicHash::uniqueHash(const PcodeOp *op,int4 slot,Funcdata *fd)
|
||||
|
||||
{
|
||||
|
@ -435,6 +486,12 @@ void DynamicHash::uniqueHash(const PcodeOp *op,int4 slot,Funcdata *fd)
|
|||
Address tmpaddr;
|
||||
uint4 maxduplicates = 8;
|
||||
|
||||
moveOffSkip(op, slot);
|
||||
if (op == (const PcodeOp *)0) {
|
||||
hash = (uint8)0;
|
||||
addrresult = Address(); // Hash cannot be calculated
|
||||
return;
|
||||
}
|
||||
gatherOpsAtAddress(oplist,fd,op->getAddr());
|
||||
for(method=4;method<7;++method) {
|
||||
clear();
|
||||
|
|
|
@ -76,6 +76,7 @@ class DynamicHash {
|
|||
void gatherUnmarkedVn(void); ///< Move staged Varnodes into the sub-graph and mark them
|
||||
void gatherUnmarkedOp(void); ///< Mark any new PcodeOps in the sub-graph
|
||||
void pieceTogetherHash(const Varnode *root,uint4 method); ///< Clean-up and piece together formal hash value
|
||||
static void moveOffSkip(const PcodeOp *&op,int4 &slot); ///< Convert given PcodeOp to a non-skip op by following data-flow
|
||||
public:
|
||||
void clear(void); ///< Called for each additional hash (after the first)
|
||||
void calcHash(const Varnode *root,uint4 method); ///< Calculate the hash for given Varnode and method
|
||||
|
@ -97,7 +98,7 @@ public:
|
|||
static bool getIsNotAttached(uint8 h); ///< Retrieve the attachment boolean from a hash
|
||||
static void clearTotalPosition(uint8 &h); ///< Clear the collision total and position fields within a hash
|
||||
static uint4 getComparable(uint8 h) { return (uint4)h; } ///< Get only the formal hash for comparing
|
||||
static uint4 transtable[]; ///< Translation of op-codes to hash values
|
||||
static const uint4 transtable[]; ///< Translation of op-codes to hash values
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue