decompiler
1.0.0
|
Class for shrinking big Varnodes carrying smaller logical values. More...
#include <subflow.hh>
Classes | |
class | PatchRecord |
Operation with a new logical value as (part of) input, but output Varnode is unchanged. More... | |
class | ReplaceOp |
Placeholder node for PcodeOp operating on smaller logical values. More... | |
class | ReplaceVarnode |
Placeholder node for Varnode holding a smaller logical value. More... | |
Public Member Functions | |
SubvariableFlow (Funcdata *f, Varnode *root, uintb mask, bool aggr, bool sext, bool big) | |
Constructor. More... | |
bool | doTrace (void) |
Trace logical value through data-flow, constructing transform. More... | |
void | doReplacement (void) |
Perform the discovered transform, making logical values explicit. | |
Private Member Functions | |
Address | getReplacementAddress (ReplaceVarnode *rvn) const |
Calculcate address of replacement Varnode for given subgraph variable node. More... | |
ReplaceVarnode * | setReplacement (Varnode *vn, uintb mask, bool &inworklist) |
Add the given Varnode as a new node in the logical subgraph. More... | |
ReplaceOp * | createOp (OpCode opc, int4 numparam, ReplaceVarnode *outrvn) |
Create a logical subgraph operator node given its output variable node. More... | |
ReplaceOp * | createOpDown (OpCode opc, int4 numparam, PcodeOp *op, ReplaceVarnode *inrvn, int4 slot) |
Create a logical subgraph operator node given one of its input variable nodes. More... | |
bool | tryCallPull (PcodeOp *op, ReplaceVarnode *rvn, int4 slot) |
Determine if the given subgraph variable can act as a parameter to the given CALL op. More... | |
bool | tryReturnPull (PcodeOp *op, ReplaceVarnode *rvn, int4 slot) |
Determine if the given subgraph variable can act as return value for the given RETURN op. More... | |
bool | tryCallReturnPush (PcodeOp *op, ReplaceVarnode *rvn) |
Determine if the given subgraph variable can act as a created value for the given INDIRECT op. More... | |
bool | trySwitchPull (PcodeOp *op, ReplaceVarnode *rvn) |
Determine if the subgraph variable can act as a switch variable for the given BRANCHIND. More... | |
bool | traceForward (ReplaceVarnode *rvn) |
Trace the logical data-flow forward for the given subgraph variable. More... | |
bool | traceBackward (ReplaceVarnode *rvn) |
Trace the logical data-flow backward for the given subgraph variable. More... | |
bool | traceForwardSext (ReplaceVarnode *rvn) |
Trace logical data-flow forward assuming sign-extensions. More... | |
bool | traceBackwardSext (ReplaceVarnode *rvn) |
Trace logical data-flow backward assuming sign-extensions. More... | |
bool | createLink (ReplaceOp *rop, uintb mask, int4 slot, Varnode *vn) |
Add a new variable to the logical subgraph as an input to the given operation. More... | |
bool | createCompareBridge (PcodeOp *op, ReplaceVarnode *inrvn, int4 slot, Varnode *othervn) |
Extend the logical subgraph through a given comparison operator if possible. More... | |
void | addPush (PcodeOp *pushOp, ReplaceVarnode *rvn) |
Mark an operation where original data-flow is being pushed into a subgraph variable. More... | |
void | addTerminalPatch (PcodeOp *pullop, ReplaceVarnode *rvn) |
Mark an operation where a subgraph variable is naturally copied into the original data-flow. More... | |
void | addTerminalPatchSameOp (PcodeOp *pullop, ReplaceVarnode *rvn, int4 slot) |
Mark an operation where a subgraph variable is naturally pulled into the original data-flow. More... | |
void | addBooleanPatch (PcodeOp *pullop, ReplaceVarnode *rvn, int4 slot) |
Mark a subgraph bit variable flowing into an operation taking a boolean input. More... | |
void | addSuggestedPatch (ReplaceVarnode *rvn, PcodeOp *pushop, int4 sa) |
Mark a subgraph variable flowing to an operation that expands it by padding with zero bits. More... | |
void | addComparePatch (ReplaceVarnode *in1, ReplaceVarnode *in2, PcodeOp *op) |
Mark subgraph variables flowing into a comparison operation. More... | |
ReplaceVarnode * | addConstant (ReplaceOp *rop, uintb mask, uint4 slot, Varnode *constvn) |
Add a constant variable node to the logical subgraph. More... | |
ReplaceVarnode * | addNewConstant (ReplaceOp *rop, uint4 slot, uintb val) |
Add a new constant variable node as an input to a logical operation. More... | |
void | createNewOut (ReplaceOp *rop, uintb mask) |
Create a new, non-shadowing, subgraph variable node as an operation output. More... | |
void | replaceInput (ReplaceVarnode *rvn) |
Replace an input Varnode in the subgraph with a temporary register. More... | |
bool | useSameAddress (ReplaceVarnode *rvn) |
Decide if we use the same memory range of the original Varnode for the logical replacement. More... | |
Varnode * | getReplaceVarnode (ReplaceVarnode *rvn) |
Build the logical Varnode which will replace its original containing Varnode. More... | |
bool | processNextWork (void) |
Extend the subgraph from the next node in the worklist. More... | |
Static Private Member Functions | |
static int4 | doesOrSet (PcodeOp *orop, uintb mask) |
Return slot of constant if INT_OR op sets all bits in mask, otherwise -1. More... | |
static int4 | doesAndClear (PcodeOp *andop, uintb mask) |
Return slot of constant if INT_AND op clears all bits in mask, otherwise -1. More... | |
Private Attributes | |
int4 | flowsize |
Size of the logical data-flow in bytes. | |
int4 | bitsize |
Number of bits in logical variable. | |
bool | returnsTraversed |
Have we tried to flow logical value across CPUI_RETURNs. | |
bool | aggressive |
Do we "know" initial seed point must be a sub variable. | |
bool | sextrestrictions |
Check for logical variables that are always sign extended into their container. | |
Funcdata * | fd |
Containing function. | |
map< Varnode *, ReplaceVarnode > | varmap |
Map from original Varnodes to the overlaying subgraph nodes. | |
list< ReplaceVarnode > | newvarlist |
Storage for subgraph variable nodes. | |
list< ReplaceOp > | oplist |
Storage for subgraph op nodes. | |
list< PatchRecord > | patchlist |
Operations getting patched (but with no flow thru) | |
vector< ReplaceVarnode * > | worklist |
Subgraph variable nodes still needing to be traced. | |
int4 | pullcount |
Number of instructions pulling out the logical value. | |
Class for shrinking big Varnodes carrying smaller logical values.
Given a root within the syntax tree and dimensions of a logical variable, this class traces the flow of this logical variable through its containing Varnodes. It then creates a subgraph of this flow, where there is a correspondence between nodes in the subgraph and nodes in the original graph containing the logical variable. When doReplacement is called, this subgraph is duplicated as a new separate piece within the syntax tree. Ops are replaced to reflect the manipulation of of the logical variable, rather than the containing variable. Operations in the original graph which pluck out the logical variable from the containing variable, are replaced with copies from the corresponding node in the new section of the graph, which frequently causes the operations on the original container Varnodes to becomes dead code.
ghidra::SubvariableFlow::SubvariableFlow | ( | Funcdata * | f, |
Varnode * | root, | ||
uintb | mask, | ||
bool | aggr, | ||
bool | sext, | ||
bool | big | ||
) |
Constructor.
f | is the function to attempt the subvariable transform on |
root | is a starting Varnode containing a smaller logical value |
mask | is a mask where 1 bits indicate the position of the logical value within the root Varnode |
aggr | is true if we should use aggressive (less restrictive) tests during the trace |
sext | is true if we should assume sign extensions from the logical value into its container |
big | is true if we look for subvariable flow for big (8-byte) logical values |
References aggressive, bitsize, createLink(), fd, flowsize, returnsTraversed, and sextrestrictions.
|
private |
Mark a subgraph bit variable flowing into an operation taking a boolean input.
This doesn't count as a Varnode holding a logical value that needs to be patched (by itself). A PatchRecord terminating the logical subgraph along the given edge is created.
pullop | is the operation taking the boolean input |
rvn | is the given bit variable |
slot | is the input slot of the variable to the operation |
References ghidra::SubvariableFlow::PatchRecord::parameter_patch, and patchlist.
Referenced by traceForward().
|
private |
Mark subgraph variables flowing into a comparison operation.
The operation accomplishes the logical comparison by comparing the larger containers. A PatchRecord is created indicating that data-flow from the subgraph terminates at the comparison.
in1 | is the first logical value to the comparison |
in2 | is the second logical value |
op | is the comparison operation |
References ghidra::SubvariableFlow::PatchRecord::compare_patch, patchlist, and pullcount.
Referenced by createCompareBridge().
|
private |
Add a constant variable node to the logical subgraph.
rop | is the logical operation taking the constant as input |
mask | is the set of bits holding the logical value (within a bigger value) |
slot | is the input slot to the operation |
constvn | is the original constant |
References ghidra::SubvariableFlow::ReplaceVarnode::def, ghidra::Varnode::getOffset(), ghidra::SubvariableFlow::ReplaceOp::input, ghidra::SubvariableFlow::ReplaceVarnode::mask, newvarlist, ghidra::SubvariableFlow::ReplaceVarnode::replacement, ghidra::SubvariableFlow::ReplaceVarnode::val, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by setReplacement(), traceBackward(), traceBackwardSext(), and traceForwardSext().
|
private |
Add a new constant variable node as an input to a logical operation.
The constant is new and isn't associated with a constant in the original graph.
rop | is the logical operation taking the constant as input |
slot | is the input slot to the operation |
val | is the constant value |
References ghidra::SubvariableFlow::ReplaceVarnode::def, ghidra::SubvariableFlow::ReplaceOp::input, ghidra::SubvariableFlow::ReplaceVarnode::mask, newvarlist, ghidra::SubvariableFlow::ReplaceVarnode::replacement, ghidra::SubvariableFlow::ReplaceVarnode::val, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by traceBackward().
|
private |
Mark an operation where original data-flow is being pushed into a subgraph variable.
The operation is not manipulating the logical value, but it produces a variable containing the logical value. The original op will not change but will just produce a smaller value.
pushOp | is the operation to mark |
rvn | is the output variable holding the logical value |
References patchlist, and ghidra::SubvariableFlow::PatchRecord::push_patch.
Referenced by traceBackward(), traceBackwardSext(), and tryCallReturnPush().
|
private |
Mark a subgraph variable flowing to an operation that expands it by padding with zero bits.
Data-flow along the specified edge within the logical subgraph is terminated by added a PatchRecord. This doesn't count as a logical value that needs to be patched (by itself).
rvn | is the given subgraph variable |
pushop | is the operation that pads the variable |
sa | is the amount the logical value is shifted to the left |
References ghidra::SubvariableFlow::PatchRecord::extension_patch, ghidra::SubvariableFlow::ReplaceVarnode::mask, and patchlist.
Referenced by traceForward().
|
private |
Mark an operation where a subgraph variable is naturally copied into the original data-flow.
If the operations naturally takes the given logical value as input but the output doesn't need to be traced as a logical value, a subgraph terminator (PatchRecord) is created noting this. The original PcodeOp will be converted to a COPY.
pullop | is the PcodeOp pulling the logical value out of the subgraph |
rvn | is the given subgraph variable holding the logical value |
References ghidra::SubvariableFlow::PatchRecord::copy_patch, patchlist, and pullcount.
Referenced by traceForward(), and traceForwardSext().
|
private |
Mark an operation where a subgraph variable is naturally pulled into the original data-flow.
If the operations naturally takes the given logical value as input but the output doesn't need to be traced as a logical value, a subgraph terminator (PatchRecord) is created noting this. The opcode of the operation will not change.
pullop | is the PcodeOp pulling the logical value out of the subgraph |
rvn | is the given subgraph variable holding the logical value |
slot | is the input slot to the operation |
References ghidra::SubvariableFlow::PatchRecord::parameter_patch, patchlist, and pullcount.
Referenced by traceForward(), and traceForwardSext().
|
private |
Extend the logical subgraph through a given comparison operator if possible.
Given the variable already in the subgraph that is compared and the other side of the comparison, add the other side as a logical value to the subgraph and create a PatchRecord for the comparison operation.
op | is the given comparison operation |
inrvn | is the variable already in the logical subgraph |
slot | is the input slot to the comparison of the variable already in the subgraph |
othervn | is the Varnode holding the other side of the comparison |
References addComparePatch(), ghidra::SubvariableFlow::ReplaceVarnode::mask, setReplacement(), and worklist.
Referenced by traceForward(), and traceForwardSext().
|
private |
Add a new variable to the logical subgraph as an input to the given operation.
The subgraph is extended by the specified input edge, and a new variable node is created if necessary or a preexisting node corresponding to the Varnode is used. If the logical value described by the given mask cannot be made to line up with the subgraph variable node, false is returned.
rop | is the given operation |
mask | is the mask describing the logical value within the input Varnode |
slot | is the input slot of the Varnode to the operation |
vn | is the original input Varnode holding the logical value |
References ghidra::SubvariableFlow::ReplaceVarnode::def, ghidra::SubvariableFlow::ReplaceOp::input, ghidra::SubvariableFlow::ReplaceOp::output, setReplacement(), and worklist.
Referenced by SubvariableFlow(), traceBackward(), traceBackwardSext(), traceForward(), and traceForwardSext().
|
private |
Create a new, non-shadowing, subgraph variable node as an operation output.
The new node does not shadow a preexisting Varnode. Because the ReplaceVarnode record is defined by rop (the -def- field is filled in) this can still be distinguished from a constant.
rop | is the logical operation taking the new output |
mask | describes the logical value |
References ghidra::SubvariableFlow::ReplaceVarnode::def, ghidra::SubvariableFlow::ReplaceVarnode::mask, newvarlist, ghidra::SubvariableFlow::ReplaceOp::output, ghidra::SubvariableFlow::ReplaceVarnode::replacement, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by traceForward().
|
private |
Create a logical subgraph operator node given its output variable node.
opc | is the opcode of the new logical operator |
numparam | is the number of parameters in the new operator |
outrvn | is the given output variable node |
References ghidra::SubvariableFlow::ReplaceVarnode::def, ghidra::Varnode::getDef(), ghidra::SubvariableFlow::ReplaceOp::numparams, ghidra::SubvariableFlow::ReplaceOp::op, ghidra::SubvariableFlow::ReplaceOp::opc, oplist, ghidra::SubvariableFlow::ReplaceOp::output, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by traceBackward(), and traceBackwardSext().
|
private |
Create a logical subgraph operator node given one of its input variable nodes.
opc | is the opcode of the new logical operator |
numparam | is the number of parameters in the new operator |
op | is the original PcodeOp being replaced |
inrvn | is the given input variable node |
slot | is the input slot of the variable node |
References ghidra::SubvariableFlow::ReplaceOp::input, ghidra::SubvariableFlow::ReplaceOp::numparams, ghidra::SubvariableFlow::ReplaceOp::op, ghidra::SubvariableFlow::ReplaceOp::opc, oplist, and ghidra::SubvariableFlow::ReplaceOp::output.
Referenced by traceForward(), and traceForwardSext().
|
staticprivate |
Return slot of constant if INT_AND op clears all bits in mask, otherwise -1.
andop | is the given CPUI_INT_AND op |
mask | is the given mask |
References ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), and ghidra::Varnode::isConstant().
Referenced by traceBackward(), and traceForward().
|
staticprivate |
Return slot of constant if INT_OR op sets all bits in mask, otherwise -1.
orop | is the given CPUI_INT_OR op |
mask | is the given mask |
References ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), and ghidra::Varnode::isConstant().
Referenced by traceBackward(), and traceForward().
bool ghidra::SubvariableFlow::doTrace | ( | void | ) |
Trace logical value through data-flow, constructing transform.
Push the logical value around, setting up explicit transforms as we go that convert them into explicit Varnodes. If at any point, we cannot naturally interpret the flow of the logical value, return false.
References fd, processNextWork(), pullcount, varmap, and worklist.
Referenced by ghidra::RuleSubvarAnd::applyOp(), ghidra::RuleSubvarSubpiece::applyOp(), ghidra::RuleSubvarCompZero::applyOp(), and ghidra::RuleSubvarShift::applyOp().
|
private |
Calculcate address of replacement Varnode for given subgraph variable node.
rvn | is the given subgraph variable node |
References flowsize, ghidra::Varnode::getAddr(), ghidra::Varnode::getSize(), ghidra::Address::isBigEndian(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::Address::renormalize(), and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by getReplaceVarnode().
|
private |
Build the logical Varnode which will replace its original containing Varnode.
This is the main routine for converting a logical variable in the subgraph into an actual Varnode object.
rvn | is the logical variable |
References ghidra::Varnode::copySymbolIfValid(), ghidra::SubvariableFlow::ReplaceVarnode::def, fd, flowsize, getReplacementAddress(), ghidra::Varnode::isConstant(), ghidra::Varnode::isInput(), ghidra::Funcdata::newConstant(), ghidra::Funcdata::newUnique(), ghidra::Funcdata::newVarnode(), replaceInput(), ghidra::SubvariableFlow::ReplaceVarnode::replacement, ghidra::Funcdata::setInputVarnode(), useSameAddress(), ghidra::SubvariableFlow::ReplaceVarnode::val, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by doReplacement().
|
private |
Extend the subgraph from the next node in the worklist.
The subgraph is extended from the variable node at the top of the worklist. Data-flow is traced forward and backward one level, possibly extending the subgraph and adding new nodes to the worklist.
References sextrestrictions, traceBackward(), traceBackwardSext(), traceForward(), traceForwardSext(), and worklist.
Referenced by doTrace().
|
private |
Replace an input Varnode in the subgraph with a temporary register.
This is used to avoid overlapping input Varnode errors. The temporary register is typically short lived and gets quickly eliminated in favor of the new logically sized Varnode.
rvn | is the logical variable to replace |
References ghidra::Funcdata::deleteVarnode(), fd, ghidra::Varnode::getSize(), ghidra::Funcdata::newUnique(), ghidra::Funcdata::setInputVarnode(), ghidra::Funcdata::totalReplace(), and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by getReplaceVarnode().
|
private |
Add the given Varnode as a new node in the logical subgraph.
A new ReplaceVarnode object is created, representing the given Varnode within the logical subgraph, and returned. If an object representing the Varnode already exists it is returned. A mask describing the subset of bits within the Varnode representing the logical value is also passed in. This method also determines if the new node needs to be added to the worklist for continued tracing.
vn | is the given Varnode holding the logical value |
mask | is the given mask describing the bits of the logical value |
inworklist | will hold true if the new node should be traced further |
References addConstant(), aggressive, bitsize, ghidra::calc_mask(), ghidra::SubvariableFlow::ReplaceVarnode::def, flowsize, ghidra::Varnode::getConsume(), ghidra::Varnode::getDef(), ghidra::Datatype::getMetatype(), ghidra::Varnode::getOffset(), ghidra::Varnode::getSize(), ghidra::Datatype::getSize(), ghidra::Varnode::getType(), ghidra::Varnode::isAddrForce(), ghidra::PcodeOp::isBoolOutput(), ghidra::Varnode::isConstant(), ghidra::Varnode::isFree(), ghidra::Varnode::isInput(), ghidra::Varnode::isMark(), ghidra::Varnode::isPersist(), ghidra::Varnode::isTypeLock(), ghidra::Varnode::isWritten(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::SubvariableFlow::ReplaceVarnode::replacement, ghidra::Varnode::setMark(), sextrestrictions, ghidra::TYPE_PARTIALSTRUCT, varmap, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by ghidra::SplitFlow::addOp(), createCompareBridge(), createLink(), and tryReturnPull().
|
private |
Trace the logical data-flow backward for the given subgraph variable.
Trace the logical value backward through one PcodeOp adding new nodes to the logical subgraph and updating the worklist.
rvn | is the given logical value to trace |
References addConstant(), addNewConstant(), addPush(), ghidra::calc_mask(), ghidra::PcodeOp::code(), ghidra::CPUI_BOOL_AND, ghidra::CPUI_BOOL_NEGATE, ghidra::CPUI_BOOL_OR, ghidra::CPUI_BOOL_XOR, ghidra::CPUI_CALL, ghidra::CPUI_CALLIND, ghidra::CPUI_COPY, ghidra::CPUI_FLOAT_EQUAL, ghidra::CPUI_FLOAT_LESSEQUAL, ghidra::CPUI_FLOAT_NAN, ghidra::CPUI_FLOAT_NOTEQUAL, ghidra::CPUI_INT_ADD, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_CARRY, ghidra::CPUI_INT_EQUAL, ghidra::CPUI_INT_LEFT, ghidra::CPUI_INT_LESS, ghidra::CPUI_INT_LESSEQUAL, ghidra::CPUI_INT_MULT, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_NOTEQUAL, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_RIGHT, ghidra::CPUI_INT_SBORROW, ghidra::CPUI_INT_SCARRY, ghidra::CPUI_INT_SEXT, ghidra::CPUI_INT_SLESS, ghidra::CPUI_INT_SLESSEQUAL, ghidra::CPUI_INT_SRIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_INT_ZEXT, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_PIECE, ghidra::CPUI_SUBPIECE, createLink(), createOp(), doesAndClear(), doesOrSet(), flowsize, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getNZMask(), ghidra::Varnode::getOffset(), ghidra::Varnode::getSize(), ghidra::Varnode::isConstant(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::PcodeOp::numInput(), tryCallReturnPush(), and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by processNextWork(), and ghidra::SplitFlow::processNextWork().
|
private |
Trace logical data-flow backward assuming sign-extensions.
Try to trace the logical variable up through its defining op, updating the logical subgraph. We assume (and check) that the logical variable has always been sign extended (sextstate) into its container.
rvn | is the given subgraph variable to trace |
References addConstant(), addPush(), ghidra::calc_mask(), ghidra::PcodeOp::code(), ghidra::CPUI_CALL, ghidra::CPUI_CALLIND, ghidra::CPUI_COPY, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_SEXT, ghidra::CPUI_INT_SRIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_INT_ZEXT, ghidra::CPUI_MULTIEQUAL, createLink(), createOp(), flowsize, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getSize(), ghidra::SubvariableFlow::ReplaceOp::input, ghidra::Varnode::isConstant(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::PcodeOp::numInput(), tryCallReturnPush(), and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by processNextWork().
|
private |
Trace the logical data-flow forward for the given subgraph variable.
Try to trace the logical variable through descendant Varnodes creating new nodes in the logical subgraph and updating the worklist.
rvn | is the given subgraph variable to trace |
References addBooleanPatch(), addSuggestedPatch(), addTerminalPatch(), addTerminalPatchSameOp(), aggressive, ghidra::Varnode::beginDescend(), bitsize, ghidra::calc_mask(), ghidra::PcodeOp::code(), ghidra::CPUI_BOOL_AND, ghidra::CPUI_BOOL_NEGATE, ghidra::CPUI_BOOL_OR, ghidra::CPUI_BOOL_XOR, ghidra::CPUI_BRANCHIND, ghidra::CPUI_CALL, ghidra::CPUI_CALLIND, ghidra::CPUI_CBRANCH, ghidra::CPUI_COPY, ghidra::CPUI_INT_ADD, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_EQUAL, ghidra::CPUI_INT_LEFT, ghidra::CPUI_INT_LESS, ghidra::CPUI_INT_LESSEQUAL, ghidra::CPUI_INT_MULT, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_NOTEQUAL, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_RIGHT, ghidra::CPUI_INT_SEXT, ghidra::CPUI_INT_SRIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_INT_ZEXT, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_PIECE, ghidra::CPUI_RETURN, ghidra::CPUI_SUBPIECE, createCompareBridge(), createLink(), createNewOut(), createOpDown(), doesAndClear(), doesOrSet(), ghidra::Varnode::endDescend(), flowsize, ghidra::Varnode::getConsume(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getNZMask(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::PcodeOp::getRepeatSlot(), ghidra::Varnode::getSize(), ghidra::PcodeOp::getSlot(), ghidra::PcodeOp::isCall(), ghidra::Varnode::isConstant(), ghidra::Varnode::isInput(), ghidra::Varnode::isMark(), ghidra::PcodeOp::numInput(), ghidra::SubvariableFlow::ReplaceOp::output, tryCallPull(), tryReturnPull(), trySwitchPull(), and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by processNextWork(), and ghidra::SplitFlow::processNextWork().
|
private |
Trace logical data-flow forward assuming sign-extensions.
Try to trace the logical variable through descendant Varnodes, updating the logical subgraph. We assume (and check) that the logical variable has always been sign extended (sextstate) into its container.
rvn | is the given subgraph variable to trace |
References addConstant(), addTerminalPatch(), addTerminalPatchSameOp(), ghidra::Varnode::beginDescend(), ghidra::calc_mask(), ghidra::PcodeOp::code(), ghidra::CPUI_BRANCHIND, ghidra::CPUI_CALL, ghidra::CPUI_CALLIND, ghidra::CPUI_COPY, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_EQUAL, ghidra::CPUI_INT_LESS, ghidra::CPUI_INT_LESSEQUAL, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_NOTEQUAL, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_SEXT, ghidra::CPUI_INT_SLESS, ghidra::CPUI_INT_SLESSEQUAL, ghidra::CPUI_INT_SRIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_RETURN, ghidra::CPUI_SUBPIECE, createCompareBridge(), createLink(), createOpDown(), ghidra::Varnode::endDescend(), flowsize, ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::PcodeOp::getRepeatSlot(), ghidra::Varnode::getSize(), ghidra::PcodeOp::getSlot(), ghidra::PcodeOp::isCall(), ghidra::Varnode::isConstant(), ghidra::Varnode::isInput(), ghidra::Varnode::isMark(), ghidra::PcodeOp::numInput(), tryCallPull(), tryReturnPull(), trySwitchPull(), and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by processNextWork().
|
private |
Determine if the given subgraph variable can act as a parameter to the given CALL op.
We assume the variable flows as a parameter to the CALL. If the CALL doesn't lock the parameter size, create a PatchRecord within the subgraph that allows the CALL to take the parameter with its smaller logical size.
op | is the given CALL op |
rvn | is the given subgraph variable acting as a parameter |
slot | is the input slot of the variable within the CALL |
References aggressive, fd, ghidra::Funcdata::getCallSpecs(), ghidra::Varnode::getConsume(), ghidra::FuncProto::isDotdotdot(), ghidra::FuncCallSpecs::isInputActive(), ghidra::FuncProto::isInputLocked(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::SubvariableFlow::PatchRecord::parameter_patch, patchlist, pullcount, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by traceForward(), and traceForwardSext().
|
private |
Determine if the given subgraph variable can act as a created value for the given INDIRECT op.
Check if the INDIRECT is an indirect creation and is not representing a locked return value. If we can, create the INDIRECT node in the subgraph representing the logical indirect creation.
op | is the given INDIRECT |
rvn | is the given subgraph variable acting as the output of the INDIRECT |
References addPush(), aggressive, bitsize, fd, ghidra::Funcdata::getCallSpecs(), ghidra::Varnode::getConsume(), ghidra::FuncCallSpecs::isOutputActive(), ghidra::FuncProto::isOutputLocked(), ghidra::SubvariableFlow::ReplaceVarnode::mask, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by traceBackward(), and traceBackwardSext().
|
private |
Determine if the given subgraph variable can act as return value for the given RETURN op.
We assume the variable flows the RETURN. If the return value size is not locked. Create a PatchRecord within the subgraph that allows the RETURN to take a smaller logical value.
op | is the given RETURN op |
rvn | is the given subgraph variable flowing to the RETURN |
slot | is the input slot of the subgraph variable |
References aggressive, ghidra::Funcdata::beginOp(), ghidra::CPUI_RETURN, ghidra::Funcdata::endOp(), fd, ghidra::Varnode::getConsume(), ghidra::Funcdata::getFuncProto(), ghidra::PcodeOp::getHaltType(), ghidra::PcodeOp::getIn(), ghidra::Varnode::isConstant(), ghidra::FuncProto::isOutputLocked(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::SubvariableFlow::PatchRecord::parameter_patch, patchlist, pullcount, returnsTraversed, setReplacement(), ghidra::SubvariableFlow::ReplaceVarnode::vn, and worklist.
Referenced by traceForward(), and traceForwardSext().
|
private |
Determine if the subgraph variable can act as a switch variable for the given BRANCHIND.
We query the JumpTable associated with the BRANCHIND to see if its switch variable can be trimmed as indicated by the logical flow.
op | is the given BRANCHIND op |
rvn | is the subgraph variable flowing to the BRANCHIND |
References ghidra::Varnode::getConsume(), ghidra::SubvariableFlow::ReplaceVarnode::mask, ghidra::SubvariableFlow::PatchRecord::parameter_patch, patchlist, pullcount, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by traceForward(), and traceForwardSext().
|
private |
Decide if we use the same memory range of the original Varnode for the logical replacement.
Usually the logical Varnode can use the true storage bytes that hold the value, but there are a few corner cases where we want to use a new temporary register to hold the value.
rvn | is the subgraph variable |
References aggressive, bitsize, ghidra::Varnode::getConsume(), ghidra::Varnode::isAddrTied(), ghidra::Varnode::isInput(), ghidra::SubvariableFlow::ReplaceVarnode::mask, and ghidra::SubvariableFlow::ReplaceVarnode::vn.
Referenced by getReplaceVarnode().