mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/GP-4582_SwitchGotoLoop' into patch
(Closes #6282)
This commit is contained in:
commit
6ede2b498f
3 changed files with 38 additions and 16 deletions
|
@ -1674,13 +1674,20 @@ BlockMultiGoto *BlockGraph::newBlockMultiGoto(FlowBlock *bl,int4 outedge)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = new BlockMultiGoto(bl);
|
ret = new BlockMultiGoto(bl);
|
||||||
|
int4 origSizeOut = bl->sizeOut();
|
||||||
vector<FlowBlock *> nodes;
|
vector<FlowBlock *> nodes;
|
||||||
nodes.push_back(bl);
|
nodes.push_back(bl);
|
||||||
identifyInternal(ret,nodes);
|
identifyInternal(ret,nodes);
|
||||||
addBlock(ret);
|
addBlock(ret);
|
||||||
ret->addEdge(targetbl);
|
ret->addEdge(targetbl);
|
||||||
if (targetbl != bl) // If the target is itself, edge is already removed by identifyInternal
|
if (targetbl != bl) {
|
||||||
removeEdge(ret,targetbl);
|
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)
|
if (isdefaultedge)
|
||||||
ret->setDefaultGoto();
|
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 updates the \b head node to the FlowBlock in the current collapsed graph.
|
||||||
/// This returns the first \b tail and passes back the head.
|
/// The \b tail nodes are also updated until one is found that has not collapsed into \b head.
|
||||||
/// \param top is where \b head is passed back
|
/// 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
|
/// \param graph is the containing control-flow structure
|
||||||
/// \return the current loop \b head
|
/// \return the current loop \b tail or null
|
||||||
FlowBlock *LoopBody::getCurrentBounds(FlowBlock **top,FlowBlock *graph)
|
FlowBlock *LoopBody::update(FlowBlock *graph)
|
||||||
|
|
||||||
{
|
{
|
||||||
while(head->getParent() != graph)
|
while(head->getParent() != graph)
|
||||||
|
@ -101,10 +103,13 @@ FlowBlock *LoopBody::getCurrentBounds(FlowBlock **top,FlowBlock *graph)
|
||||||
bottom = bottom->getParent();
|
bottom = bottom->getParent();
|
||||||
tails[i] = bottom;
|
tails[i] = bottom;
|
||||||
if (bottom != head) { // If the loop hasn't been fully collapsed yet
|
if (bottom != head) { // If the loop hasn't been fully collapsed yet
|
||||||
*top = head;
|
|
||||||
return bottom;
|
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;
|
return (FlowBlock *)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,17 +396,17 @@ void LoopBody::emitLikelyEdges(list<FloatingEdge> &likely,FlowBlock *graph)
|
||||||
break;
|
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
|
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))
|
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];
|
FlowBlock *tail = tails[i];
|
||||||
int4 sizeout = tail->sizeOut();
|
int4 sizeout = tail->sizeOut();
|
||||||
for(int4 j=0;j<sizeout;++j) {
|
for(int4 j=0;j<sizeout;++j) {
|
||||||
FlowBlock *bl = tail->getOut(j);
|
FlowBlock *bl = tail->getOut(j);
|
||||||
if (bl == head) // If out edge to head (back-edge for this loop)
|
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
|
// 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)
|
trace->destnode->setVisitCount( trace->destnode->getVisitCount() + trace->edgelump ); // Ignore edge(s)
|
||||||
|
|
||||||
BranchPoint *parentbp = trace->top;
|
BranchPoint *parentbp = trace->top;
|
||||||
|
@ -1194,11 +1199,21 @@ bool CollapseStructure::updateLoopBody(void)
|
||||||
FlowBlock *loopbottom = (FlowBlock *)0;
|
FlowBlock *loopbottom = (FlowBlock *)0;
|
||||||
FlowBlock *looptop = (FlowBlock *)0;
|
FlowBlock *looptop = (FlowBlock *)0;
|
||||||
while (loopbodyiter != loopbody.end()) { // Last innermost loop
|
while (loopbodyiter != loopbody.end()) { // Last innermost loop
|
||||||
loopbottom = (*loopbodyiter).getCurrentBounds(&looptop,&graph);
|
LoopBody &curBody( *loopbodyiter );
|
||||||
|
loopbottom = curBody.update(&graph);
|
||||||
if (loopbottom != (FlowBlock *)0) {
|
if (loopbottom != (FlowBlock *)0) {
|
||||||
if ((!likelylistfull) ||
|
looptop = curBody.getHead();
|
||||||
(likelyiter != likelygoto.end())) // Reaching here means, we removed edges but loop still didn't collapse
|
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
|
break; // Loop still exists
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++loopbodyiter;
|
++loopbodyiter;
|
||||||
likelylistfull = false; // Need to generate likely list for new loopbody (or no loopbody)
|
likelylistfull = false; // Need to generate likely list for new loopbody (or no loopbody)
|
||||||
|
|
|
@ -55,7 +55,7 @@ class LoopBody {
|
||||||
public:
|
public:
|
||||||
LoopBody(FlowBlock *h) { head=h; immed_container = (LoopBody *)0; depth=0; } ///< Construct with a loop head
|
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 *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
|
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
|
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
|
void findBase(vector<FlowBlock *> &body); ///< Mark the body FlowBlocks of \b this loop
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue