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

Discover and eliminate split conditions. More...

#include <blockaction.hh>

Classes

struct  MergePair
 A pair of Varnode objects that have been split (and should be merged) More...
 

Public Member Functions

 ConditionalJoin (Funcdata &fd)
 Constructor.
 
bool match (BlockBasic *b1, BlockBasic *b2)
 Test blocks for the merge condition. More...
 
void execute (void)
 Execute the merge. More...
 
void clear (void)
 Clear for a new test.
 

Private Member Functions

bool findDups (void)
 Search for duplicate conditional expressions. More...
 
void checkExitBlock (BlockBasic *exit, int4 in1, int4 in2)
 Look for additional Varnode pairs in an exit block that need to be merged. More...
 
void cutDownMultiequals (BlockBasic *exit, int4 in1, int4 in2)
 Substitute new joined Varnode in the given exit block. More...
 
void setupMultiequals (void)
 Join the Varnodes in the new joinblock. More...
 
void moveCbranch (void)
 Remove the other CBRANCH.
 

Private Attributes

Funcdatadata
 The function being analyzed.
 
BlockBasicblock1
 Side 1 of the (putative) split.
 
BlockBasicblock2
 Side 2 of the (putative) split.
 
BlockBasicexita
 First (common) exit point.
 
BlockBasicexitb
 Second (common) exit point.
 
int4 a_in1
 In edge of exita coming from block1.
 
int4 a_in2
 In edge of exita coming from block2.
 
int4 b_in1
 In edge of exitb coming from block1.
 
int4 b_in2
 In edge of exitb coming from block2.
 
PcodeOpcbranch1
 CBRANCH at bottom of block1.
 
PcodeOpcbranch2
 CBRANCH at bottom of block2.
 
BlockBasicjoinblock
 The new joined condition block.
 
map< MergePair, Varnode * > mergeneed
 Map from the MergePair of Varnodes to the merged Varnode.
 

Detailed Description

Discover and eliminate split conditions.

A split condition is when a conditional expression, resulting in a CBRANCH, is duplicated across two blocks that would otherwise merge. Instead of a single conditional in a merged block, there are two copies of the conditional, two splitting blocks and no direct merge.

Member Function Documentation

◆ checkExitBlock()

void ghidra::ConditionalJoin::checkExitBlock ( BlockBasic exit,
int4  in1,
int4  in2 
)
private

Look for additional Varnode pairs in an exit block that need to be merged.

Varnodes that are merged in the exit block flowing from block1 and block2 will need to merged in the new joined block. Add these pairs to the mergeneed map.

Parameters
exitis the exit block
in1is the index of the edge coming from block1
in2is the index of the edge coming from block2

References ghidra::BlockBasic::beginOp(), ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_MULTIEQUAL, ghidra::BlockBasic::endOp(), and ghidra::PcodeOp::getIn().

◆ cutDownMultiequals()

void ghidra::ConditionalJoin::cutDownMultiequals ( BlockBasic exit,
int4  in1,
int4  in2 
)
private

Substitute new joined Varnode in the given exit block.

For any MULTIEQUAL in the exit, given two input slots, remove one Varnode, and substitute the other Varnode from the corresponding Varnode in the mergeneed map.

Parameters
exitis the exit block
in1is the index of the incoming edge from block1
in2is the index of the incoming edge from block2

References ghidra::BlockBasic::beginOp(), ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_MULTIEQUAL, ghidra::BlockBasic::endOp(), ghidra::PcodeOp::getIn(), and ghidra::PcodeOp::numInput().

◆ execute()

void ghidra::ConditionalJoin::execute ( void  )

Execute the merge.

All the conditions have been met. Go ahead and do the join.

Referenced by ghidra::ActionNodeJoin::apply().

◆ findDups()

bool ghidra::ConditionalJoin::findDups ( void  )
private

Search for duplicate conditional expressions.

Given two conditional blocks, determine if the corresponding conditional expressions are equivalent, up to Varnodes that need to be merged. Any Varnode pairs that need to be merged are put in the mergeneed map.

Returns
true if there are matching conditions

References ghidra::PcodeOp::code(), ghidra::CPUI_CBRANCH, ghidra::CPUI_COPY, ghidra::CPUI_SUBPIECE, ghidra::Varnode::getDef(), ghidra::Varnode::isSpacebase(), and ghidra::Varnode::isWritten().

◆ match()

bool ghidra::ConditionalJoin::match ( BlockBasic b1,
BlockBasic b2 
)

Test blocks for the merge condition.

Given a pair of conditional blocks, make sure that they match the split conditions necessary for merging and set up to do the merge. If the conditions are not met, this method cleans up so that additional calls can be made.

Parameters
b1is the BlockBasic exhibiting one side of the split
b2is the BlockBasic on the other side of the split
Returns
true if the conditions for merging are met

References ghidra::FlowBlock::getOut(), and ghidra::FlowBlock::getOutRevIndex().

Referenced by ghidra::ActionNodeJoin::apply().

◆ setupMultiequals()

void ghidra::ConditionalJoin::setupMultiequals ( void  )
private

Join the Varnodes in the new joinblock.

Create a new Varnode and its defining MULTIEQUAL operation for each MergePair in the map.

References ghidra::CPUI_MULTIEQUAL, and ghidra::Varnode::getSize().


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