decompiler
1.0.0
|
A loop structure where the condition is checked at the top. More...
#include <block.hh>
Public Member Functions | |
BlockWhileDo (void) | |
Constructor. | |
PcodeOp * | getInitializeOp (void) const |
Get root of initialize statement or null. | |
PcodeOp * | getIterateOp (void) const |
Get root of iterate statement or null. | |
bool | hasOverflowSyntax (void) const |
Does this require overflow syntax. | |
void | setOverflowSyntax (void) |
Set that this requires overflow syntax. | |
virtual block_type | getType (void) const |
Get the FlowBlock type of this. | |
virtual void | markLabelBumpUp (bool bump) |
Let hierarchical blocks steal labels of their (first) components. More... | |
virtual void | scopeBreak (int4 curexit, int4 curloopexit) |
Mark unstructured edges that should be breaks. | |
virtual void | printHeader (ostream &s) const |
Print a simple description of this to stream. More... | |
virtual void | emit (PrintLanguage *lng) const |
Emit the instructions in this FlowBlock as structured code. More... | |
virtual FlowBlock * | nextFlowAfter (const FlowBlock *bl) const |
Get the leaf FlowBlock that will execute after the given FlowBlock. More... | |
virtual void | finalTransform (Funcdata &data) |
virtual void | finalizePrinting (Funcdata &data) const |
Public Member Functions inherited from ghidra::BlockGraph | |
void | clear (void) |
Clear all component FlowBlock objects. | |
virtual | ~BlockGraph (void) |
Destructor. | |
const vector< FlowBlock * > & | getList (void) const |
Get the list of component FlowBlock objects. | |
int4 | getSize (void) const |
Get the number of components. | |
FlowBlock * | getBlock (int4 i) const |
Get the i-th component. | |
virtual FlowBlock * | subBlock (int4 i) const |
Get the i-th component block. | |
virtual void | markUnstructured (void) |
Mark target blocks of any unstructured edges. | |
virtual void | printTree (ostream &s, int4 level) const |
Print tree structure of any blocks owned by this. More... | |
virtual void | printRaw (ostream &s) const |
Print raw instructions contained in this FlowBlock. | |
virtual void | encodeBody (Encoder &encoder) const |
Encode detail about components to a stream. | |
virtual void | decodeBody (Decoder &decoder) |
Restore details about this FlowBlock from an element stream. More... | |
void | decode (Decoder &decoder) |
Decode this BlockGraph from a stream. More... | |
void | addEdge (FlowBlock *begin, FlowBlock *end) |
Add a directed edge between component FlowBlocks. More... | |
void | addLoopEdge (FlowBlock *begin, int4 outindex) |
Mark a given edge as a loop edge. More... | |
void | removeEdge (FlowBlock *begin, FlowBlock *end) |
Remove an edge between component FlowBlocks. More... | |
void | switchEdge (FlowBlock *in, FlowBlock *outbefore, FlowBlock *outafter) |
Move an edge from one out FlowBlock to another. More... | |
void | moveOutEdge (FlowBlock *blold, int4 slot, FlowBlock *blnew) |
Move indicated out edge to a new FlowBlock. More... | |
void | removeBlock (FlowBlock *bl) |
Remove a FlowBlock from this BlockGraph. More... | |
void | removeFromFlow (FlowBlock *bl) |
Remove given FlowBlock preserving flow in this. More... | |
void | removeFromFlowSplit (FlowBlock *bl, bool flipflow) |
Remove FlowBlock splitting flow between input and output edges. More... | |
void | spliceBlock (FlowBlock *bl) |
Splice given FlowBlock together with its output. More... | |
void | setStartBlock (FlowBlock *bl) |
Set the entry point FlowBlock for this graph. More... | |
FlowBlock * | getStartBlock (void) const |
Get the entry point FlowBlock. More... | |
FlowBlock * | newBlock (void) |
Build a new plain FlowBlock. More... | |
BlockBasic * | newBlockBasic (Funcdata *fd) |
Build a new BlockBasic. More... | |
BlockCopy * | newBlockCopy (FlowBlock *bl) |
Build a new BlockCopy. More... | |
BlockGoto * | newBlockGoto (FlowBlock *bl) |
Build a new BlockGoto. More... | |
BlockMultiGoto * | newBlockMultiGoto (FlowBlock *bl, int4 outedge) |
Build a new BlockMultiGoto. More... | |
BlockList * | newBlockList (const vector< FlowBlock *> &nodes) |
Build a new BlockList. More... | |
BlockCondition * | newBlockCondition (FlowBlock *b1, FlowBlock *b2) |
Build a new BlockCondition. More... | |
BlockIf * | newBlockIfGoto (FlowBlock *cond) |
Build a new BlockIfGoto. More... | |
BlockIf * | newBlockIf (FlowBlock *cond, FlowBlock *tc) |
Build a new BlockIf. More... | |
BlockIf * | newBlockIfElse (FlowBlock *cond, FlowBlock *tc, FlowBlock *fc) |
Build a new BlockIfElse. More... | |
BlockWhileDo * | newBlockWhileDo (FlowBlock *cond, FlowBlock *cl) |
Build a new BlockWhileDo. More... | |
BlockDoWhile * | newBlockDoWhile (FlowBlock *condcl) |
Build a new BlockDoWhile. More... | |
BlockInfLoop * | newBlockInfLoop (FlowBlock *body) |
Build a new BlockInfLoop. More... | |
BlockSwitch * | newBlockSwitch (const vector< FlowBlock *> &cs, bool hasExit) |
Build a new BlockSwitch. More... | |
void | orderBlocks (void) |
void | buildCopy (const BlockGraph &graph) |
Build a copy of a BlockGraph. More... | |
void | clearVisitCount (void) |
Clear the visit count in all node FlowBlocks. | |
void | calcForwardDominator (const vector< FlowBlock *> &rootlist) |
Calculate forward dominators. More... | |
void | buildDomTree (vector< vector< FlowBlock *> > &child) const |
Build the dominator tree. More... | |
int4 | buildDomDepth (vector< int4 > &depth) const |
Calculate dominator depths. More... | |
void | buildDomSubTree (vector< FlowBlock *> &res, FlowBlock *root) const |
Collect nodes from a dominator sub-tree. More... | |
void | calcLoop (void) |
Calculate loop edges. More... | |
void | collectReachable (vector< FlowBlock *> &res, FlowBlock *bl, bool un) const |
Collect reachable/unreachable FlowBlocks from a given start FlowBlock. More... | |
void | structureLoops (vector< FlowBlock *> &rootlist) |
Label loop edges. More... | |
Public Member Functions inherited from ghidra::FlowBlock | |
FlowBlock (void) | |
Construct a block with no edges. | |
virtual | ~FlowBlock (void) |
Destructor. | |
int4 | getIndex (void) const |
Get the index assigned to this block. | |
FlowBlock * | getParent (void) |
Get the parent FlowBlock of this. | |
FlowBlock * | getImmedDom (void) const |
Get the immediate dominator FlowBlock. | |
FlowBlock * | getCopyMap (void) const |
Get the mapped FlowBlock. | |
const FlowBlock * | getParent (void) const |
Get the parent FlowBlock of this. | |
uint4 | getFlags (void) const |
Get the block_flags properties. | |
virtual Address | getStart (void) const |
Get the starting address of code in this FlowBlock. | |
virtual Address | getStop (void) const |
Get the ending address of code in this FlowBlock. | |
virtual const FlowBlock * | getExitLeaf (void) const |
Get the FlowBlock to which this block exits. | |
virtual PcodeOp * | lastOp (void) const |
Get the last PcodeOp executed by this FlowBlock. | |
virtual bool | negateCondition (bool toporbottom) |
Flip the condition computed by this. More... | |
virtual bool | preferComplement (Funcdata &data) |
Rearrange this hierarchy to simplify boolean expressions. More... | |
virtual FlowBlock * | getSplitPoint (void) |
Get the leaf splitting block. More... | |
virtual int4 | flipInPlaceTest (vector< PcodeOp *> &fliplist) const |
Test normalizing the conditional branch in this. More... | |
virtual void | flipInPlaceExecute (void) |
Perform the flip to normalize conditional branch executed by this block. More... | |
virtual bool | isComplex (void) const |
Is this too complex to be a condition (BlockCondition) | |
virtual void | encodeHeader (Encoder &encoder) const |
Encode basic information as attributes. More... | |
virtual void | decodeHeader (Decoder &decoder) |
Decode basic information from element attributes. More... | |
void | encodeEdges (Encoder &encoder) const |
Encode edge information to a stream. More... | |
void | decodeEdges (Decoder &decoder, BlockMap &resolver) |
Restore edges from an encoded stream. More... | |
void | encode (Encoder &encoder) const |
Encode this to a stream. More... | |
void | decode (Decoder &decoder, BlockMap &resolver) |
Decode this from a stream. More... | |
const FlowBlock * | nextInFlow (void) const |
Return next block to be executed in flow. More... | |
void | setVisitCount (int4 i) |
Set the number of times this block has been visited. | |
int4 | getVisitCount (void) const |
Get the count of visits. | |
void | setGotoBranch (int4 i) |
Mark a goto branch. More... | |
void | setDefaultSwitch (int4 pos) |
Mark an edge as the switch default. More... | |
bool | isMark (void) const |
Return true if this block has been marked. | |
void | setMark (void) |
Mark this block. | |
void | clearMark (void) |
Clear any mark on this block. | |
void | setDonothingLoop (void) |
Label this as a do nothing loop. | |
void | setDead (void) |
Label this as dead. | |
bool | hasSpecialLabel (void) const |
Return true if this uses a different label. | |
bool | isJoined (void) const |
Return true if this is a joined basic block. | |
bool | isDuplicated (void) const |
Return true if this is a duplicated block. | |
void | setLoopExit (int4 i) |
Label the edge exiting this as a loop. | |
void | clearLoopExit (int4 i) |
Clear the loop exit edge. | |
void | setBackEdge (int4 i) |
Label the back edge of a loop. | |
bool | getFlipPath (void) const |
Have out edges been flipped. | |
bool | isJumpTarget (void) const |
Return true if non-fallthru jump flows into this. More... | |
FlowBlock * | getFalseOut (void) const |
Get the false output FlowBlock. | |
FlowBlock * | getTrueOut (void) const |
Get the true output FlowBlock. | |
FlowBlock * | getOut (int4 i) |
Get the i-th output FlowBlock. | |
const FlowBlock * | getOut (int4 i) const |
Get i-th output FlowBlock. | |
int4 | getOutRevIndex (int4 i) const |
Get the input index of the i-th output FlowBlock. | |
FlowBlock * | getIn (int4 i) |
Get the i-th input FlowBlock. | |
const FlowBlock * | getIn (int4 i) const |
Get the i-th input FlowBlock. | |
int4 | getInRevIndex (int4 i) const |
Get the output index of the i-th input FlowBlock. | |
const FlowBlock * | getFrontLeaf (void) const |
Get the first leaf FlowBlock. More... | |
FlowBlock * | getFrontLeaf (void) |
Get the first leaf FlowBlock. More... | |
int4 | calcDepth (const FlowBlock *leaf) const |
Get the depth of the given component FlowBlock. More... | |
bool | dominates (const FlowBlock *subBlock) const |
Does this block dominate the given block. More... | |
bool | restrictedByConditional (const FlowBlock *cond) const |
Check if the condition from the given block holds for this block. More... | |
int4 | sizeOut (void) const |
Get the number of out edges. | |
int4 | sizeIn (void) const |
Get the number of in edges. | |
bool | hasLoopIn (void) const |
Is there a looping edge coming into this block. More... | |
bool | hasLoopOut (void) const |
Is there a looping edge going out of this block. More... | |
bool | isLoopIn (int4 i) const |
Is the i-th incoming edge a loop edge. | |
bool | isLoopOut (int4 i) const |
Is the i-th outgoing edge a loop edge. | |
int4 | getInIndex (const FlowBlock *bl) const |
Get the incoming edge index for the given FlowBlock. More... | |
int4 | getOutIndex (const FlowBlock *bl) const |
Get the outgoing edge index for the given FlowBlock. More... | |
bool | isDefaultBranch (int4 i) const |
Is the i-th out edge the switch default edge. | |
bool | isLabelBumpUp (void) const |
Are labels for this printed by the parent. | |
bool | isUnstructuredTarget (void) const |
Is this the target of an unstructured goto. | |
bool | isInteriorGotoTarget (void) const |
Is there an unstructured goto to this block's interior. | |
bool | hasInteriorGoto (void) const |
Is there an unstructured goto out of this block's interior. | |
bool | isEntryPoint (void) const |
Is the entry point of the function. | |
bool | isSwitchOut (void) const |
Is this a switch block. | |
bool | isDonothingLoop (void) const |
Is this a do nothing block. | |
bool | isDead (void) const |
Is this block dead. | |
bool | isTreeEdgeIn (int4 i) const |
Is the i-th incoming edge part of the spanning tree. | |
bool | isBackEdgeIn (int4 i) const |
Is the i-th incoming edge a back edge. | |
bool | isBackEdgeOut (int4 i) const |
Is the i-th outgoing edge a back edge. | |
bool | isIrreducibleOut (int4 i) const |
Is the i-th outgoing edge an irreducible edge. | |
bool | isIrreducibleIn (int4 i) const |
Is the i-th incoming edge an irreducible edge. | |
bool | isDecisionOut (int4 i) const |
Can this and the i-th output be merged into a BlockIf or BlockList. | |
bool | isDecisionIn (int4 i) const |
Can this and the i-th input be merged into a BlockIf or BlockList. | |
bool | isLoopDAGOut (int4 i) const |
Is the i-th outgoing edge part of the DAG sub-graph. | |
bool | isLoopDAGIn (int4 i) const |
Is the i-th incoming edge part of the DAG sub-graph. | |
bool | isGotoIn (int4 i) const |
Is the i-th incoming edge unstructured. | |
bool | isGotoOut (int4 i) const |
Is the i-th outgoing edge unstructured. | |
JumpTable * | getJumptable (void) const |
Get the JumpTable associated this block. More... | |
Private Member Functions | |
void | findLoopVariable (PcodeOp *cbranch, BlockBasic *head, BlockBasic *tail, PcodeOp *lastOp) |
Find a loop variable. More... | |
PcodeOp * | findInitializer (BlockBasic *head, int4 slot) const |
Find the for-loop initializer op. More... | |
PcodeOp * | testTerminal (Funcdata &data, int4 slot) const |
Test that given statement is terminal and explicit. More... | |
bool | testIterateForm (void) const |
Return false if the iterate statement is of an unacceptable form. More... | |
Private Attributes | |
PcodeOp * | initializeOp |
Statement used as for loop initializer. | |
PcodeOp * | iterateOp |
Statement used as for loop iterator. | |
PcodeOp * | loopDef |
MULTIEQUAL merging loop variable. | |
Additional Inherited Members | |
Public Types inherited from ghidra::FlowBlock | |
enum | block_type { t_plain, t_basic, t_graph, t_copy, t_goto, t_multigoto, t_ls, t_condition, t_if, t_whiledo, t_dowhile, t_switch, t_infloop } |
The possible block types. | |
enum | block_flags { f_goto_goto = 1, f_break_goto = 2, f_continue_goto = 4, f_switch_out = 0x10, f_unstructured_targ = 0x20, f_mark = 0x80, f_mark2 = 0x100, f_entry_point = 0x200, f_interior_gotoout = 0x400, f_interior_gotoin = 0x800, f_label_bumpup = 0x1000, f_donothing_loop = 0x2000, f_dead = 0x4000, f_whiledo_overflow = 0x8000, f_flip_path = 0x10000, f_joined_block = 0x20000, f_duplicate_block = 0x40000 } |
Boolean properties of blocks. More... | |
enum | edge_flags { f_goto_edge = 1, f_loop_edge = 2, f_defaultswitch_edge = 4, f_irreducible = 8, f_tree_edge = 0x10, f_forward_edge = 0x20, f_cross_edge = 0x40, f_back_edge = 0x80, f_loop_exit_edge = 0x100 } |
Boolean properties on edges. More... | |
Static Public Member Functions inherited from ghidra::FlowBlock | |
static block_type | nameToType (const string &name) |
Get the block_type associated with a name string. More... | |
static string | typeToName (block_type bt) |
Get the name string associated with a block_type. More... | |
static bool | compareBlockIndex (const FlowBlock *bl1, const FlowBlock *bl2) |
Compare FlowBlock by index. More... | |
static bool | compareFinalOrder (const FlowBlock *bl1, const FlowBlock *bl2) |
Final FlowBlock comparison. More... | |
static FlowBlock * | findCommonBlock (FlowBlock *bl1, FlowBlock *bl2) |
Find the common dominator of two FlowBlocks. More... | |
static FlowBlock * | findCommonBlock (const vector< FlowBlock *> &blockSet) |
Find common dominator of multiple FlowBlocks. More... | |
Protected Member Functions inherited from ghidra::BlockGraph | |
void | swapBlocks (int4 i, int4 j) |
Swap the positions two component FlowBlocks. More... | |
Protected Member Functions inherited from ghidra::FlowBlock | |
void | setFlag (uint4 fl) |
Set a boolean property. | |
void | clearFlag (uint4 fl) |
Clear a boolean property. | |
Static Protected Member Functions inherited from ghidra::BlockGraph | |
static void | markCopyBlock (FlowBlock *bl, uint4 fl) |
Set properties on the first leaf FlowBlock. More... | |
A loop structure where the condition is checked at the top.
This has exactly two components: one conditional block which evaluates when the loop terminates, and one body block. The conditional block has two outgoing edges, one to the body block and one to the exit block. The body block has one outgoing edge back to the conditional block. The BlockWhileDo instance has exactly one outgoing edge.
Overflow syntax refers to the situation where there is a proper BlockWhileDo structure but the conditional block is too long or complicated to emit as a single conditional expression. An alternate while(true) { }
form is used instead.
If an iterator op is provided, the block will be printed using for loop syntax, for(i=0;i<10;++i)
where an initializer statement and iterator statement are printed alongside the condition statement. Otherwise, while loop syntax is used while(i<10)
|
inlinevirtual |
Emit the instructions in this FlowBlock as structured code.
This is the main entry point, at the control-flow level, for printing structured code.
lng | is the PrintLanguage that provides details of the high-level language being printed |
Reimplemented from ghidra::BlockGraph.
References ghidra::PrintLanguage::emitBlockWhileDo().
|
virtual |
Assume that finalTransform() has run and that all HighVariable merging has occurred. Do any final tests checking that the initialization and iteration statements are good. Extract initialization and iteration statements from their basic blocks.
data | is the function containing the loop |
Reimplemented from ghidra::BlockGraph.
References ghidra::BlockGraph::finalizePrinting(), and ghidra::Funcdata::opMarkNonPrinting().
|
virtual |
Determine if this block can be printed as a for loop, with an initializer statement extracted from the previous block, and an iterator statement extracted from the body.
data | is the function containing this loop |
Reimplemented from ghidra::BlockGraph.
References ghidra::Architecture::analyze_for_loops, ghidra::PcodeOp::code(), ghidra::CPUI_CBRANCH, ghidra::BlockGraph::finalTransform(), ghidra::Funcdata::getArch(), ghidra::FlowBlock::getOut(), ghidra::FlowBlock::getOutRevIndex(), ghidra::PcodeOp::getParent(), ghidra::BlockBasic::getType(), ghidra::PcodeOp::isBranch(), ghidra::Funcdata::opInsertAfter(), ghidra::Funcdata::opUninsert(), ghidra::PcodeOp::previousOp(), ghidra::FlowBlock::sizeOut(), and ghidra::FlowBlock::subBlock().
|
private |
Find the for-loop initializer op.
Given a control flow loop, try to find a putative initializer PcodeOp for the loop variable. The initializer must be read by read by loopDef and by in a block that flows only into the loop. If an initializer is found, then initializeOp is set and the lastOp (not including a branch) in the initializer block is returned. Otherwise null is returned.
head | is the head block of the loop |
slot | is the block input coming from the loop tail |
References ghidra::Varnode::getDef(), ghidra::FlowBlock::getIn(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::isBranch(), ghidra::PcodeOp::isMarker(), ghidra::Varnode::isWritten(), ghidra::FlowBlock::lastOp(), ghidra::PcodeOp::previousOp(), ghidra::FlowBlock::sizeIn(), and ghidra::FlowBlock::sizeOut().
|
private |
Find a loop variable.
Try to find a Varnode that represents the controlling loop variable for this loop. The Varnode must be:
If the loop variable is found, this routine sets the iterateOp and the loopDef.
cbranch | is the CBRANCH implementing the loop exit |
head | is the head basic-block of the loop |
tail | is the tail basic-block of the loop |
lastOp | is the precomputed last PcodeOp of tail that isn't a BRANCH |
References ghidra::PcodeOp::code(), ghidra::CPUI_MULTIEQUAL, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::FlowBlock::getOutRevIndex(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::isCall(), ghidra::PcodeOp::isMarker(), ghidra::PcodeOp::isMoveable(), ghidra::Varnode::isWritten(), ghidra::PcodeOp::numInput(), ghidra::PcodeOpNode::op, and ghidra::PcodeOpNode::slot.
|
virtual |
Let hierarchical blocks steal labels of their (first) components.
bump | if true, mark that labels for this block are printed by somebody higher in hierarchy |
Reimplemented from ghidra::BlockGraph.
References ghidra::BlockGraph::markLabelBumpUp().
Get the leaf FlowBlock that will execute after the given FlowBlock.
Within the hierarchy of this FlowBlock, assume the given FlowBlock will fall-thru in its execution at some point. Return the first leaf block (BlockBasic or BlockCopy) that will execute after the given FlowBlock completes, assuming this is a unique block.
bl | is the given FlowBlock |
Reimplemented from ghidra::BlockGraph.
References ghidra::FlowBlock::getFrontLeaf().
|
virtual |
Print a simple description of this to stream.
Only print a header for this single block
s | is the output stream |
Reimplemented from ghidra::FlowBlock.
References ghidra::FlowBlock::printHeader().
|
private |
Return false if the iterate statement is of an unacceptable form.
Make sure the loop variable is involved as input in the iterator statement.
References ghidra::Varnode::getDef(), ghidra::Varnode::getHigh(), ghidra::Varnode::isAnnotation(), ghidra::Varnode::isExplicit(), and ghidra::Varnode::isWritten().
Test that given statement is terminal and explicit.
For-loop initializer or iterator statements must be the final statement in their respective basic block. This method tests that iterateOp/initializeOp (specified by slot) is the root of or can be turned into the root of a terminal statement. The root output must be an explicit variable being read by the loopDef MULTIEQUAL at the top of the loop. If the root is not the last PcodeOp in the block, an attempt is made to move it. Return the root PcodeOp if all these conditions are met, otherwise return null.
data | is the function containing the while loop |
slot | is the slot read by loopDef from the output of the statement |
References ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::FlowBlock::getIn(), ghidra::PcodeOp::getParent(), ghidra::FlowBlock::getParent(), ghidra::PcodeOp::isBranch(), ghidra::Varnode::isExplicit(), ghidra::Varnode::isWritten(), ghidra::BlockBasic::lastOp(), ghidra::Funcdata::moveRespectingCover(), ghidra::PcodeOp::notPrinted(), and ghidra::PcodeOp::previousOp().