decompiler  1.0.0
Classes | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
ghidra::SubvariableFlow Class Reference

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...
 
ReplaceVarnodesetReplacement (Varnode *vn, uintb mask, bool &inworklist)
 Add the given Varnode as a new node in the logical subgraph. More...
 
ReplaceOpcreateOp (OpCode opc, int4 numparam, ReplaceVarnode *outrvn)
 Create a logical subgraph operator node given its output variable node. More...
 
ReplaceOpcreateOpDown (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...
 
ReplaceVarnodeaddConstant (ReplaceOp *rop, uintb mask, uint4 slot, Varnode *constvn)
 Add a constant variable node to the logical subgraph. More...
 
ReplaceVarnodeaddNewConstant (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...
 
VarnodegetReplaceVarnode (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.
 
Funcdatafd
 Containing function.
 
map< Varnode *, ReplaceVarnodevarmap
 Map from original Varnodes to the overlaying subgraph nodes.
 
list< ReplaceVarnodenewvarlist
 Storage for subgraph variable nodes.
 
list< ReplaceOpoplist
 Storage for subgraph op nodes.
 
list< PatchRecordpatchlist
 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.
 

Detailed Description

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.

Constructor & Destructor Documentation

◆ SubvariableFlow()

ghidra::SubvariableFlow::SubvariableFlow ( Funcdata f,
Varnode root,
uintb  mask,
bool  aggr,
bool  sext,
bool  big 
)

Constructor.

Parameters
fis the function to attempt the subvariable transform on
rootis a starting Varnode containing a smaller logical value
maskis a mask where 1 bits indicate the position of the logical value within the root Varnode
aggris true if we should use aggressive (less restrictive) tests during the trace
sextis true if we should assume sign extensions from the logical value into its container
bigis true if we look for subvariable flow for big (8-byte) logical values

References aggressive, bitsize, createLink(), fd, flowsize, returnsTraversed, and sextrestrictions.

Member Function Documentation

◆ addBooleanPatch()

void ghidra::SubvariableFlow::addBooleanPatch ( PcodeOp pullop,
ReplaceVarnode rvn,
int4  slot 
)
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.

Parameters
pullopis the operation taking the boolean input
rvnis the given bit variable
slotis the input slot of the variable to the operation

References ghidra::SubvariableFlow::PatchRecord::parameter_patch, and patchlist.

Referenced by traceForward().

◆ addComparePatch()

void ghidra::SubvariableFlow::addComparePatch ( ReplaceVarnode in1,
ReplaceVarnode in2,
PcodeOp op 
)
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.

Parameters
in1is the first logical value to the comparison
in2is the second logical value
opis the comparison operation

References ghidra::SubvariableFlow::PatchRecord::compare_patch, patchlist, and pullcount.

Referenced by createCompareBridge().

◆ addConstant()

SubvariableFlow::ReplaceVarnode * ghidra::SubvariableFlow::addConstant ( ReplaceOp rop,
uintb  mask,
uint4  slot,
Varnode constvn 
)
private

Add a constant variable node to the logical subgraph.

Parameters
ropis the logical operation taking the constant as input
maskis the set of bits holding the logical value (within a bigger value)
slotis the input slot to the operation
constvnis the original constant
Returns
the new constant variable node

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().

◆ addNewConstant()

SubvariableFlow::ReplaceVarnode * ghidra::SubvariableFlow::addNewConstant ( ReplaceOp rop,
uint4  slot,
uintb  val 
)
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.

Parameters
ropis the logical operation taking the constant as input
slotis the input slot to the operation
valis the constant value
Returns
the new constant variable node

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().

◆ addPush()

void ghidra::SubvariableFlow::addPush ( PcodeOp pushOp,
ReplaceVarnode rvn 
)
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.

Parameters
pushOpis the operation to mark
rvnis the output variable holding the logical value

References patchlist, and ghidra::SubvariableFlow::PatchRecord::push_patch.

Referenced by traceBackward(), traceBackwardSext(), and tryCallReturnPush().

◆ addSuggestedPatch()

void ghidra::SubvariableFlow::addSuggestedPatch ( ReplaceVarnode rvn,
PcodeOp pushop,
int4  sa 
)
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).

Parameters
rvnis the given subgraph variable
pushopis the operation that pads the variable
sais 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().

◆ addTerminalPatch()

void ghidra::SubvariableFlow::addTerminalPatch ( PcodeOp pullop,
ReplaceVarnode rvn 
)
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.

Parameters
pullopis the PcodeOp pulling the logical value out of the subgraph
rvnis the given subgraph variable holding the logical value

References ghidra::SubvariableFlow::PatchRecord::copy_patch, patchlist, and pullcount.

Referenced by traceForward(), and traceForwardSext().

◆ addTerminalPatchSameOp()

void ghidra::SubvariableFlow::addTerminalPatchSameOp ( PcodeOp pullop,
ReplaceVarnode rvn,
int4  slot 
)
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.

Parameters
pullopis the PcodeOp pulling the logical value out of the subgraph
rvnis the given subgraph variable holding the logical value
slotis the input slot to the operation

References ghidra::SubvariableFlow::PatchRecord::parameter_patch, patchlist, and pullcount.

Referenced by traceForward(), and traceForwardSext().

◆ createCompareBridge()

bool ghidra::SubvariableFlow::createCompareBridge ( PcodeOp op,
ReplaceVarnode inrvn,
int4  slot,
Varnode othervn 
)
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.

Parameters
opis the given comparison operation
inrvnis the variable already in the logical subgraph
slotis the input slot to the comparison of the variable already in the subgraph
othervnis the Varnode holding the other side of the comparison
Returns
true if the logical subgraph can successfully be extended through the comparison

References addComparePatch(), ghidra::SubvariableFlow::ReplaceVarnode::mask, setReplacement(), and worklist.

Referenced by traceForward(), and traceForwardSext().

◆ createLink()

bool ghidra::SubvariableFlow::createLink ( ReplaceOp rop,
uintb  mask,
int4  slot,
Varnode vn 
)
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.

Parameters
ropis the given operation
maskis the mask describing the logical value within the input Varnode
slotis the input slot of the Varnode to the operation
vnis the original input Varnode holding the logical value
Returns
true is the subgraph is successfully extended to the input

References ghidra::SubvariableFlow::ReplaceVarnode::def, ghidra::SubvariableFlow::ReplaceOp::input, ghidra::SubvariableFlow::ReplaceOp::output, setReplacement(), and worklist.

Referenced by SubvariableFlow(), traceBackward(), traceBackwardSext(), traceForward(), and traceForwardSext().

◆ createNewOut()

void ghidra::SubvariableFlow::createNewOut ( ReplaceOp rop,
uintb  mask 
)
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.

Parameters
ropis the logical operation taking the new output
maskdescribes 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().

◆ createOp()

SubvariableFlow::ReplaceOp * ghidra::SubvariableFlow::createOp ( OpCode  opc,
int4  numparam,
ReplaceVarnode outrvn 
)
private

Create a logical subgraph operator node given its output variable node.

Parameters
opcis the opcode of the new logical operator
numparamis the number of parameters in the new operator
outrvnis the given output variable node
Returns
the new logical subgraph operator object

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().

◆ createOpDown()

SubvariableFlow::ReplaceOp * ghidra::SubvariableFlow::createOpDown ( OpCode  opc,
int4  numparam,
PcodeOp op,
ReplaceVarnode inrvn,
int4  slot 
)
private

Create a logical subgraph operator node given one of its input variable nodes.

Parameters
opcis the opcode of the new logical operator
numparamis the number of parameters in the new operator
opis the original PcodeOp being replaced
inrvnis the given input variable node
slotis the input slot of the variable node
Returns
the new logical subgraph operator objects

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().

◆ doesAndClear()

int4 ghidra::SubvariableFlow::doesAndClear ( PcodeOp andop,
uintb  mask 
)
staticprivate

Return slot of constant if INT_AND op clears all bits in mask, otherwise -1.

Parameters
andopis the given CPUI_INT_AND op
maskis the given mask
Returns
constant slot or -1

References ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), and ghidra::Varnode::isConstant().

Referenced by traceBackward(), and traceForward().

◆ doesOrSet()

int4 ghidra::SubvariableFlow::doesOrSet ( PcodeOp orop,
uintb  mask 
)
staticprivate

Return slot of constant if INT_OR op sets all bits in mask, otherwise -1.

Parameters
oropis the given CPUI_INT_OR op
maskis the given mask
Returns
constant slot or -1

References ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), and ghidra::Varnode::isConstant().

Referenced by traceBackward(), and traceForward().

◆ doTrace()

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.

Returns
true if a full transform has been constructed that can make logical values into explicit Varnodes

References fd, processNextWork(), pullcount, varmap, and worklist.

Referenced by ghidra::RuleSubvarAnd::applyOp(), ghidra::RuleSubvarSubpiece::applyOp(), ghidra::RuleSubvarCompZero::applyOp(), and ghidra::RuleSubvarShift::applyOp().

◆ getReplacementAddress()

Address ghidra::SubvariableFlow::getReplacementAddress ( ReplaceVarnode rvn) const
private

Calculcate address of replacement Varnode for given subgraph variable node.

Parameters
rvnis the given subgraph variable node
Returns
the address of the new logical Varnode

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().

◆ getReplaceVarnode()

Varnode * ghidra::SubvariableFlow::getReplaceVarnode ( ReplaceVarnode rvn)
private

◆ processNextWork()

bool ghidra::SubvariableFlow::processNextWork ( void  )
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.

Returns
true if the node was successfully processed

References sextrestrictions, traceBackward(), traceBackwardSext(), traceForward(), traceForwardSext(), and worklist.

Referenced by doTrace().

◆ replaceInput()

void ghidra::SubvariableFlow::replaceInput ( ReplaceVarnode rvn)
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.

