mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 12:11:55 +00:00
Merge remote-tracking branch 'origin/GP-4582_SwitchGotoLoop' into patch
(Closes #6282)
This commit is contained in:
commit
6ede2b498f
@ -1674,13 +1674,20 @@ BlockMultiGoto *BlockGraph::newBlockMultiGoto(FlowBlock *bl,int4 outedge)
|
||||
}
|
||||
else {
|
||||
ret = new BlockMultiGoto(bl);
|
||||
int4 origSizeOut = bl->sizeOut();
|
||||
vector<FlowBlock *> nodes;
|
||||
nodes.push_back(bl);
|
||||
identifyInternal(ret,nodes);
|
||||
addBlock(ret);
|
||||
ret->addEdge(targetbl);
|
||||
if (targetbl != bl) // If the target is itself, edge is already removed by identifyInternal
|
||||
removeEdge(ret,targetbl);
|
||||
if (targetbl != bl) {
|
||||
if (ret->sizeOut() != origSizeOut) { // If there are less out edges after identifyInternal
|
||||
// it must have collapsed a self edge (switch out edges are already deduped)
|
||||
ret->forceOutputNum(ret->sizeOut()+1); // preserve the self edge (it is not the goto edge)
|
||||
}
|
||||
removeEdge(ret,targetbl); // Remove the edge to the goto target
|
||||
}
|
||||
// else -- the goto edge is a self edge and will get removed by identifyInternal
|
||||
if (isdefaultedge)
|
||||
ret->setDefaultGoto();
|
||||
}
|
||||
|
@ -84,12 +84,14 @@ void LoopBody::extendToContainer(const LoopBody &container,vector<FlowBlock *> &
|
||||
}
|
||||
}
|
||||
|
||||
/// This updates the \b head and \b tail nodes to FlowBlock in the current collapsed graph.
|
||||
/// This returns the first \b tail and passes back the head.
|
||||
/// \param top is where \b head is passed back
|
||||
/// This updates the \b head node to the FlowBlock in the current collapsed graph.
|
||||
/// The \b tail nodes are also updated until one is found that has not collapsed into \b head.
|
||||
/// This first updated \b tail is returned. The loop may still exist as a \b head node with an
|
||||
/// out edge back into itself, in which case \b head is returned as the active \b tail.
|
||||
/// If the loop has been completely collapsed, null is returned.
|
||||
/// \param graph is the containing control-flow structure
|
||||
/// \return the current loop \b head
|
||||
FlowBlock *LoopBody::getCurrentBounds(FlowBlock **top,FlowBlock *graph)
|
||||
/// \return the current loop \b tail or null
|
||||
FlowBlock *LoopBody::update(FlowBlock *graph)
|
||||
|
||||
{
|
||||
while(head->getParent() != graph)
|
||||
@ -101,10 +103,13 @@ FlowBlock *LoopBody::getCurrentBounds(FlowBlock **top,FlowBlock *graph)
|
||||
bottom = bottom->getParent();
|
||||
tails[i] = bottom;
|
||||
if (bottom != head) { // If the loop hasn't been fully collapsed yet
|
||||
*top = head;
|
||||
return bottom;
|
||||
}
|
||||
}
|
||||
for(int4 i=head->sizeOut()-1;i>=0;--i) {
|
||||
if (head->getOut(i) == head) // Check for head looping with itself
|
||||
return head;
|
||||
}
|
||||
return (FlowBlock *)0;
|
||||
}
|
||||
|
||||
@ -391,17 +396,17 @@ void LoopBody::emitLikelyEdges(list<FloatingEdge> &likely,FlowBlock *graph)
|
||||
break;
|
||||
}
|
||||
}
|
||||
likely.push_back(FloatingEdge(inbl,outbl));
|
||||
likely.emplace_back(inbl,outbl);
|
||||
}
|
||||
for(int4 i=tails.size()-1;i>=0;--i) { // Go in reverse order, to put out less preferred back-edges first
|
||||
if ((holdin!=(FlowBlock *)0)&&(i==0))
|
||||
likely.push_back(FloatingEdge(holdin,holdout)); // Put in delayed exit, right before final backedge
|
||||
likely.emplace_back(holdin,holdout); // Put in delayed exit, right before final backedge
|
||||
FlowBlock *tail = tails[i];
|
||||
int4 sizeout = tail->sizeOut();
|
||||
for(int4 j=0;j<sizeout;++j) {
|
||||
FlowBlock *bl = tail->getOut(j);
|
||||
if (bl == head) // If out edge to head (back-edge for this loop)
|
||||
likely.push_back(FloatingEdge(tail,head)); // emit it
|
||||
likely.emplace_back(tail,head); // emit it
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -652,7 +657,7 @@ void TraceDAG::removeTrace(BlockTrace *trace)
|
||||
|
||||
{
|
||||
// Record that we should now treat this edge like goto
|
||||
likelygoto.push_back(FloatingEdge(trace->bottom,trace->destnode)); // Create goto record
|
||||
likelygoto.emplace_back(trace->bottom,trace->destnode); // Create goto record
|
||||
trace->destnode->setVisitCount( trace->destnode->getVisitCount() + trace->edgelump ); // Ignore edge(s)
|
||||
|
||||
BranchPoint *parentbp = trace->top;
|
||||
@ -1194,11 +1199,21 @@ bool CollapseStructure::updateLoopBody(void)
|
||||
FlowBlock *loopbottom = (FlowBlock *)0;
|
||||
FlowBlock *looptop = (FlowBlock *)0;
|
||||
while (loopbodyiter != loopbody.end()) { // Last innermost loop
|
||||
loopbottom = (*loopbodyiter).getCurrentBounds(&looptop,&graph);
|
||||
LoopBody &curBody( *loopbodyiter );
|
||||
loopbottom = curBody.update(&graph);
|
||||
if (loopbottom != (FlowBlock *)0) {
|
||||
if ((!likelylistfull) ||
|
||||
(likelyiter != likelygoto.end())) // Reaching here means, we removed edges but loop still didn't collapse
|
||||
looptop = curBody.getHead();
|
||||
if (loopbottom == looptop) { // Check for single node looping back to itself
|
||||
// If sizeout is 1 or 2, the loop would have collapsed, so the node is likely a switch.
|
||||
likelygoto.clear();
|
||||
likelygoto.emplace_back(looptop,looptop); // Mark the loop edge as a goto
|
||||
likelyiter = likelygoto.begin();
|
||||
likelylistfull = true;
|
||||
return true;
|
||||
}
|
||||
if (!likelylistfull || likelyiter != likelygoto.end()) {
|
||||
break; // Loop still exists
|
||||
}
|
||||
}
|
||||
++loopbodyiter;
|
||||
likelylistfull = false; // Need to generate likely list for new loopbody (or no loopbody)
|
||||
|
@ -55,7 +55,7 @@ class LoopBody {
|
||||
public:
|
||||
LoopBody(FlowBlock *h) { head=h; immed_container = (LoopBody *)0; depth=0; } ///< Construct with a loop head
|
||||
FlowBlock *getHead(void) const { return head; } ///< Return the head FlowBlock of the loop
|
||||
FlowBlock *getCurrentBounds(FlowBlock **top,FlowBlock *graph); ///< Return current loop bounds (\b head and \b bottom).
|
||||
FlowBlock *update(FlowBlock *graph); ///< Update loop body to current view
|
||||
void addTail(FlowBlock *bl) { tails.push_back(bl); } ///< Add a \e tail to the loop
|
||||
FlowBlock *getExitBlock(void) const { return exitblock; } ///< Get the exit FlowBlock or NULL
|
||||
void findBase(vector<FlowBlock *> &body); ///< Mark the body FlowBlocks of \b this loop
|
||||
|
Loading…
Reference in New Issue
Block a user