Ejemplo n.º 1
0
    public static void UpdateDebugInfo(this MethodDefinition method)
    {
        if (!method.HasBody || !method.DebugInformation.HasSequencePoints)
        {
            return;
        }

        var debugInfo    = method.DebugInformation;
        var instructions = method.Body.Instructions;
        var scope        = debugInfo.Scope;

        if (scope == null || instructions.Count == 0)
        {
            return;
        }

        // Step 1: check if all variables are present
        foreach (var variable in method.Body.Variables)
        {
            var hasVariable = scope.Variables.Any(x => x.Index == variable.Index);
            if (!hasVariable)
            {
                var variableDebugInfo = new VariableDebugInformation(variable, $"__var_{variable.Index}");
                scope.Variables.Add(variableDebugInfo);
            }
        }

        // Step 2: update the scopes by setting the indices
        scope.Start = new InstructionOffset(instructions.First());
        scope.End   = new InstructionOffset(instructions.Last());
    }
    public static VariableDefinition DeclareVariable(this MethodBody body, string name, TypeReference type)
    {
        var variable = new VariableDefinition(type);

        body.Variables.Add(variable);
        var variableDebug = new VariableDebugInformation(variable, name);

        body.Method?.DebugInformation?.Scope?.Variables?.Add(variableDebug);
        return(variable);
    }
Ejemplo n.º 3
0
 void DefineLocalVariable(VariableDebugInformation variable, int local_var_token, int start_offset, int end_offset)
 {
     writer.DefineLocalVariable2(
         variable.Name,
         variable.Attributes,
         local_var_token,
         variable.Index,
         0,
         0,
         start_offset,
         end_offset);
 }
Ejemplo n.º 4
0
 void CreateLocalVariable(VariableDebugInformation variable, SymbolToken local_var_token, int start_offset, int end_offset)
 {
     writer.DefineLocalVariable2(
         variable.Name,
         variable.Attributes,
         local_var_token,
         SymAddressKind.ILOffset,
         variable.Index,
         0,
         0,
         start_offset,
         end_offset);
 }
Ejemplo n.º 5
0
    public static void UpdateDebugInfo(this MethodDefinition method)
    {
        var debugInfo = method?.DebugInformation;

        if (debugInfo == null || !method.HasBody || !debugInfo.HasSequencePoints)
        {
            return;
        }

        var methodBody   = method.Body;
        var instructions = methodBody.Instructions;
        var scope        = debugInfo.Scope;

        if (scope == null || instructions.Count == 0)
        {
            return;
        }

        // Step 1: check if all variables are present
        foreach (var variable in methodBody.Variables)
        {
            var hasVariable = scope.Variables.Any(x => x.Index == variable.Index);
            if (!hasVariable)
            {
                var variableDebugInfo = new VariableDebugInformation(variable, $"__var_{variable.Index}");
                scope.Variables.Add(variableDebugInfo);
            }
        }

        // Step 2: point the first sequence point to the first instruction; this will include null guard added IL in the first instruction.
        if (debugInfo.HasSequencePoints)
        {
            var sequencePoints = debugInfo.SequencePoints;

            var s = sequencePoints?.FirstOrDefault();

            if (s?.Offset == 0)
            {
                var entry = instructions[0];
                sequencePoints[0] = new SequencePoint(entry, s.Document)
                {
                    StartColumn = s.StartColumn, StartLine = s.StartLine, EndColumn = s.EndColumn, EndLine = s.EndLine
                };
                scope.Start = new InstructionOffset(entry);
            }
        }
    }
Ejemplo n.º 6
0
        static ScopeDebugInformation ReadScopeAndLocals(PdbScope scope, MethodDebugInformation info)
        {
            var parent = new ScopeDebugInformation();

            parent.Start = new InstructionOffset((int)scope.offset);
            parent.End   = new InstructionOffset((int)(scope.offset + scope.length));

            if (!scope.slots.IsNullOrEmpty())
            {
                parent.variables = new Collection <VariableDebugInformation> (scope.slots.Length);

                foreach (PdbSlot slot in scope.slots)
                {
                    if (slot.flags == 1)                     // parameter names
                    {
                        continue;
                    }

                    var index    = (int)slot.slot;
                    var variable = new VariableDebugInformation(index, slot.name);
                    if (slot.flags == 4)
                    {
                        variable.IsDebuggerHidden = true;
                    }
                    parent.variables.Add(variable);
                }
            }

            if (!scope.constants.IsNullOrEmpty())
            {
                parent.constants = new Collection <ConstantDebugInformation> (scope.constants.Length);

                foreach (var constant in scope.constants)
                {
                    parent.constants.Add(new ConstantDebugInformation(
                                             constant.name,
                                             (TypeReference)info.method.Module.LookupToken((int)constant.token),
                                             constant.value));
                }
            }

            parent.scopes = ReadScopeAndLocals(scope.scopes, info);

            return(parent);
        }
Ejemplo n.º 7
0
        static void ReadLocalVariables(MethodEntry entry, ScopeDebugInformation [] scopes)
        {
            var locals = entry.GetLocals();

            foreach (var local in locals)
            {
                var variable = new VariableDebugInformation(local.Index, local.Name);

                var index = local.BlockIndex;
                if (index < 0 || index >= scopes.Length)
                {
                    continue;
                }

                var scope = scopes [index];
                if (scope == null)
                {
                    continue;
                }

                scope.Variables.Add(variable);
            }
        }
Ejemplo n.º 8
0
 public VarInfo(VariableDebugInformation v)
 {
     this.Name  = v.Name;
     this.Index = v.Index;
 }
Ejemplo n.º 9
0
    public static void UpdateDebugInfo(this MethodDefinition method)
    {
        if (!method.HasBody || !method.DebugInformation.HasSequencePoints)
        {
            return;
        }

        var debugInfo    = method.DebugInformation;
        var instructions = method.Body.Instructions;
        var scope        = debugInfo.Scope;

        if (scope == null || instructions.Count == 0)
        {
            return;
        }

        var oldSequencePoints = debugInfo.SequencePoints;
        var newSequencePoints = new Collection <SequencePoint>();

        // Step 1: check if all variables are present
        foreach (var variable in method.Body.Variables)
        {
            var hasVariable = scope.Variables.Any(x => x.Index == variable.Index);
            if (!hasVariable)
            {
                var variableDebugInfo = new VariableDebugInformation(variable, $"__var_{variable.Index}");
                scope.Variables.Add(variableDebugInfo);
            }
        }

        // Step 2: Make sure the instructions point to the correct items
        foreach (var oldSequencePoint in oldSequencePoints)
        {
            var instructionOffset = (InstructionOffset)SequencePointOffsetFieldInfo.GetValue(oldSequencePoint);
            var offsetInstruction = (Instruction)InstructionOffsetInstructionFieldInfo.GetValue(instructionOffset);

            // Fix offset
            for (var i = 0; i < instructions.Count; i++)
            {
                var instruction = instructions[i];
                if (instruction == offsetInstruction)
                {
                    var newSequencePoint = new SequencePoint(instruction, oldSequencePoint.Document)
                    {
                        StartLine   = oldSequencePoint.StartLine,
                        StartColumn = oldSequencePoint.StartColumn,
                        EndLine     = oldSequencePoint.EndLine,
                        EndColumn   = oldSequencePoint.EndColumn
                    };

                    newSequencePoints.Add(newSequencePoint);
                    break;
                }
            }
        }

        debugInfo.SequencePoints.Clear();

        foreach (var newSequencePoint in newSequencePoints)
        {
            debugInfo.SequencePoints.Add(newSequencePoint);
        }

        // Step 3: update the scopes by setting the indices
        scope.Start = new InstructionOffset(instructions.First());
        scope.End   = new InstructionOffset(instructions.Last());
    }
Ejemplo n.º 10
0
        ScopeDebugInformation ReadScopeAndLocals(PdbScope scope, MethodDebugInformation info)
        {
            var parent = new ScopeDebugInformation();

            parent.Start = new InstructionOffset((int)scope.offset);
            parent.End   = new InstructionOffset((int)(scope.offset + scope.length));

            if (!scope.slots.IsNullOrEmpty())
            {
                parent.variables = new Collection <VariableDebugInformation> (scope.slots.Length);

                foreach (PdbSlot slot in scope.slots)
                {
                    if ((slot.flags & 1) != 0)                     // parameter names
                    {
                        continue;
                    }

                    var index    = (int)slot.slot;
                    var variable = new VariableDebugInformation(index, slot.name);
                    if ((slot.flags & 4) != 0)
                    {
                        variable.IsDebuggerHidden = true;
                    }
                    parent.variables.Add(variable);
                }
            }

            if (!scope.constants.IsNullOrEmpty())
            {
                parent.constants = new Collection <ConstantDebugInformation> (scope.constants.Length);

                foreach (var constant in scope.constants)
                {
                    var type  = info.Method.Module.Read(constant, (c, r) => r.ReadConstantSignature(new MetadataToken(c.token)));
                    var value = constant.value;

                    // Object "null" is encoded as integer
                    if (type != null && !type.IsValueType && value is int && (int)value == 0)
                    {
                        value = null;
                    }

                    parent.constants.Add(new ConstantDebugInformation(constant.name, type, value));
                }
            }

            if (!scope.usedNamespaces.IsNullOrEmpty())
            {
                ImportDebugInformation import;
                if (imports.TryGetValue(scope, out import))
                {
                    parent.import = import;
                }
                else
                {
                    import = GetImport(scope, info.Method.Module);
                    imports.Add(scope, import);
                    parent.import = import;
                }
            }

            parent.scopes = ReadScopeAndLocals(scope.scopes, info);

            return(parent);
        }
Ejemplo n.º 11
0
        public static void UpdateDebugInfo(this MethodDefinition method)
        {
            var debugInfo    = method.DebugInformation;
            var instructions = method.Body.Instructions;
            var scope        = debugInfo.Scope;

            if (scope == null || instructions.Count == 0)
            {
                return;
            }

            var oldSequencePoints = debugInfo.SequencePoints;
            var newSequencePoints = new Collection <SequencePoint>();

            // Step 1: check if all variables are present
            foreach (var variable in method.Body.Variables)
            {
                if (method.IsAsyncMethod())
                {
                    // Skip some special items of an async method:
                    // 1) int (state?)
                    // 2) exception
                    if (variable.Index == 0 && variable.VariableType.Name.Contains("Int") ||
                        variable.VariableType.Name.Contains("Exception"))
                    {
                        continue;
                    }
                }

                if (!ContainsVariable(scope, variable))
                {
                    var variableDebugInfo = new VariableDebugInformation(variable, $"__var_{variable.Index}");
                    scope.Variables.Add(variableDebugInfo);
                }
            }

            // Step 2: Make sure the instructions point to the correct items
            foreach (var oldSequencePoint in oldSequencePoints)
            {
                //var isValid = false;

                //// Special cases we need to ignore
                //if (oldSequencePoint.StartLine == AddressToIgnore ||
                //    oldSequencePoint.EndLine == AddressToIgnore)
                //{
                //    continue;
                //}

                var instructionOffset = (InstructionOffset)SequencePointOffsetFieldInfo.GetValue(oldSequencePoint);
                var offsetInstruction = (Instruction)InstructionOffsetInstructionFieldInfo.GetValue(instructionOffset);

                // Fix offset
                for (var i = 0; i < instructions.Count; i++)
                {
                    var instruction = instructions[i];
                    if (instruction == offsetInstruction)
                    {
                        var newSequencePoint = new SequencePoint(instruction, oldSequencePoint.Document)
                        {
                            StartLine   = oldSequencePoint.StartLine,
                            StartColumn = oldSequencePoint.StartColumn,
                            EndLine     = oldSequencePoint.EndLine,
                            EndColumn   = oldSequencePoint.EndColumn
                        };

                        newSequencePoints.Add(newSequencePoint);

                        //isValid = true;

                        break;
                    }
                }
            }

            debugInfo.SequencePoints.Clear();

            foreach (var newSequencePoint in newSequencePoints)
            {
                debugInfo.SequencePoints.Add(newSequencePoint);
            }

            // Step 3: Remove any unused variables
            RemoveUnusedVariablesFromDebugInfo(scope);

            // Final step: update the scopes by setting the indices
            scope.Start = new InstructionOffset(instructions.First());
            scope.End   = new InstructionOffset(instructions.Last());
        }