mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-5915_ConditionalJoinFix' into
patch (Closes #8310)
This commit is contained in:
commit
8055da80b8
4 changed files with 83 additions and 17 deletions
|
@ -638,6 +638,17 @@ JumpTable *FlowBlock::getJumptable(void) const
|
|||
return jt;
|
||||
}
|
||||
|
||||
/// Print a single unique identifier for \b this block
|
||||
/// \param s is the output stream
|
||||
void FlowBlock::printShortHeader(ostream &s) const
|
||||
|
||||
{
|
||||
s << "Block_" << dec << index;
|
||||
if (!getStart().isInvalid()) {
|
||||
s << ':' << getStart();
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a string describing a FlowBlock type, return the block_type.
|
||||
/// This is currently only used by the decode() process.
|
||||
/// TODO: Fill in the remaining names and types
|
||||
|
@ -1293,8 +1304,24 @@ void BlockGraph::printRaw(ostream &s) const
|
|||
|
||||
printHeader(s);
|
||||
s << endl;
|
||||
for(iter=list.begin();iter!=list.end();++iter)
|
||||
(*iter)->printRaw(s);
|
||||
if (list.empty()) return;
|
||||
iter = list.begin();
|
||||
FlowBlock *lastBl = *iter;
|
||||
++iter;
|
||||
lastBl->printRaw(s);
|
||||
for(;iter!=list.end();++iter) {
|
||||
FlowBlock *curBl = *iter;
|
||||
lastBl->printRawImpliedGoto(s, curBl);
|
||||
curBl->printRaw(s);
|
||||
lastBl = curBl;
|
||||
}
|
||||
}
|
||||
|
||||
void BlockGraph::printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const
|
||||
|
||||
{
|
||||
if (list.empty()) return;
|
||||
list.back()->printRawImpliedGoto(s, nextBlock);
|
||||
}
|
||||
|
||||
PcodeOp *BlockGraph::firstOp(void) const
|
||||
|
@ -2658,6 +2685,24 @@ void BlockBasic::printRaw(ostream &s) const
|
|||
}
|
||||
}
|
||||
|
||||
void BlockBasic::printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const
|
||||
|
||||
{
|
||||
if (sizeOut() != 1) return;
|
||||
const FlowBlock *outBlock = getOut(0);
|
||||
if (nextBlock->getType() != t_basic) {
|
||||
nextBlock = nextBlock->getFrontLeaf();
|
||||
if (nextBlock == (const FlowBlock *)0) return;
|
||||
nextBlock = nextBlock->subBlock(0);
|
||||
}
|
||||
if (getOut(0) == nextBlock) return;
|
||||
if (!op.empty() && op.back()->isBranch()) return;
|
||||
getStop().printRaw(s);
|
||||
s << ": \t[ goto ";
|
||||
outBlock->printShortHeader(s);
|
||||
s << " ]" << endl;
|
||||
}
|
||||
|
||||
/// \brief Check for values created in \b this block that flow outside the block.
|
||||
///
|
||||
/// The block can calculate a value for a BRANCHIND or CBRANCH and can copy values and this method will still
|
||||
|
|
|
@ -210,6 +210,14 @@ public:
|
|||
/// \param s is the given stream to write to
|
||||
virtual void printRaw(ostream &s) const {}
|
||||
|
||||
/// \brief If the \e out block of \b this is not the given next block, print an implied \b goto to the out block
|
||||
///
|
||||
/// In order to see where \b this block is flowing to, if there is no explicit branch op, and if the next block
|
||||
/// being printed is \e not the fallthru branch, print the destination block as an implied \b goto op.
|
||||
/// \param s is the output stream
|
||||
/// \param nextBlock is the given nextBlock being printed
|
||||
virtual void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const {}
|
||||
|
||||
virtual void emit(PrintLanguage *lng) const; ///<Emit the instructions in \b this FlowBlock as structured code
|
||||
|
||||
/// \brief Get the leaf block from which \b this block exits
|
||||
|
@ -338,6 +346,7 @@ public:
|
|||
bool isGotoIn(int4 i) const { return ((intothis[i].label & (f_irreducible|f_goto_edge))!=0); } ///< Is the i-th incoming edge unstructured
|
||||
bool isGotoOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_goto_edge))!=0); } ///< Is the i-th outgoing edge unstructured
|
||||
JumpTable *getJumptable(void) const; ///< Get the JumpTable associated \b this block
|
||||
void printShortHeader(ostream &s) const; ///< Print a short identifier for the block
|
||||
static block_type nameToType(const string &name); ///< Get the block_type associated with a name string
|
||||
static string typeToName(block_type bt); ///< Get the name string associated with a block_type
|
||||
static bool compareBlockIndex(const FlowBlock *bl1,const FlowBlock *bl2); ///< Compare FlowBlock by index
|
||||
|
@ -380,6 +389,7 @@ public:
|
|||
virtual void scopeBreak(int4 curexit,int4 curloopexit);
|
||||
virtual void printTree(ostream &s,int4 level) const;
|
||||
virtual void printRaw(ostream &s) const;
|
||||
void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const;
|
||||
virtual void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); }
|
||||
virtual PcodeOp *firstOp(void) const;
|
||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||
|
@ -473,6 +483,7 @@ public:
|
|||
virtual void decodeBody(Decoder &decoder);
|
||||
virtual void printHeader(ostream &s) const;
|
||||
virtual void printRaw(ostream &s) const;
|
||||
virtual void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const;
|
||||
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
|
||||
virtual const FlowBlock *getExitLeaf(void) const { return this; }
|
||||
virtual PcodeOp *firstOp(void) const;
|
||||
|
@ -515,6 +526,7 @@ public:
|
|||
virtual void printHeader(ostream &s) const;
|
||||
virtual void printTree(ostream &s,int4 level) const;
|
||||
virtual void printRaw(ostream &s) const { copy->printRaw(s); }
|
||||
virtual void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const { copy->printRawImpliedGoto(s, nextBlock); }
|
||||
virtual void emit(PrintLanguage *lng) const { lng->emitBlockCopy(this); }
|
||||
virtual const FlowBlock *getExitLeaf(void) const { return this; }
|
||||
virtual PcodeOp *firstOp(void) const { return copy->firstOp(); }
|
||||
|
|
|
@ -2074,18 +2074,10 @@ bool ConditionalJoin::match(BlockBasic *b1,BlockBasic *b2)
|
|||
exita = (BlockBasic *)block1->getOut(0);
|
||||
exitb = (BlockBasic *)block1->getOut(1);
|
||||
if (exita == exitb) return false;
|
||||
if (block2->getOut(0) == exita) {
|
||||
if (block2->getOut(1) != exitb) return false;
|
||||
if (block2->getOut(0) != exita) return false; // False exits must match
|
||||
if (block2->getOut(1) != exitb) return false; // True exits must match
|
||||
a_in2 = block2->getOutRevIndex(0);
|
||||
b_in2 = block2->getOutRevIndex(1);
|
||||
}
|
||||
else if (block2->getOut(0) == exitb) {
|
||||
if (block2->getOut(1) != exita) return false;
|
||||
a_in2 = block2->getOutRevIndex(1);
|
||||
b_in2 = block2->getOutRevIndex(0);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
a_in1 = block1->getOutRevIndex(0);
|
||||
b_in1 = block1->getOutRevIndex(1);
|
||||
|
||||
|
|
|
@ -591,6 +591,11 @@ void TypeOpBranch::printRaw(ostream &s,const PcodeOp *op)
|
|||
|
||||
{
|
||||
s << name << ' ';
|
||||
const BlockBasic *parent = op->getParent();
|
||||
if (parent != (const BlockBasic *)0 && parent->sizeOut() == 1) {
|
||||
parent->getOut(0)->printShortHeader(s);
|
||||
}
|
||||
else
|
||||
Varnode::printRaw(s,op->getIn(0));
|
||||
}
|
||||
|
||||
|
@ -617,13 +622,25 @@ void TypeOpCbranch::printRaw(ostream &s,const PcodeOp *op)
|
|||
|
||||
{
|
||||
s << name << ' ';
|
||||
const BlockBasic *parent = op->getParent();
|
||||
FlowBlock *falseOut = (FlowBlock *)0;
|
||||
if (parent != (const BlockBasic *)0 && parent->sizeOut() == 2) {
|
||||
FlowBlock *trueOut = parent->getTrueOut();
|
||||
falseOut = parent->getFalseOut();
|
||||
trueOut->printShortHeader(s);
|
||||
}
|
||||
else
|
||||
Varnode::printRaw(s,op->getIn(0)); // Print the distant (non-fallthru) destination
|
||||
s << " if (";
|
||||
Varnode::printRaw(s,op->getIn(1));
|
||||
if (op->isBooleanFlip()^op->isFallthruTrue())
|
||||
if (op->isBooleanFlip())
|
||||
s << " == 0)";
|
||||
else
|
||||
s << " != 0)";
|
||||
if (falseOut != (FlowBlock *)0) {
|
||||
s << " else ";
|
||||
falseOut->printShortHeader(s);
|
||||
}
|
||||
}
|
||||
|
||||
TypeOpBranchind::TypeOpBranchind(TypeFactory *t) : TypeOp(t,CPUI_BRANCHIND,"switch")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue