Beispiel #1
0
        private List <DebugLocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope)
        {
            List <DebugLocalVariableInfo> vars = new List <DebugLocalVariableInfo>();

            foreach (ISymUnmanagedVariable symVar in symScope.GetLocals())
            {
                ISymUnmanagedVariable symVarCopy = symVar;
                int                       start;
                SignatureReader           sigReader  = new SignatureReader(symVar.GetSignature());
                LocalVarSig.LocalVariable locVarSig  = sigReader.ReadLocalVariable(sigReader.Blob, 0, out start);
                DebugType                 locVarType = DebugType.CreateFromSignature(this.DebugModule, locVarSig.Type, declaringType);
                // Compiler generated?
                // NB: Display class does not have the compiler-generated flag
                if ((symVar.GetAttributes() & 1) == 1 || symVar.GetName().StartsWith("CS$"))
                {
                    // Get display class from local variable
                    if (locVarType.IsDisplayClass)
                    {
                        AddCapturedLocalVariables(
                            vars,
                            (int)symScope.GetStartOffset(),
                            (int)symScope.GetEndOffset(),
                            delegate(StackFrame context)
                        {
                            return(GetLocalVariableValue(context, symVarCopy));
                        },
                            locVarType
                            );
                    }
                }
                else
                {
                    DebugLocalVariableInfo locVar = new DebugLocalVariableInfo(
                        symVar.GetName(),
                        (int)symVar.GetAddressField1(),
                        // symVar also has Get*Offset methods, but the are not implemented
                        (int)symScope.GetStartOffset(),
                        (int)symScope.GetEndOffset(),
                        locVarType,
                        delegate(StackFrame context)
                    {
                        return(GetLocalVariableValue(context, symVarCopy));
                    }
                        );
                    vars.Add(locVar);
                }
            }
            foreach (ISymUnmanagedScope childScope in symScope.GetChildren())
            {
                vars.AddRange(GetLocalVariablesInScope(childScope));
            }

            return(vars);
        }
Beispiel #2
0
        public static int GetEndOffset(this ISymUnmanagedScope scope)
        {
            int endOffset;

            scope.GetEndOffset(out endOffset);
            return(endOffset);
        }
Beispiel #3
0
        public static int GetEndOffset(this ISymUnmanagedScope scope)
        {
            int endOffset;
            int hr = scope.GetEndOffset(out endOffset);

            ThrowExceptionForHR(hr);
            return(endOffset);
        }
Beispiel #4
0
        public static void ValidateRange(ISymUnmanagedScope scope, int expectedStartOffset, int expectedLength)
        {
            int actualOffset;
            Assert.Equal(HResult.S_OK, scope.GetStartOffset(out actualOffset));
            Assert.Equal(expectedStartOffset, actualOffset);

            Assert.Equal(HResult.S_OK, scope.GetEndOffset(out actualOffset));
            Assert.Equal(expectedStartOffset + expectedLength, 2);
        }
        public static void ValidateRange(ISymUnmanagedScope scope, int expectedStartOffset, int expectedLength)
        {
            int actualOffset;

            Assert.Equal(HResult.S_OK, scope.GetStartOffset(out actualOffset));
            Assert.Equal(expectedStartOffset, actualOffset);

            Assert.Equal(HResult.S_OK, scope.GetEndOffset(out actualOffset));
            Assert.Equal(expectedStartOffset + expectedLength, 2);
        }
        public static int GetEndOffset(this ISymUnmanagedScope scope)
        {
            if (scope == null)
            {
                throw new ArgumentNullException(nameof(scope));
            }

            int endOffset;

            ThrowExceptionForHR(scope.GetEndOffset(out endOffset));
            return(endOffset);
        }
Beispiel #7
0
        private static bool IsInScope(ISymUnmanagedScope scope, int offset, bool isEndInclusive)
        {
            int startOffset = scope.GetStartOffset();
            if (offset < startOffset)
            {
                return false;
            }

            int endOffset = scope.GetEndOffset();

            // In PDBs emitted by VB the end offset is inclusive, 
            // in PDBs emitted by C# the end offset is exclusive.
            return isEndInclusive ? offset <= endOffset : offset < endOffset;
        }
Beispiel #8
0
        private static bool IsInScope(this ISymUnmanagedScope scope, int offset)
        {
            int startOffset;

            scope.GetStartOffset(out startOffset);
            if (offset < startOffset)
            {
                return(false);
            }

            int endOffset;

            scope.GetEndOffset(out endOffset);
            return(offset <= endOffset);
        }
Beispiel #9
0
 /// <summary>
 /// Get definitions of local variables in scope.
 /// </summary>
 /// <param name="scope">Interface refering to desired scope.</param>
 /// <param name="index">Index pointing to the last read variable.</param>
 /// <param name="definitions">List of definitions, where found variable definition are placed.</param>
 private void getDefinitionsForScope(ISymUnmanagedScope scope, ref int index, List <LocalVarDefinition> definitions)
 {
     ISymUnmanagedVariable[] variables = scope.GetLocals();
     foreach (ISymUnmanagedVariable var in variables)
     {
         LocalVarDefinition def = new LocalVarDefinition();
         def.ilStart   = scope.GetStartOffset();
         def.ilEnd     = scope.GetEndOffset();
         def.name      = var.GetName();
         def.signature = var.GetSignature();
         definitions.Add(def);
         ++index;
     }
     foreach (ISymUnmanagedScope cScope in scope.GetChildren())
     {
         getDefinitionsForScope(cScope, ref index, definitions);
     }
 }
Beispiel #10
0
        internal static bool IsInScope(this ISymUnmanagedScope scope, int offset, bool isEndInclusive)
        {
            int startOffset;

            scope.GetStartOffset(out startOffset);
            if (offset < startOffset)
            {
                return(false);
            }

            int endOffset;

            scope.GetEndOffset(out endOffset);

            // In PDBs emitted by VB the end offset is inclusive,
            // in PDBs emitted by C# the end offset is exclusive.
            return(isEndInclusive ? offset <= endOffset : offset < endOffset);
        }
Beispiel #11
0
        private void WriteScopes(ISymUnmanagedScope scope)
        {
            writer.WriteStartElement("scope");
            {
                writer.WriteAttributeString("startOffset", AsILOffset(scope.GetStartOffset()));
                writer.WriteAttributeString("endOffset", AsILOffset(scope.GetEndOffset()));
                {
                    foreach (ISymUnmanagedNamespace @namespace in scope.GetNamespaces())
                    {
                        WriteNamespace(@namespace);
                    }

                    WriteLocalsHelper(scope, slotNames: null, includeChildScopes: false);
                }
                foreach (ISymUnmanagedScope child in scope.GetScopes())
                {
                    WriteScopes(child);
                }
            }
            writer.WriteEndElement(); // </scope>
        }
Beispiel #12
0
        private void WriteScopes(ISymUnmanagedScope scope)
        {
            writer.WriteStartElement("scope");
            {
                writer.WriteAttributeString("startOffset", AsILOffset(scope.GetStartOffset()));
                writer.WriteAttributeString("endOffset", AsILOffset(scope.GetEndOffset()));
                {
                    foreach (ISymUnmanagedNamespace @namespace in scope.GetNamespaces())
                    {
                        WriteNamespace(@namespace);
                    }

                    WriteLocalsHelper(scope, slotNames: null, includeChildScopes: false);
                }
                foreach (ISymUnmanagedScope child in scope.GetScopes())
                {
                    WriteScopes(child);
                }
            }
            writer.WriteEndElement(); // </scope>
        }
Beispiel #13
0
        public IEnumerable <ILLocalVariable> GetLocalVariables(IMethod method)
        {
            List <ILLocalVariable> vars = new List <ILLocalVariable>();
            var symMethod = method.GetSymMethod();

            if (symMethod == null)
            {
                return(vars);
            }

            Stack <ISymUnmanagedScope> scopes = new Stack <ISymUnmanagedScope>();

            scopes.Push(symMethod.GetRootScope());
            while (scopes.Count > 0)
            {
                ISymUnmanagedScope scope = scopes.Pop();
                foreach (ISymUnmanagedVariable symVar in scope.GetLocals())
                {
                    int index = (int)symVar.GetAddressField1();
                    vars.Add(new ILLocalVariable()
                    {
                        Index = index,
                        Type  = method.GetLocalVariableType(index),
                        Name  = symVar.GetName(),
                        IsCompilerGenerated = (symVar.GetAttributes() & 1) == 1,
                        // symVar also has Get*Offset methods, but the are not implemented
                        ILRanges = new [] { new ILRange()
                                            {
                                                From = (int)scope.GetStartOffset(), To = (int)scope.GetEndOffset()
                                            } }
                    });
                }
                foreach (ISymUnmanagedScope childScope in scope.GetChildren())
                {
                    scopes.Push(childScope);
                }
            }
            return(vars);
        }
Beispiel #14
0
 List<DebugLocalVariableInfo> GetLocalVariablesInScope(ISymUnmanagedScope symScope)
 {
     List<DebugLocalVariableInfo> vars = new List<DebugLocalVariableInfo>();
     foreach (ISymUnmanagedVariable symVar in symScope.GetLocals()) {
         ISymUnmanagedVariable symVarCopy = symVar;
         var locVarSig = new DebugSignatureReader().ReadTypeSignature(symVar.GetSignature());
         DebugType locVarType = DebugType.CreateFromSignature(this.DebugModule, locVarSig, declaringType);
         // Compiler generated?
         // NB: Display class does not have the compiler-generated flag
         if ((symVar.GetAttributes() & 1) == 1 || symVar.GetName().StartsWith("CS$")) {
             // Get display class from local variable
             if (locVarType.IsDisplayClass) {
                 AddCapturedLocalVariables(
                     vars,
                     (int)symScope.GetStartOffset(),
                     (int)symScope.GetEndOffset(),
                     delegate(StackFrame context) {
                         return GetLocalVariableValue(context, symVarCopy);
                     },
                     locVarType
                 );
             }
         } else {
             DebugLocalVariableInfo locVar = new DebugLocalVariableInfo(
                 symVar.GetName(),
                 (int)symVar.GetAddressField1(),
                 // symVar also has Get*Offset methods, but the are not implemented
                 (int)symScope.GetStartOffset(),
                 (int)symScope.GetEndOffset(),
                 locVarType,
                 delegate(StackFrame context) {
                     return GetLocalVariableValue(context, symVarCopy);
                 }
             );
             vars.Add(locVar);
         }
     }
     foreach(ISymUnmanagedScope childScope in symScope.GetChildren()) {
         vars.AddRange(GetLocalVariablesInScope(childScope));
     }
     return vars;
 }
Beispiel #15
0
        private void WriteLocals(ISymUnmanagedScope scope)
        {
            foreach (ISymUnmanagedVariable l in scope.GetLocals())
            {
                _writer.WriteStartElement("local");
                _writer.WriteAttributeString("name", l.GetName());

                // NOTE: VB emits "fake" locals for resumable locals which are actually backed by fields.
                //       These locals always map to the slot #0 which is just a valid number that is 
                //       not used. Only scoping information is used by EE in this case.
                _writer.WriteAttributeString("il_index", CultureInvariantToString(l.GetSlot()));

                _writer.WriteAttributeString("il_start", AsILOffset(scope.GetStartOffset()));
                _writer.WriteAttributeString("il_end", AsILOffset(scope.GetEndOffset()));
                _writer.WriteAttributeString("attributes", CultureInvariantToString(l.GetAttributes()));
                _writer.WriteEndElement();
            }

            foreach (ISymUnmanagedConstant constant in scope.GetConstants())
            {
                string name = constant.GetName();
                var signature = constant.GetSignature();
                object value = constant.GetValue();

                _writer.WriteStartElement("constant");
                _writer.WriteAttributeString("name", name);

                if (value is int &&
                    (int)value == 0 &&
                    (signature[0] == (byte)ConstantTypeCode.NullReference ||
                     signature[0] == (int)SignatureTypeCode.Object ||
                     signature[0] == (int)SignatureTypeCode.String ||
                     signature[0] == (int)SignatureTypeCode.GenericTypeInstance))
                {
                    // TODO: 0 for enums nested in a generic class, null for reference type
                    // We need to decode the signature and see if the target type is enum.
                    _writer.WriteAttributeString("value", "null");

                    if (signature[0] == (int)SignatureTypeCode.String)
                    {
                        _writer.WriteAttributeString("type", "String");
                    }
                    else if (signature[0] == (int)SignatureTypeCode.Object)
                    {
                        _writer.WriteAttributeString("type", "Object");
                    }
                    else
                    {
                        // TODO:
                        // A null reference, the type is encoded in the signature. 
                        // Ideally we would parse the signature and display the target type name. 
                        // That requires MetadataReader vNext though.
                        _writer.WriteAttributeString("signature", BitConverter.ToString(signature.ToArray()));
                    }
                }
                else if (value == null)
                {
                    // empty string
                    if (signature[0] == (byte)SignatureTypeCode.String)
                    {
                        _writer.WriteAttributeString("value", "");
                        _writer.WriteAttributeString("type", "String");
                    }
                    else
                    {
                        _writer.WriteAttributeString("value", "null");
                        _writer.WriteAttributeString("unknown-signature", BitConverter.ToString(signature.ToArray()));
                    }
                }
                else if (value is decimal)
                {
                    // TODO: check that the signature is a TypeRef
                    _writer.WriteAttributeString("value", ((decimal)value).ToString(CultureInfo.InvariantCulture));
                    _writer.WriteAttributeString("type", value.GetType().Name);
                }
                else if (value is double && signature[0] != (byte)SignatureTypeCode.Double)
                {
                    // TODO: check that the signature is a TypeRef
                    _writer.WriteAttributeString("value", DateTimeUtilities.ToDateTime((double)value).ToString(CultureInfo.InvariantCulture));
                    _writer.WriteAttributeString("type", "DateTime");
                }
                else
                {
                    _writer.WriteAttributeString("value", (value as string)?.Replace("\0", "U+0000") ?? string.Format(CultureInfo.InvariantCulture, "{0}", value));

                    var runtimeType = GetConstantRuntimeType(signature);
                    if (runtimeType == null && 
                        (value is sbyte || value is byte || value is short || value is ushort ||
                         value is int || value is uint || value is long || value is ulong))
                    {
                        // TODO:
                        // Enum.
                        // Ideally we would parse the signature and display the target type name. 
                        // That requires MetadataReader vNext though.
                        _writer.WriteAttributeString("signature", BitConverter.ToString(signature.ToArray()));
                    }
                    else if (runtimeType == value.GetType())
                    {
                        _writer.WriteAttributeString("type", ((SignatureTypeCode)signature[0]).ToString());
                    }
                    else
                    {
                        _writer.WriteAttributeString("runtime-type", value.GetType().Name);
                        _writer.WriteAttributeString("unknown-signature", BitConverter.ToString(signature.ToArray()));
                    }
                }

                _writer.WriteEndElement();
            }
        }
Beispiel #16
0
        private void WriteScope(ISymUnmanagedScope scope, bool isRoot)
        {
            _writer.WriteStartElement(isRoot ? "rootScope" : "scope");
            _writer.WriteAttributeString("startOffset", AsILOffset(scope.GetStartOffset()));
            _writer.WriteAttributeString("endOffset", AsILOffset(scope.GetEndOffset()));

            foreach (ISymUnmanagedNamespace @namespace in scope.GetNamespaces())
            {
                WriteNamespace(@namespace);
            }

            WriteLocals(scope);

            foreach (ISymUnmanagedScope child in scope.GetScopes())
            {
                WriteScope(child, isRoot: false);
            }

            _writer.WriteEndElement(); 
        }
Beispiel #17
0
 /// <summary>
 /// Get definitions of local variables in scope.    
 /// </summary>
 /// <param name="scope">Interface refering to desired scope.</param>
 /// <param name="index">Index pointing to the last read variable.</param>
 /// <param name="definitions">List of definitions, where found variable definition are placed.</param>
 private void getDefinitionsForScope(ISymUnmanagedScope scope, ref int index, List<LocalVarDefinition> definitions)
 {
     ISymUnmanagedVariable[] variables = scope.GetLocals();
     foreach (ISymUnmanagedVariable var in variables) {
         LocalVarDefinition def = new LocalVarDefinition();
         def.ilStart = scope.GetStartOffset();
         def.ilEnd = scope.GetEndOffset();
         def.name = var.GetName();
         def.signature = var.GetSignature();
         definitions.Add(def);
         ++index;
     }
     foreach (ISymUnmanagedScope cScope in scope.GetChildren()) {
         getDefinitionsForScope(cScope, ref index, definitions);
     }
 }
        private void WriteLocals(ISymUnmanagedScope scope)
        {
            foreach (ISymUnmanagedVariable l in scope.GetLocals())
            {
                _writer.WriteStartElement("local");
                _writer.WriteAttributeString("name", l.GetName());

                // NOTE: VB emits "fake" locals for resumable locals which are actually backed by fields.
                //       These locals always map to the slot #0 which is just a valid number that is 
                //       not used. Only scoping information is used by EE in this case.
                _writer.WriteAttributeString("il_index", CultureInvariantToString(l.GetSlot()));

                _writer.WriteAttributeString("il_start", AsILOffset(scope.GetStartOffset()));
                _writer.WriteAttributeString("il_end", AsILOffset(scope.GetEndOffset()));
                _writer.WriteAttributeString("attributes", CultureInvariantToString(l.GetAttributes()));
                _writer.WriteEndElement();
            }

            foreach (ISymUnmanagedConstant constant in scope.GetConstants())
            {
                string name = constant.GetName();
                var signature = constant.GetSignature();
                object value = constant.GetValue();

                _writer.WriteStartElement("constant");
                _writer.WriteAttributeString("name", name);

                if (value is int &&
                    (int)value == 0 &&
                    (signature[0] == (byte)ConstantTypeCode.NullReference ||
                     signature[0] == (int)SignatureTypeCode.Object ||
                     signature[0] == (int)SignatureTypeCode.String ||
                     (signature.Length > 2 && signature[0] == (int)SignatureTypeCode.GenericTypeInstance && signature[1] == (byte)ConstantTypeCode.NullReference)))
                {
                    _writer.WriteAttributeString("value", "null");

                    if (signature[0] == (int)SignatureTypeCode.String)
                    {
                        _writer.WriteAttributeString("type", "String");
                    }
                    else if (signature[0] == (int)SignatureTypeCode.Object)
                    {
                        _writer.WriteAttributeString("type", "Object");
                    }
                    else
                    {
                        _writer.WriteAttributeString("signature", FormatSignature(signature));
                    }
                }
                else if (value == null)
                {
                    // empty string
                    if (signature[0] == (byte)SignatureTypeCode.String)
                    {
                        _writer.WriteAttributeString("value", "");
                        _writer.WriteAttributeString("type", "String");
                    }
                    else
                    {
                        _writer.WriteAttributeString("value", "null");
                        _writer.WriteAttributeString("unknown-signature", BitConverter.ToString(signature.ToArray()));
                    }
                }
                else if (value is decimal)
                {
                    // TODO: check that the signature is a TypeRef
                    _writer.WriteAttributeString("value", ((decimal)value).ToString(CultureInfo.InvariantCulture));
                    _writer.WriteAttributeString("type", value.GetType().Name);
                }
                else if (value is double && signature[0] != (byte)SignatureTypeCode.Double)
                {
                    // TODO: check that the signature is a TypeRef
                    _writer.WriteAttributeString("value", DateTimeUtilities.ToDateTime((double)value).ToString(CultureInfo.InvariantCulture));
                    _writer.WriteAttributeString("type", "DateTime");
                }
                else
                {
                    string str = value as string;
                    if (str != null)
                    {
                        _writer.WriteAttributeString("value", StringUtilities.EscapeNonPrintableCharacters(str));
                    }
                    else
                    {
                        _writer.WriteAttributeString("value", string.Format(CultureInfo.InvariantCulture, "{0}", value));
                    }

                    var runtimeType = GetConstantRuntimeType(signature);
                    if (runtimeType == null &&
                        (value is sbyte || value is byte || value is short || value is ushort ||
                         value is int || value is uint || value is long || value is ulong))
                    {
                        _writer.WriteAttributeString("signature", FormatSignature(signature));
                    }
                    else if (runtimeType == value.GetType())
                    {
                        _writer.WriteAttributeString("type", ((SignatureTypeCode)signature[0]).ToString());
                    }
                    else
                    {
                        _writer.WriteAttributeString("runtime-type", value.GetType().Name);
                        _writer.WriteAttributeString("unknown-signature", BitConverter.ToString(signature.ToArray()));
                    }
                }

                _writer.WriteEndElement();
            }
        }
        private static void SerializeScope(
            MetadataBuilder metadataBuilder,
            MetadataModel metadataModel,
            MethodDefinitionHandle methodHandle,
            ImportScopeHandle importScopeHandle,
            ISymUnmanagedScope symScope,
            Dictionary <int, DynamicLocalInfo> dynamicSlots,
            Dictionary <string, DynamicLocalInfo> dynamicNames,
            bool vbSemantics,
            ref LocalVariableHandle lastLocalVariableHandle,
            ref LocalConstantHandle lastLocalConstantHandle)
        {
            // VB Windows PDB encode the range as end-inclusive,
            // all Portable PDBs use end-exclusive encoding.
            int start = symScope.GetStartOffset();
            int end   = symScope.GetEndOffset() + (vbSemantics ? 1 : 0);

            metadataBuilder.AddLocalScope(
                method: methodHandle,
                importScope: importScopeHandle,
                variableList: NextHandle(lastLocalVariableHandle),
                constantList: NextHandle(lastLocalConstantHandle),
                startOffset: start,
                length: end - start);

            foreach (var symLocal in symScope.GetLocals())
            {
                int    slot = symLocal.GetSlot();
                string name = symLocal.GetName();

                lastLocalVariableHandle = metadataBuilder.AddLocalVariable(
                    attributes: (LocalVariableAttributes)symLocal.GetAttributes(),
                    index: slot,
                    name: metadataBuilder.GetOrAddString(name));

                DynamicLocalInfo dynamicInfo;
                if (slot > 0 && dynamicSlots.TryGetValue(slot, out dynamicInfo) ||
                    slot == 0 && dynamicNames.TryGetValue(name, out dynamicInfo))
                {
                    metadataBuilder.AddCustomDebugInformation(
                        parent: lastLocalVariableHandle,
                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.DynamicLocalVariables),
                        value: SerializeDynamicLocalBlob(metadataBuilder, dynamicInfo));
                }
            }

            foreach (var symConstant in symScope.GetConstants())
            {
                string name  = symConstant.GetName();
                object value = symConstant.GetValue();

                lastLocalConstantHandle = metadataBuilder.AddLocalConstant(
                    name: metadataBuilder.GetOrAddString(name),
                    signature: SerializeConstantSignature(metadataBuilder, metadataModel, symConstant.GetSignature(), value));

                DynamicLocalInfo dynamicInfo;
                if (dynamicNames.TryGetValue(name, out dynamicInfo))
                {
                    metadataBuilder.AddCustomDebugInformation(
                        parent: lastLocalConstantHandle,
                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.DynamicLocalVariables),
                        value: SerializeDynamicLocalBlob(metadataBuilder, dynamicInfo));
                }
            }

            int previousChildScopeEnd = start;

            foreach (ISymUnmanagedScope child in symScope.GetChildren())
            {
                int childScopeStart = child.GetStartOffset();
                int childScopeEnd   = child.GetEndOffset();

                // scopes are properly nested:
                if (childScopeStart < previousChildScopeEnd || childScopeEnd > end)
                {
                    // TODO: loc/warning
                    throw new BadImageFormatException($"Invalid scope IL offset range: [{childScopeStart}, {childScopeEnd}), method 0x{MetadataTokens.GetToken(methodHandle):x}.");
                }

                previousChildScopeEnd = childScopeEnd;

                SerializeScope(metadataBuilder, metadataModel, methodHandle, importScopeHandle, child, dynamicSlots, dynamicNames, vbSemantics, ref lastLocalVariableHandle, ref lastLocalConstantHandle);
            }
        }
Beispiel #20
0
 public int GetEndOffset(out int pRetVal)
 {
     return(_scope.GetEndOffset(out pRetVal));
 }
Beispiel #21
0
        private void WriteLocalsHelper(ISymUnmanagedScope scope, Dictionary <int, ImmutableArray <string> > slotNames, bool includeChildScopes)
        {
            foreach (ISymUnmanagedVariable l in scope.GetLocals())
            {
                writer.WriteStartElement("local");
                {
                    writer.WriteAttributeString("name", l.GetName());

                    // Each local maps to a "IL Index" or "slot" number.
                    // The index is not necessarily unique. Several locals may refer to the same slot.
                    // It just means that the same local is known under different names inside the same or different scopes.
                    // This index is what you pass to ICorDebugILFrame::GetLocalVariable() to get
                    // a specific local variable.
                    // NOTE: VB emits "fake" locals for resumable locals which are actually backed by fields.
                    //       These locals always map to the slot #0 which is just a valid number that is
                    //       not used. Only scoping information is used by EE in this case.
                    int slot = l.GetSlot();
                    writer.WriteAttributeString("il_index", CultureInvariantToString(slot));

                    bool reusingSlot = false;

                    // collect slot names so that we can verify ISymUnmanagedReader APIs
                    if (slotNames != null)
                    {
                        ImmutableArray <string> existingNames;
                        if (slotNames.TryGetValue(slot, out existingNames))
                        {
                            slotNames[slot] = existingNames.Add(l.GetName());
                            reusingSlot     = true;
                        }
                        else
                        {
                            slotNames.Add(slot, ImmutableArray.Create(l.GetName()));
                        }
                    }

                    // Provide scope range
                    writer.WriteAttributeString("il_start", AsILOffset(scope.GetStartOffset()));
                    writer.WriteAttributeString("il_end", AsILOffset(scope.GetEndOffset()));
                    writer.WriteAttributeString("attributes", l.GetAttributes().ToString());

                    if (reusingSlot)
                    {
                        writer.WriteAttributeString("reusingslot", reusingSlot.ToString(CultureInfo.InvariantCulture));
                    }
                }
                writer.WriteEndElement(); // </local>
            }

            foreach (ISymUnmanagedConstant c in scope.GetConstants())
            {
                // Note: We can retrieve constant tokens by saving it into signature blob
                // in our implementation of IMetadataImport.GetSigFromToken.
                writer.WriteStartElement("constant");
                {
                    writer.WriteAttributeString("name", c.GetName());

                    object value    = c.GetValue();
                    string typeName = value.GetType().Name;

                    // certain Unicode characters will give Xml writers fits...in order to avoid this, we'll replace
                    // problematic characters/sequences with their hexadecimal equivalents, like U+0000, etc...
                    var chars = value as string;
                    if (chars != null)
                    {
                        PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
                        var valueWithPlaceholders  = pooled.Builder;
                        foreach (var ch in chars)
                        {
                            // if we end up with more, we can add them here
                            if (0 == (int)ch)
                            {
                                valueWithPlaceholders.AppendFormat("U+{0:X4}", (int)ch);
                            }
                            else
                            {
                                valueWithPlaceholders.Append(ch);
                            }
                        }
                        if (valueWithPlaceholders.Length > chars.Length)
                        {
                            value = valueWithPlaceholders.ToString();
                        }
                        pooled.Free();
                    }

                    writer.WriteAttributeString("value", value.ToString());
                    writer.WriteAttributeString("type", typeName);
                }
                writer.WriteEndElement(); // </constant>
            }

            if (includeChildScopes)
            {
                foreach (ISymUnmanagedScope childScope in scope.GetScopes())
                {
                    WriteLocalsHelper(childScope, slotNames, includeChildScopes);
                }
            }
        }
Beispiel #22
0
        private void WriteLocalsHelper(ISymUnmanagedScope scope, Dictionary<int, ImmutableArray<string>> slotNames, bool includeChildScopes)
        {
            foreach (ISymUnmanagedVariable l in scope.GetLocals())
            {
                writer.WriteStartElement("local");
                {
                    writer.WriteAttributeString("name", l.GetName());

                    // Each local maps to a "IL Index" or "slot" number. 
                    // The index is not necessarily unique. Several locals may refer to the same slot. 
                    // It just means that the same local is known under different names inside the same or different scopes.
                    // This index is what you pass to ICorDebugILFrame::GetLocalVariable() to get
                    // a specific local variable. 
                    // NOTE: VB emits "fake" locals for resumable locals which are actually backed by fields.
                    //       These locals always map to the slot #0 which is just a valid number that is 
                    //       not used. Only scoping information is used by EE in this case.
                    int slot = l.GetSlot();
                    writer.WriteAttributeString("il_index", CultureInvariantToString(slot));

                    bool reusingSlot = false;

                    // collect slot names so that we can verify ISymUnmanagedReader APIs
                    if (slotNames != null)
                    {
                        ImmutableArray<string> existingNames;
                        if (slotNames.TryGetValue(slot, out existingNames))
                        {
                            slotNames[slot] = existingNames.Add(l.GetName());
                            reusingSlot = true;
                        }
                        else
                        {
                            slotNames.Add(slot, ImmutableArray.Create(l.GetName()));
                        }
                    }

                    // Provide scope range
                    writer.WriteAttributeString("il_start", AsILOffset(scope.GetStartOffset()));
                    writer.WriteAttributeString("il_end", AsILOffset(scope.GetEndOffset()));
                    writer.WriteAttributeString("attributes", l.GetAttributes().ToString());

                    if (reusingSlot)
                    {
                        writer.WriteAttributeString("reusingslot", reusingSlot.ToString(CultureInfo.InvariantCulture));
                    }
                }
                writer.WriteEndElement(); // </local>
            }

            foreach (ISymUnmanagedConstant c in scope.GetConstants())
            {
                // Note: We can retrieve constant tokens by saving it into signature blob
                // in our implementation of IMetadataImport.GetSigFromToken.
                writer.WriteStartElement("constant");
                {
                    writer.WriteAttributeString("name", c.GetName());

                    object value = c.GetValue();
                    string typeName = value.GetType().Name;

                    // certain Unicode characters will give Xml writers fits...in order to avoid this, we'll replace
                    // problematic characters/sequences with their hexadecimal equivalents, like U+0000, etc...
                    var chars = value as string;
                    if (chars != null)
                    {
                        PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
                        var valueWithPlaceholders = pooled.Builder;
                        foreach (var ch in chars)
                        {
                            // if we end up with more, we can add them here
                            if (0 == (int)ch)
                            {
                                valueWithPlaceholders.AppendFormat("U+{0:X4}", (int)ch);
                            }
                            else
                            {
                                valueWithPlaceholders.Append(ch);
                            }
                        }
                        if (valueWithPlaceholders.Length > chars.Length)
                        {
                            value = valueWithPlaceholders.ToString();
                        }
                        pooled.Free();
                    }

                    writer.WriteAttributeString("value", value.ToString());
                    writer.WriteAttributeString("type", typeName);
                }
                writer.WriteEndElement(); // </constant>
            }

            if (includeChildScopes)
            {
                foreach (ISymUnmanagedScope childScope in scope.GetScopes())
                {
                    WriteLocalsHelper(childScope, slotNames, includeChildScopes);
                }
            }
        }