/* Copyright (C) 2011 de4dot@gmail.com This file is part of de4dot. de4dot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. de4dot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with de4dot. If not, see . */ using System.Collections.Generic; namespace de4dot.blocks { class BlocksSorter { ScopeBlock scopeBlock; Dictionary visited; List sorted; public BlocksSorter(ScopeBlock scopeBlock) { this.scopeBlock = scopeBlock; } bool hasVisited(BaseBlock bb) { bool hasVisited; if (visited.TryGetValue(bb, out hasVisited)) return hasVisited; visited[bb] = false; return false; } public List sort() { visited = new Dictionary(); sorted = new List(scopeBlock.BaseBlocks.Count); search(scopeBlock.BaseBlocks[0]); sorted.Reverse(); // It's in reverse order // Just in case there's dead code or unreferenced exception blocks foreach (var bb in scopeBlock.BaseBlocks) { if (hasVisited(bb)) continue; sorted.Add(bb); } sorted = new ForwardScanOrder(scopeBlock, sorted).fix(); return sorted; } // Depth-first order void search(BaseBlock bb) { if (hasVisited(bb)) return; visited[bb] = true; var block = bb as Block; // Block or ScopeBlock if (block != null) { // Since the sorted array will be in reverse order, and we want the // conditional branches to fall through to their fall-through target, make // sure the FallThrough target is added last! Some conditional instructions // aren't reversible (eg. beq and bne.un) since they don't take the same // types of arguments. This will also make sure .NET Reflector doesn't // crash (sometimes). var targets = new List(block.getTargets()); targets.Reverse(); foreach (var target in targets) { var child = scopeBlock.toChild(target); if (child != null) search(child); } } sorted.Add(bb); } } }