-
Notifications
You must be signed in to change notification settings - Fork 50
/
dynamic.hh
108 lines (99 loc) · 6.41 KB
/
dynamic.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// \file dynamic.hh
/// \brief Utilities for making references to \b dynamic variables: defined as
/// locations and constants that can only be identified by their context within the data-flow graph.
#ifndef __DYNAMIC_HH__
#define __DYNAMIC_HH__
#include "varnode.hh"
namespace ghidra {
/// \brief An edge between a Varnode and a PcodeOp
///
/// A DynamicHash is defined on a sub-graph of the data-flow, and this defines an edge
/// in the sub-graph. The edge can either be from an input Varnode to the PcodeOp
/// that reads it, or from a PcodeOp to the Varnode it defines.
class ToOpEdge {
const PcodeOp *op; ///< The PcodeOp defining the edge
int4 slot; ///< Slot containing the input Varnode or -1 for the p-code op output
public:
ToOpEdge(const PcodeOp *o,int4 s) { op = o; slot = s; } ///< Constructor
const PcodeOp *getOp(void) const { return op; } ///< Get the PcodeOp defining the edge
int4 getSlot(void) const { return slot; } ///< Get the slot of the starting Varnode
bool operator<(const ToOpEdge &op2) const; ///< Compare two edges based on PcodeOp
uint4 hash(uint4 reg) const; ///< Hash \b this edge into an accumulator
};
/// \brief A hash utility to uniquely identify a temporary Varnode in data-flow
///
/// Most Varnodes can be identified within the data-flow graph by their storage address
/// and the address of the PcodeOp that defines them. For temporary registers,
/// this does not work because the storage address is ephemeral. This class allows
/// Varnodes like temporary registers (and constants) to be robustly identified
/// by hashing details of the local data-flow.
///
/// This class, when presented a Varnode via calcHash(), calculates a hash (getHash())
/// and an address (getAddress()) of the PcodeOp most closely associated with the Varnode,
/// either the defining op or the op directly reading the Varnode.
/// There are actually four hash variants that can be calculated, labeled 0, 1, 2, or 3,
/// which incrementally hash in a larger portion of data-flow. The method uniqueHash() selects
/// the simplest variant that causes the hash to be unique for the Varnode, among all
/// the Varnodes that share the same address.
///
/// The variant index is encoded in the hash, so the hash and the address are enough information
/// to uniquely identify the Varnode. This is what is stored in the symbol table for
/// a \e dynamic Symbol.
class DynamicHash {
uint4 vnproc; ///< Number of Varnodes processed in the \b markvn list so far
uint4 opproc; ///< Number of PcodeOps processed in the \b markop list so far
uint4 opedgeproc; ///< Number of edges processed in the \b opedge list
vector<const PcodeOp *> markop; ///< List of PcodeOps in the sub-graph being hashed
vector<const Varnode *> markvn; ///< List of Varnodes is the sub-graph being hashed
vector<const Varnode *> vnedge; ///< A staging area for Varnodes before formally adding to the sub-graph
vector<ToOpEdge> opedge; ///< The edges in the sub-graph
Address addrresult; ///< Address most closely associated with variable
uint8 hash; ///< The calculated hash value
void buildVnUp(const Varnode *vn); ///< Add in the edge between the given Varnode and its defining PcodeOp
void buildVnDown(const Varnode *vn); ///< Add in edges between the given Varnode and any PcodeOp that reads it
void buildOpUp(const PcodeOp *op); ///< Move input Varnodes for the given PcodeOp into staging
void buildOpDown(const PcodeOp *op); ///< Move the output Varnode for the given PcodeOp into staging
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
static void dedupVarnodes(vector<Varnode *> &varlist); ///< Remove any duplicate Varnodes in given list
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
void calcHash(const PcodeOp *op,int4 slot,uint4 method); ///< Calculate hash for given PcodeOp, slot, and method
void uniqueHash(const Varnode *root,Funcdata *fd); ///< Select a unique hash for the given Varnode
void uniqueHash(const PcodeOp *op,int4 slot,Funcdata *fd); ///< Select unique hash for given PcodeOp and slot
Varnode *findVarnode(const Funcdata *fd,const Address &addr,uint8 h);
PcodeOp *findOp(const Funcdata *fd,const Address &addr,uint8 h);
uint8 getHash(void) const { return hash; } ///< Get the (current) hash
const Address &getAddress(void) const { return addrresult; } ///< Get the (current) address
static void gatherFirstLevelVars(vector<Varnode *> &varlist,const Funcdata *fd,const Address &addr,uint8 h);
static void gatherOpsAtAddress(vector<PcodeOp *> &opList,const Funcdata *fd,const Address &addr);
static int4 getSlotFromHash(uint8 h); ///< Retrieve the encoded slot from a hash
static uint4 getMethodFromHash(uint8 h); ///< Retrieve the encoded method from a hash
static uint4 getOpCodeFromHash(uint8 h); ///< Retrieve the encoded op-code from a hash
static uint4 getPositionFromHash(uint8 h); ///< Retrieve the encoded position from a hash
static uint4 getTotalFromHash(uint8 h); ///< Retrieve the encoded collision total from a hash
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 const uint4 transtable[]; ///< Translation of op-codes to hash values
};
} // End namespace ghidra
#endif