decompiler
1.0.0
|
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 | |
Funcdata & | data |
The function being analyzed. | |
BlockBasic * | block1 |
Side 1 of the (putative) split. | |
BlockBasic * | block2 |
Side 2 of the (putative) split. | |
BlockBasic * | exita |
First (common) exit point. | |
BlockBasic * | exitb |
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. | |
PcodeOp * | cbranch1 |
CBRANCH at bottom of block1. | |
PcodeOp * | cbranch2 |
CBRANCH at bottom of block2. | |
BlockBasic * | joinblock |
The new joined condition block. | |
map< MergePair, Varnode * > | mergeneed |
Map from the MergePair of Varnodes to the merged Varnode. | |
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.
|
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.
exit | is the exit block |
in1 | is the index of the edge coming from block1 |
in2 | is 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().
|
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.
exit | is the exit block |
in1 | is the index of the incoming edge from block1 |
in2 | is 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().
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().
|
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.
References ghidra::PcodeOp::code(), ghidra::CPUI_CBRANCH, ghidra::CPUI_COPY, ghidra::CPUI_SUBPIECE, ghidra::Varnode::getDef(), ghidra::Varnode::isSpacebase(), and ghidra::Varnode::isWritten().
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.
b1 | is the BlockBasic exhibiting one side of the split |
b2 | is the BlockBasic on the other side of the split |
References ghidra::FlowBlock::getOut(), and ghidra::FlowBlock::getOutRevIndex().
Referenced by ghidra::ActionNodeJoin::apply().
|
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().