mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-5915 Fix bug in ConditionalJoin
This commit is contained in:
parent
3e550cf08f
commit
29b7cb6552
4 changed files with 83 additions and 17 deletions
|
@ -638,6 +638,17 @@ JumpTable *FlowBlock::getJumptable(void) const
|
||||||
return jt;
|
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.
|
/// Given a string describing a FlowBlock type, return the block_type.
|
||||||
/// This is currently only used by the decode() process.
|
/// This is currently only used by the decode() process.
|
||||||
/// TODO: Fill in the remaining names and types
|
/// TODO: Fill in the remaining names and types
|
||||||
|
@ -1293,8 +1304,24 @@ void BlockGraph::printRaw(ostream &s) const
|
||||||
|
|
||||||
printHeader(s);
|
printHeader(s);
|
||||||
s << endl;
|
s << endl;
|
||||||
for(iter=list.begin();iter!=list.end();++iter)
|
if (list.empty()) return;
|
||||||
(*iter)->printRaw(s);
|
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
|
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.
|
/// \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
|
/// 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
|
/// \param s is the given stream to write to
|
||||||
virtual void printRaw(ostream &s) const {}
|
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
|
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
|
/// \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 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
|
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
|
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 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 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
|
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 scopeBreak(int4 curexit,int4 curloopexit);
|
||||||
virtual void printTree(ostream &s,int4 level) const;
|
virtual void printTree(ostream &s,int4 level) const;
|
||||||
virtual void printRaw(ostream &s) 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 void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); }
|
||||||
virtual PcodeOp *firstOp(void) const;
|
virtual PcodeOp *firstOp(void) const;
|
||||||
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
|
||||||
|
@ -473,6 +483,7 @@ public:
|
||||||
virtual void decodeBody(Decoder &decoder);
|
virtual void decodeBody(Decoder &decoder);
|
||||||
virtual void printHeader(ostream &s) const;
|
virtual void printHeader(ostream &s) const;
|
||||||
virtual void printRaw(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 void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
|
||||||
virtual const FlowBlock *getExitLeaf(void) const { return this; }
|
virtual const FlowBlock *getExitLeaf(void) const { return this; }
|
||||||
virtual PcodeOp *firstOp(void) const;
|
virtual PcodeOp *firstOp(void) const;
|
||||||
|
@ -515,6 +526,7 @@ public:
|
||||||
virtual void printHeader(ostream &s) const;
|
virtual void printHeader(ostream &s) const;
|
||||||
virtual void printTree(ostream &s,int4 level) const;
|
virtual void printTree(ostream &s,int4 level) const;
|
||||||
virtual void printRaw(ostream &s) const { copy->printRaw(s); }
|
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 void emit(PrintLanguage *lng) const { lng->emitBlockCopy(this); }
|
||||||
virtual const FlowBlock *getExitLeaf(void) const { return this; }
|
virtual const FlowBlock *getExitLeaf(void) const { return this; }
|
||||||
virtual PcodeOp *firstOp(void) const { return copy->firstOp(); }
|
virtual PcodeOp *firstOp(void) const { return copy->firstOp(); }
|
||||||
|
|
|
@ -2074,18 +2074,10 @@ bool ConditionalJoin::match(BlockBasic *b1,BlockBasic *b2)
|
||||||
exita = (BlockBasic *)block1->getOut(0);
|
exita = (BlockBasic *)block1->getOut(0);
|
||||||
exitb = (BlockBasic *)block1->getOut(1);
|
exitb = (BlockBasic *)block1->getOut(1);
|
||||||
if (exita == exitb) return false;
|
if (exita == exitb) return false;
|
||||||
if (block2->getOut(0) == exita) {
|
if (block2->getOut(0) != exita) return false; // False exits must match
|
||||||
if (block2->getOut(1) != exitb) return false;
|
if (block2->getOut(1) != exitb) return false; // True exits must match
|
||||||
a_in2 = block2->getOutRevIndex(0);
|
a_in2 = block2->getOutRevIndex(0);
|
||||||
b_in2 = block2->getOutRevIndex(1);
|
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);
|
a_in1 = block1->getOutRevIndex(0);
|
||||||
b_in1 = block1->getOutRevIndex(1);
|
b_in1 = block1->getOutRevIndex(1);
|
||||||
|
|
||||||
|
|
|
@ -591,7 +591,12 @@ void TypeOpBranch::printRaw(ostream &s,const PcodeOp *op)
|
||||||
|
|
||||||
{
|
{
|
||||||
s << name << ' ';
|
s << name << ' ';
|
||||||
Varnode::printRaw(s,op->getIn(0));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeOpCbranch::TypeOpCbranch(TypeFactory *t) : TypeOp(t,CPUI_CBRANCH,"goto")
|
TypeOpCbranch::TypeOpCbranch(TypeFactory *t) : TypeOp(t,CPUI_CBRANCH,"goto")
|
||||||
|
@ -617,13 +622,25 @@ void TypeOpCbranch::printRaw(ostream &s,const PcodeOp *op)
|
||||||
|
|
||||||
{
|
{
|
||||||
s << name << ' ';
|
s << name << ' ';
|
||||||
Varnode::printRaw(s,op->getIn(0)); // Print the distant (non-fallthru) destination
|
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 (";
|
s << " if (";
|
||||||
Varnode::printRaw(s,op->getIn(1));
|
Varnode::printRaw(s,op->getIn(1));
|
||||||
if (op->isBooleanFlip()^op->isFallthruTrue())
|
if (op->isBooleanFlip())
|
||||||
s << " == 0)";
|
s << " == 0)";
|
||||||
else
|
else
|
||||||
s << " != 0)";
|
s << " != 0)";
|
||||||
|
if (falseOut != (FlowBlock *)0) {
|
||||||
|
s << " else ";
|
||||||
|
falseOut->printShortHeader(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeOpBranchind::TypeOpBranchind(TypeFactory *t) : TypeOp(t,CPUI_BRANCHIND,"switch")
|
TypeOpBranchind::TypeOpBranchind(TypeFactory *t) : TypeOp(t,CPUI_BRANCHIND,"switch")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue