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

Class for splitting data-flow on laned registers. More...

#include <subflow.hh>

Inheritance diagram for ghidra::LaneDivide:
ghidra::TransformManager

Classes

class  WorkNode
 Description of a large Varnode that needs to be traced (in the worklist) More...
 

Public Member Functions

 LaneDivide (Funcdata *f, Varnode *root, const LaneDescription &desc, bool allowDowncast)
 Constructor. More...
 
bool doTrace (void)
 Trace lanes as far as possible from the root Varnode. More...
 
- Public Member Functions inherited from ghidra::TransformManager
 TransformManager (Funcdata *f)
 Constructor.
 
virtual ~TransformManager (void)
 Destructor.
 
virtual bool preserveAddress (Varnode *vn, int4 bitSize, int4 lsbOffset) const
 Should the address of the given Varnode be preserved when constructing a piece. More...
 
FuncdatagetFunction (void) const
 Get function being transformed.
 
void clearVarnodeMarks (void)
 Clear mark for all Varnodes in the map.
 
TransformVarnewPreexistingVarnode (Varnode *vn)
 Make placeholder for preexisting Varnode. More...
 
TransformVarnewUnique (int4 size)
 Make placeholder for new unique space Varnode. More...
 
TransformVarnewConstant (int4 size, int4 lsbOffset, uintb val)
 Make placeholder for constant Varnode. More...
 
TransformVarnewIop (Varnode *vn)
 Make placeholder for special iop constant. More...
 
TransformVarnewPiece (Varnode *vn, int4 bitSize, int4 lsbOffset)
 Make placeholder for piece of a Varnode. More...
 
TransformVarnewSplit (Varnode *vn, const LaneDescription &description)
 Create placeholder nodes splitting a Varnode into its lanes. More...
 
TransformVarnewSplit (Varnode *vn, const LaneDescription &description, int4 numLanes, int4 startLane)
 Create placeholder nodes splitting a Varnode into a subset of lanes in the given description. More...
 
TransformOpnewOpReplace (int4 numParams, OpCode opc, PcodeOp *replace)
 Create a new placeholder op intended to replace an existing op. More...
 
TransformOpnewOp (int4 numParams, OpCode opc, TransformOp *follow)
 Create a new placeholder op that will not replace an existing op. More...
 
TransformOpnewPreexistingOp (int4 numParams, OpCode opc, PcodeOp *originalOp)
 Create a new placeholder op for an existing PcodeOp. More...
 
TransformVargetPreexistingVarnode (Varnode *vn)
 Get (or create) placeholder for preexisting Varnode. More...
 
TransformVargetPiece (Varnode *vn, int4 bitSize, int4 lsbOffset)
 Get (or create) placeholder piece. More...
 
TransformVargetSplit (Varnode *vn, const LaneDescription &description)
 Find (or create) placeholder nodes splitting a Varnode into its lanes. More...
 
TransformVargetSplit (Varnode *vn, const LaneDescription &description, int4 numLanes, int4 startLane)
 Find (or create) placeholder nodes splitting a Varnode into a subset of lanes from a description. More...
 
void opSetInput (TransformOp *rop, TransformVar *rvn, int4 slot)
 Mark given variable as input to given op. More...
 
void opSetOutput (TransformOp *rop, TransformVar *rvn)
 Mark given variable as output of given op. More...
 
void apply (void)
 Apply the full transform to the function.
 

Private Member Functions

TransformVarsetReplacement (Varnode *vn, int4 numLanes, int4 skipLanes)
 Find or build the placeholder objects for a Varnode that needs to be split into lanes. More...
 
void buildUnaryOp (OpCode opc, PcodeOp *op, TransformVar *inVars, TransformVar *outVars, int4 numLanes)
 Build unary op placeholders with the same opcode across a set of lanes. More...
 
void buildBinaryOp (OpCode opc, PcodeOp *op, TransformVar *in0Vars, TransformVar *in1Vars, TransformVar *outVars, int4 numLanes)
 Build binary op placeholders with the same opcode across a set of lanes. More...
 
bool buildPiece (PcodeOp *op, TransformVar *outVars, int4 numLanes, int4 skipLanes)
 Convert a CPUI_PIECE operation into copies between placeholders, given the output lanes. More...
 
bool buildMultiequal (PcodeOp *op, TransformVar *outVars, int4 numLanes, int4 skipLanes)
 Split a given CPUI_MULTIEQUAL operation into placeholders given the output lanes. More...
 
bool buildStore (PcodeOp *op, int4 numLanes, int4 skipLanes)
 Split a given CPUI_STORE operation into a sequence of STOREs of individual lanes. More...
 
bool buildLoad (PcodeOp *op, TransformVar *outVars, int4 numLanes, int4 skipLanes)
 Split a given CPUI_LOAD operation into a sequence of LOADs of individual lanes. More...
 
bool buildRightShift (PcodeOp *op, TransformVar *outVars, int4 numLanes, int4 skipLanes)
 Check that a CPUI_INT_RIGHT respects the lanes then generate lane placeholders. More...
 
bool traceForward (TransformVar *rvn, int4 numLanes, int4 skipLanes)
 Push the logical lanes forward through any PcodeOp reading the given variable. More...
 
bool traceBackward (TransformVar *rvn, int4 numLanes, int4 skipLanes)
 Pull the logical lanes back through the defining PcodeOp of the given variable. More...
 
bool processNextWork (void)
 Process the next Varnode on the work list. More...
 

Private Attributes

LaneDescription description
 Global description of lanes that need to be split.
 
vector< WorkNodeworkList
 List of Varnodes still left to trace.
 
bool allowSubpieceTerminator
 true if we allow lanes to be cast (via SUBPIECE) to a smaller integer size
 

Additional Inherited Members

- Static Public Member Functions inherited from ghidra::TransformManager
static bool preexistingGuard (int4 slot, TransformVar *rvn)
 Should newPreexistingOp be called. More...
 

Detailed Description

Class for splitting data-flow on laned registers.

From a root Varnode and a description of its lanes, trace data-flow as far as possible through the function, propagating each lane, using the doTrace() method. Then using the apply() method, data-flow can be split, making each lane in every traced register into an explicit Varnode

Constructor & Destructor Documentation

◆ LaneDivide()

ghidra::LaneDivide::LaneDivide ( Funcdata f,
Varnode root,
const LaneDescription desc,
bool  allowDowncast 
)

Constructor.

Parameters
fis the function being transformed
rootis the root Varnode to start tracing lanes from
descis a description of the lanes on the root Varnode
allowDowncastis true if we all SUBPIECE to be treated as terminating

References allowSubpieceTerminator, ghidra::LaneDescription::getNumLanes(), and setReplacement().

Member Function Documentation

◆ buildBinaryOp()

void ghidra::LaneDivide::buildBinaryOp ( OpCode  opc,
PcodeOp op,
TransformVar in0Vars,
TransformVar in1Vars,
TransformVar outVars,
int4  numLanes 
)
private

Build binary op placeholders with the same opcode across a set of lanes.

We assume the input and output placeholder variables have already been collected

Parameters
opcis the desired opcode for the new op placeholders
opis the PcodeOp getting replaced
in0Varsis the array of input[0] variables, 1 for each binary op
in1Varsis the array of input[1] variables, 1 for each binar op
outVarsis the array of output variables, 1 for each binary op
numLanesis the number of binary ops to create

References ghidra::TransformManager::newOpReplace(), ghidra::TransformManager::opSetInput(), and ghidra::TransformManager::opSetOutput().

◆ buildLoad()

bool ghidra::LaneDivide::buildLoad ( PcodeOp op,
TransformVar outVars,
int4  numLanes,
int4  skipLanes 
)
private

Split a given CPUI_LOAD operation into a sequence of LOADs of individual lanes.

A new pointer is constructed for each individual lane into a temporary, then a LOAD is created using the pointer that loads an individual lane.

Parameters
opis the given CPUI_LOAD PcodeOp
outVarsis the output placeholders for the LOAD
numLanesis the number of lanes the LOAD is split into
skipLanesis the starting lane (within the global description) of the value being loaded
Returns
true if the CPUI_LOAD was successfully modeled on lanes

References ghidra::CPUI_INT_ADD, ghidra::CPUI_LOAD, ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::TransformManager::getPreexistingVarnode(), ghidra::Varnode::getSize(), ghidra::Varnode::getSpaceFromConst(), ghidra::AddrSpace::isBigEndian(), ghidra::Varnode::isConstant(), ghidra::Varnode::isFree(), ghidra::TransformManager::newConstant(), ghidra::TransformManager::newOp(), ghidra::TransformManager::newOpReplace(), ghidra::TransformManager::newUnique(), ghidra::TransformManager::opSetInput(), and ghidra::TransformManager::opSetOutput().

◆ buildMultiequal()

bool ghidra::LaneDivide::buildMultiequal ( PcodeOp op,
TransformVar outVars,
int4  numLanes,
int4  skipLanes 
)
private

Split a given CPUI_MULTIEQUAL operation into placeholders given the output lanes.

Model the single given CPUI_MULTIEQUAL as a sequence of smaller MULTIEQUALs on each individual lane. Return false if the operation cannot be modeled as naturally.

Parameters
opis the original CPUI_MULTIEQUAL PcodeOp
outVarsis the placeholder variables making up the lanes of the output
numLanesis the number of lanes in the output
skipLanesis the index of the least significant output lane within the global description
Returns
true if the operation was fully modeled

References ghidra::CPUI_MULTIEQUAL, ghidra::PcodeOp::getIn(), ghidra::TransformManager::newOpReplace(), ghidra::PcodeOp::numInput(), ghidra::TransformManager::opSetInput(), ghidra::TransformManager::opSetOutput(), and ghidra::SubfloatFlow::setReplacement().

◆ buildPiece()

bool ghidra::LaneDivide::buildPiece ( PcodeOp op,
TransformVar outVars,
int4  numLanes,
int4  skipLanes 
)
private

Convert a CPUI_PIECE operation into copies between placeholders, given the output lanes.

Model the given CPUI_PIECE either as either copies from preexisting Varnodes into the output lanes, or as copies from placeholder variables into the output lanes. Return false if the operation cannot be modeled as natural copies between lanes.

Parameters
opis the original CPUI_PIECE PcodeOp
outVarsis the placeholder variables making up the lanes of the output
numLanesis the number of lanes in the output
skipLanesis the index of the least significant output lane within the global description
Returns
true if the CPUI_PIECE was modeled as natural lane copies

References ghidra::CPUI_COPY, ghidra::PcodeOp::getIn(), ghidra::TransformManager::getPreexistingVarnode(), ghidra::Varnode::getSize(), ghidra::TransformManager::newOpReplace(), ghidra::TransformManager::opSetInput(), ghidra::TransformManager::opSetOutput(), and ghidra::SubfloatFlow::setReplacement().

◆ buildRightShift()

bool ghidra::LaneDivide::buildRightShift ( PcodeOp op,
TransformVar outVars,
int4  numLanes,
int4  skipLanes 
)
private

Check that a CPUI_INT_RIGHT respects the lanes then generate lane placeholders.

For the given lane scheme, check that the RIGHT shift is copying whole lanes to each other. If so, generate the placeholder COPYs that model the shift.

Parameters
opis the given CPUI_INT_RIGHT PcodeOp
outVarsis the output placeholders for the RIGHT shift
numLanesis the number of lanes the shift is split into
skipLanesis the starting lane (within the global description) of the value being loaded
Returns
true if the CPUI_INT_RIGHT was successfully modeled on lanes

References ghidra::CPUI_COPY, ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::Varnode::isConstant(), ghidra::TransformManager::newConstant(), ghidra::TransformManager::newOpReplace(), ghidra::TransformManager::opSetInput(), ghidra::TransformManager::opSetOutput(), and ghidra::SubfloatFlow::setReplacement().

◆ buildStore()

bool ghidra::LaneDivide::buildStore ( PcodeOp op,
int4  numLanes,
int4  skipLanes 
)
private

Split a given CPUI_STORE operation into a sequence of STOREs of individual lanes.

A new pointer is constructed for each individual lane into a temporary, then a STORE is created using the pointer that stores an individual lane.

Parameters
opis the given CPUI_STORE PcodeOp
numLanesis the number of lanes the STORE is split into
skipLanesis the starting lane (within the global description) of the value being stored
Returns
true if the CPUI_STORE was successfully modeled on lanes

References ghidra::CPUI_INT_ADD, ghidra::CPUI_STORE, ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::TransformManager::getPreexistingVarnode(), ghidra::Varnode::getSize(), ghidra::Varnode::getSpaceFromConst(), ghidra::AddrSpace::isBigEndian(), ghidra::Varnode::isConstant(), ghidra::Varnode::isFree(), ghidra::TransformManager::newConstant(), ghidra::TransformManager::newOp(), ghidra::TransformManager::newOpReplace(), ghidra::TransformManager::newUnique(), ghidra::TransformManager::opSetInput(), ghidra::TransformManager::opSetOutput(), and ghidra::SubfloatFlow::setReplacement().

◆ buildUnaryOp()

void ghidra::LaneDivide::buildUnaryOp ( OpCode  opc,
PcodeOp op,
TransformVar inVars,
TransformVar outVars,
int4  numLanes 
)
private

Build unary op placeholders with the same opcode across a set of lanes.

We assume the input and output placeholder variables have already been collected

Parameters
opcis the desired opcode for the new op placeholders
opis the PcodeOp getting replaced
inVarsis the array of input variables, 1 for each unary op
outVarsis the array of output variables, 1 for each unary op
numLanesis the number of unary ops to create

References ghidra::TransformManager::newOpReplace(), ghidra::TransformManager::opSetInput(), and ghidra::TransformManager::opSetOutput().

◆ doTrace()

bool ghidra::LaneDivide::doTrace ( void  )

Trace lanes as far as possible from the root Varnode.

Push the lanes around from the root, setting up the explicit transforms as we go. If at any point, the lanes cannot be naturally pushed, return false.

Returns
true if a full transform has been constructed that can split into explicit lanes

References ghidra::TransformManager::clearVarnodeMarks(), processNextWork(), and workList.

◆ processNextWork()

bool ghidra::LaneDivide::processNextWork ( void  )
private

Process the next Varnode on the work list.

Returns
true if the lane split for the top Varnode on the work list is propagated through local operators

References ghidra::SubfloatFlow::traceBackward(), and ghidra::SubfloatFlow::traceForward().

Referenced by doTrace().

◆ setReplacement()

TransformVar * ghidra::LaneDivide::setReplacement ( Varnode vn,
int4  numLanes,
int4  skipLanes 
)
private

Find or build the placeholder objects for a Varnode that needs to be split into lanes.

The Varnode is split based on the given subset of the lane description. Constants can be split. Decide if the Varnode needs to go into the work list. If the Varnode cannot be acceptably split, return null.

Parameters
vnis the Varnode that needs to be split
numLanesis the number of lanes in the subset
skipLanesis the start (least significant) lane in the subset
Returns
the array of placeholders describing the split or null

References ghidra::Datatype::getMetatype(), ghidra::TransformManager::getSplit(), ghidra::Varnode::getType(), ghidra::Varnode::isConstant(), ghidra::Varnode::isFree(), ghidra::Varnode::isMark(), ghidra::Varnode::isTypeLock(), ghidra::TransformManager::newSplit(), ghidra::Varnode::setMark(), and ghidra::TYPE_PARTIALSTRUCT.

Referenced by LaneDivide().

◆ traceBackward()

bool ghidra::LaneDivide::traceBackward ( TransformVar rvn,
int4  numLanes,
int4  skipLanes 
)
private

Pull the logical lanes back through the defining PcodeOp of the given variable.

Determine if the logical lanes can be pulled back naturally, and create placeholder variables and ops representing the logical data-flow. Update the worklist with any new Varnodes that the lanes get pulled back into.

Parameters
rvnis the placeholder variable to pull back
numLanesis the number of lanes represented by the placeholder variable
skipLanesis the index of the starting lane within the global description of the placeholder variable
Returns
true if the lanes can be naturally pulled back

References ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_RIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_LOAD, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_PIECE, ghidra::CPUI_SUBPIECE, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::TransformVar::getOriginal(), ghidra::Varnode::getSize(), and ghidra::SubfloatFlow::setReplacement().

◆ traceForward()

bool ghidra::LaneDivide::traceForward ( TransformVar rvn,
int4  numLanes,
int4  skipLanes 
)
private

Push the logical lanes forward through any PcodeOp reading the given variable.

Determine if the logical lanes can be pushed forward naturally, and create placeholder variables and ops representing the logical data-flow. Update the worklist with any new Varnodes that the lanes get pushed into.

Parameters
rvnis the placeholder variable to push forward from
numLanesis the number of lanes represented by the placeholder variable
skipLanesis the index of the starting lane within the global description of the placeholder variable
Returns
true if the lanes can be naturally pushed forward

References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_NEGATE, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_RIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_PIECE, ghidra::CPUI_STORE, ghidra::CPUI_SUBPIECE, ghidra::Varnode::endDescend(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::TransformVar::getOriginal(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), ghidra::Varnode::isConstant(), ghidra::Varnode::isMark(), ghidra::TransformManager::newConstant(), ghidra::TransformManager::newPreexistingOp(), ghidra::TransformManager::opSetInput(), and ghidra::SubfloatFlow::setReplacement().


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