Parameters
rvnis 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().

◆ setReplacement()

SubvariableFlow::ReplaceVarnode * ghidra::SubvariableFlow::setReplacement ( Varnode vn,
uintb  mask,
bool &  inworklist 
)
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.

Parameters
vnis the given Varnode holding the logical value
maskis the given mask describing the bits of the logical value
inworklistwill hold true if the new node should be traced further
Returns
the new subgraph variable node

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().

◆ traceBackward()

bool ghidra::SubvariableFlow::traceBackward ( ReplaceVarnode rvn)
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.

Parameters
rvnis the given logical value to trace
Returns
true if the logical value can be traced backward one level

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().

◆ traceBackwardSext()

bool ghidra::SubvariableFlow::traceBackwardSext ( ReplaceVarnode rvn)
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.

Parameters
rvnis the given subgraph variable to trace
Returns
true if the logical value can successfully traced backward one level

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().

◆ traceForward()

bool ghidra::SubvariableFlow::traceForward ( ReplaceVarnode rvn)
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.

Parameters
rvnis the given subgraph variable to trace
Returns
true if the logical value can be traced forward one level

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().

◆ traceForwardSext()

bool ghidra::SubvariableFlow::traceForwardSext ( ReplaceVarnode rvn)
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.

Parameters
rvnis the given subgraph variable to trace
Returns
true if the logical value can successfully traced forward one level

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().

◆ tryCallPull()

bool ghidra::SubvariableFlow::tryCallPull ( PcodeOp op,
ReplaceVarnode rvn,
int4  slot 
)
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.

Parameters
opis the given CALL op
rvnis the given subgraph variable acting as a parameter
slotis the input slot of the variable within the CALL
Returns
true if the parameter can be successfully trimmed to its logical size

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().

◆ tryCallReturnPush()

bool ghidra::SubvariableFlow::tryCallReturnPush ( PcodeOp op,
ReplaceVarnode rvn 
)
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.

Parameters
opis the given INDIRECT
rvnis the given subgraph variable acting as the output of the INDIRECT
Returns
true if we can successfully trim the value to its logical size

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().

◆ tryReturnPull()

bool ghidra::SubvariableFlow::tryReturnPull ( PcodeOp op,
ReplaceVarnode rvn,
int4  slot 
)
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.

Parameters
opis the given RETURN op
rvnis the given subgraph variable flowing to the RETURN
slotis the input slot of the subgraph variable
Returns
true if the return value can be successfully trimmed to its logical size

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().

◆ trySwitchPull()

bool ghidra::SubvariableFlow::trySwitchPull ( PcodeOp op,
ReplaceVarnode rvn 
)
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.

Parameters
opis the given BRANCHIND op
rvnis the subgraph variable flowing to the BRANCHIND
Returns
true if the switch variable can be successfully trimmed to its logical size

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().

◆ useSameAddress()

bool ghidra::SubvariableFlow::useSameAddress ( ReplaceVarnode rvn)
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.

Parameters
rvnis the subgraph variable
Returns
true if the same memory range can be used to hold the value

References aggressive, bitsize, ghidra::Varnode::getConsume(), ghidra::Varnode::isAddrTied(), ghidra::Varnode::isInput(), ghidra::SubvariableFlow::ReplaceVarnode::mask, and ghidra::SubvariableFlow::ReplaceVarnode::vn.

Referenced by getReplaceVarnode().


The documentation for this class was generated from the following files: