// Removes the TryBlock and all its TryHandlerBlocks. The code inside the try block // is not removed. public void removeTryBlock(TryBlock tryBlock) { int tryBlockIndex = baseBlocks.IndexOf(tryBlock); if (tryBlockIndex < 0) { throw new ApplicationException("Can't remove the TryBlock since it's not this ScopeBlock's TryBlock"); } foreach (var bb in tryBlock.BaseBlocks) { bb.Parent = this; } baseBlocks.RemoveAt(tryBlockIndex); baseBlocks.InsertRange(tryBlockIndex, tryBlock.BaseBlocks); tryBlock.BaseBlocks.Clear(); // Get removed blocks and make sure they're not referenced by remaining code var removedBlocks = new List <Block>(); foreach (var handler in tryBlock.TryHandlerBlocks) { handler.getTheBlocks(removedBlocks); } if (!verifyNoExternalRefs(removedBlocks)) { throw new ApplicationException("Removed blocks are referenced by remaining code"); } removeAllDeadBlocks(Utils.convert <TryHandlerBlock, BaseBlock>(tryBlock.TryHandlerBlocks)); }
void AddTargets(List <BaseBlock> dest, TryBlock tryBlock) { AddTargets(dest, (ScopeBlock)tryBlock); foreach (var tryHandlerBlock in tryBlock.TryHandlerBlocks) { dest.Add(tryHandlerBlock); AddTargets(dest, tryHandlerBlock); } }
bool find(Blocks blocks, out TryBlock tryBlock) { tryBlock = null; foreach (var bb in blocks.MethodBlocks.BaseBlocks) { tryBlock = bb as TryBlock; if (tryBlock == null) continue; if (tryBlock.TryHandlerBlocks.Count != 1) continue; var catchBlock = tryBlock.TryHandlerBlocks[0]; if (catchBlock.HandlerType != ExceptionHandlerType.Catch || catchBlock.CatchType.FullName != "System.Exception") { continue; } if (catchBlock.BaseBlocks.Count != 1) continue; var handlerBlock = catchBlock.BaseBlocks[0] as HandlerBlock; if (handlerBlock == null) continue; int calls = 0; Instr callInstr = null; bool failed = false; foreach (var bb2 in handlerBlock.BaseBlocks) { var block = bb2 as Block; if (block == null) { failed = true; break; } foreach (var instr in block.Instructions) { switch (instr.OpCode.Code) { case Code.Call: case Code.Calli: case Code.Callvirt: calls++; callInstr = instr; break; } } } if (failed || calls != 1 || callInstr.OpCode.Code != Code.Call) continue; var calledMethod = callInstr.Operand as MethodReference; if (calledMethod == null) continue; if (!isExceptionLogger(calledMethod)) continue; return true; } return false; }
BaseBlocksList createBaseBlockList(List <Block> allBlocks, List <List <ExceptionHandler> > exSorted) { var bbl = new BaseBlocksList(); foreach (var block in allBlocks) { int start = instrToIndex[block.FirstInstr.Instruction]; int end = instrToIndex[block.LastInstr.Instruction]; bbl.add(block, start, end); } foreach (var exHandlers in exSorted) { var tryBlock = new TryBlock(); var tryStart = instrToIndex[exHandlers[0].TryStart]; var tryEnd = getInstrIndex(exHandlers[0].TryEnd) - 1; tryBlock.BaseBlocks = bbl.replace(tryStart, tryEnd, tryBlock); foreach (var exHandler in exHandlers) { var tryHandlerBlock = new TryHandlerBlock(exHandler); tryBlock.addTryHandler(tryHandlerBlock); int filterStart = -1, handlerStart = -1, handlerEnd = -1; if (exHandler.FilterStart != null) { filterStart = instrToIndex[exHandler.FilterStart]; var end = instrToIndex[exHandler.HandlerStart] - 1; tryHandlerBlock.FilterHandlerBlock.BaseBlocks = bbl.replace(filterStart, end, tryHandlerBlock.FilterHandlerBlock); } handlerStart = instrToIndex[exHandler.HandlerStart]; handlerEnd = getInstrIndex(exHandler.HandlerEnd) - 1; tryHandlerBlock.HandlerBlock.BaseBlocks = bbl.replace(handlerStart, handlerEnd, tryHandlerBlock.HandlerBlock); tryHandlerBlock.BaseBlocks = bbl.replace(filterStart == -1 ? handlerStart : filterStart, handlerEnd, tryHandlerBlock); } } return(bbl); }
void doTryBlock(TryBlock tryBlock) { var tryStart = blocks.Count; stateStack.Push(new BlockState(tryBlock)); processBaseBlocks(tryBlock.BaseBlocks, (block) => { return(block.LastInstr.OpCode == OpCodes.Leave || block.LastInstr.OpCode == OpCodes.Leave_S); }); stateStack.Pop(); var tryEnd = blocks.Count - 1; if (tryBlock.TryHandlerBlocks.Count == 0) { throw new ApplicationException("No handler blocks"); } foreach (var handlerBlock in tryBlock.TryHandlerBlocks) { visited[handlerBlock] = true; stateStack.Push(new BlockState(handlerBlock)); var filterStart = blocks.Count; if (handlerBlock.FilterHandlerBlock.BaseBlocks != null) { doBaseBlock(handlerBlock.FilterHandlerBlock); } var handlerStart = blocks.Count; doBaseBlock(handlerBlock.HandlerBlock); var handlerEnd = blocks.Count - 1; exceptions.Add(new ExceptionInfo(tryStart, tryEnd, filterStart, handlerStart, handlerEnd, handlerBlock.CatchType, handlerBlock.HandlerType)); stateStack.Pop(); } }
BaseBlocksList CreateBaseBlockList(List<Block> allBlocks, List<List<ExceptionHandler>> exSorted) { var bbl = new BaseBlocksList(); foreach (var block in allBlocks) { int start = instrToIndex[block.FirstInstr.Instruction]; int end = instrToIndex[block.LastInstr.Instruction]; bbl.Add(block, start, end); } foreach (var exHandlers in exSorted) { var tryBlock = new TryBlock(); var tryStart = instrToIndex[exHandlers[0].TryStart]; var tryEnd = GetInstrIndex(exHandlers[0].TryEnd) - 1; tryBlock.BaseBlocks = bbl.Replace(tryStart, tryEnd, tryBlock); foreach (var exHandler in exHandlers) { var tryHandlerBlock = new TryHandlerBlock(exHandler); tryBlock.AddTryHandler(tryHandlerBlock); int filterStart = -1, handlerStart = -1, handlerEnd = -1; if (exHandler.FilterStart != null) { filterStart = instrToIndex[exHandler.FilterStart]; var end = instrToIndex[exHandler.HandlerStart] - 1; tryHandlerBlock.FilterHandlerBlock.BaseBlocks = bbl.Replace(filterStart, end, tryHandlerBlock.FilterHandlerBlock); } handlerStart = instrToIndex[exHandler.HandlerStart]; handlerEnd = GetInstrIndex(exHandler.HandlerEnd) - 1; tryHandlerBlock.HandlerBlock.BaseBlocks = bbl.Replace(handlerStart, handlerEnd, tryHandlerBlock.HandlerBlock); tryHandlerBlock.BaseBlocks = bbl.Replace(filterStart == -1 ? handlerStart : filterStart, handlerEnd, tryHandlerBlock); } } return bbl; }
void doTryBlock(TryBlock tryBlock) { var tryStart = blocks.Count; stateStack.Push(new BlockState(tryBlock)); processBaseBlocks(tryBlock.BaseBlocks, (block) => { return block.LastInstr.OpCode == OpCodes.Leave || block.LastInstr.OpCode == OpCodes.Leave_S; }); stateStack.Pop(); var tryEnd = blocks.Count - 1; if (tryBlock.TryHandlerBlocks.Count == 0) throw new ApplicationException("No handler blocks"); foreach (var handlerBlock in tryBlock.TryHandlerBlocks) { visited[handlerBlock] = true; stateStack.Push(new BlockState(handlerBlock)); var filterStart = blocks.Count; if (handlerBlock.FilterHandlerBlock.BaseBlocks != null) doBaseBlock(handlerBlock.FilterHandlerBlock); var handlerStart = blocks.Count; doBaseBlock(handlerBlock.HandlerBlock); var handlerEnd = blocks.Count - 1; exceptions.Add(new ExceptionInfo(tryStart, tryEnd, filterStart, handlerStart, handlerEnd, handlerBlock.CatchType, handlerBlock.HandlerType)); stateStack.Pop(); } }
void AddTargets(List<BaseBlock> dest, TryBlock tryBlock) { AddTargets(dest, (ScopeBlock)tryBlock); foreach (var tryHandlerBlock in tryBlock.TryHandlerBlocks) { dest.Add(tryHandlerBlock); AddTargets(dest, tryHandlerBlock); } }