Exemple #1
0
        public void CreateBlocks(BlockContainer mainContainer, List <ILInstruction> instructions, BitArray incomingBranches, CancellationToken cancellationToken)
        {
            CreateContainerStructure();
            mainContainer.ILRange = new Interval(0, body.CodeSize);
            currentContainer      = mainContainer;

            foreach (var inst in instructions)
            {
                cancellationToken.ThrowIfCancellationRequested();
                int start = inst.ILRange.Start;
                if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst)))
                {
                    // Finish up the previous block
                    FinalizeCurrentBlock(start, fallthrough: true);
                    // Leave nested containers if necessary
                    while (start >= currentContainer.ILRange.End)
                    {
                        currentContainer = containerStack.Pop();
                    }
                    // Enter a handler if necessary
                    BlockContainer handlerContainer;
                    if (handlerContainers.TryGetValue(start, out handlerContainer))
                    {
                        containerStack.Push(currentContainer);
                        currentContainer = handlerContainer;
                        currentBlock     = handlerContainer.EntryPoint;
                    }
                    else
                    {
                        // Create the new block
                        currentBlock = new Block();
                        currentContainer.Blocks.Add(currentBlock);
                    }
                    currentBlock.ILRange = new Interval(start, start);
                }
                while (nextTry != null && start == nextTry.TryBlock.ILRange.Start)
                {
                    currentBlock.Instructions.Add(nextTry);
                    containerStack.Push(currentContainer);
                    currentContainer = (BlockContainer)nextTry.TryBlock;
                    currentBlock     = new Block();
                    currentContainer.Blocks.Add(currentBlock);
                    currentBlock.ILRange = new Interval(start, start);

                    nextTry = tryInstructionList.ElementAtOrDefault(++currentTryIndex);
                }
                currentBlock.Instructions.Add(inst);
                if (inst.HasFlag(InstructionFlags.EndPointUnreachable))
                {
                    FinalizeCurrentBlock(inst.ILRange.End, fallthrough: false);
                }
                else if (!CreateExtendedBlocks && inst.HasFlag(InstructionFlags.MayBranch))
                {
                    FinalizeCurrentBlock(inst.ILRange.End, fallthrough: true);
                }
            }
            FinalizeCurrentBlock(body.CodeSize, fallthrough: false);
            containerStack.Clear();
            ConnectBranches(mainContainer, cancellationToken);
        }
Exemple #2
0
        public void CreateBlocks(BlockContainer mainContainer, List <ILInstruction> instructions, BitArray incomingBranches, CancellationToken cancellationToken)
        {
            CreateContainerStructure();
            mainContainer.ILRange = new Interval(0, body.GetCodeSize());
            currentContainer      = mainContainer;
            if (instructions.Count == 0)
            {
                currentContainer.Blocks.Add(new Block {
                    Instructions =
                    {
                        new InvalidBranch("Empty body found. Decompiled assembly might be a reference assembly.")
                    }
                });
                return;
            }

            foreach (var inst in instructions)
            {
                cancellationToken.ThrowIfCancellationRequested();
                int start = inst.ILRange.Start;
                if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst)))
                {
                    // Finish up the previous block
                    FinalizeCurrentBlock(start, fallthrough: true);
                    // Leave nested containers if necessary
                    while (start >= currentContainer.ILRange.End)
                    {
                        currentContainer = containerStack.Pop();
                        currentBlock     = currentContainer.Blocks.Last();
                        // this container is skipped (i.e. the loop will execute again)
                        // set ILRange to the last instruction offset inside the block.
                        if (start >= currentContainer.ILRange.End)
                        {
                            Debug.Assert(currentBlock.ILRange.IsEmpty);
                            currentBlock.ILRange = new Interval(currentBlock.ILRange.Start, start);
                        }
                    }
                    // Enter a handler if necessary
                    BlockContainer handlerContainer;
                    if (handlerContainers.TryGetValue(start, out handlerContainer))
                    {
                        containerStack.Push(currentContainer);
                        currentContainer = handlerContainer;
                        currentBlock     = handlerContainer.EntryPoint;
                    }
                    else
                    {
                        FinalizeCurrentBlock(start, fallthrough: false);
                        // Create the new block
                        currentBlock = new Block();
                        currentContainer.Blocks.Add(currentBlock);
                    }
                    currentBlock.ILRange = new Interval(start, start);
                }
                while (nextTry != null && start == nextTry.TryBlock.ILRange.Start)
                {
                    currentBlock.Instructions.Add(nextTry);
                    containerStack.Push(currentContainer);
                    currentContainer = (BlockContainer)nextTry.TryBlock;
                    currentBlock     = new Block();
                    currentContainer.Blocks.Add(currentBlock);
                    currentBlock.ILRange = new Interval(start, start);

                    nextTry = tryInstructionList.ElementAtOrDefault(++currentTryIndex);
                }
                currentBlock.Instructions.Add(inst);
                if (inst.HasFlag(InstructionFlags.EndPointUnreachable))
                {
                    FinalizeCurrentBlock(inst.ILRange.End, fallthrough: false);
                }
                else if (!CreateExtendedBlocks && inst.HasFlag(InstructionFlags.MayBranch))
                {
                    FinalizeCurrentBlock(inst.ILRange.End, fallthrough: true);
                }
            }
            FinalizeCurrentBlock(mainContainer.ILRange.End, fallthrough: false);
            // Finish up all containers
            while (containerStack.Count > 0)
            {
                currentContainer = containerStack.Pop();
                currentBlock     = currentContainer.Blocks.Last();
                FinalizeCurrentBlock(mainContainer.ILRange.End, fallthrough: false);
            }
            ConnectBranches(mainContainer, cancellationToken);
        }