Beispiel #1
0
 private static void GetAllScopes(ISymUnmanagedScope scope, ArrayBuilder<ISymUnmanagedScope> builder, int offset, bool isScopeEndInclusive)
 {
     builder.Add(scope);
     foreach (var nested in scope.GetScopes())
     {
         if ((offset < 0) || nested.IsInScope(offset, isScopeEndInclusive))
         {
             GetAllScopes(nested, builder, offset, isScopeEndInclusive);
             if (offset >= 0)
             {
                 return;
             }
         }
     }
 }
Beispiel #2
0
 private static void GetAllScopes(ISymUnmanagedScope scope, ArrayBuilder <ISymUnmanagedScope> builder, int offset, bool isScopeEndInclusive)
 {
     builder.Add(scope);
     foreach (var nested in scope.GetScopes())
     {
         if ((offset < 0) || nested.IsInScope(offset, isScopeEndInclusive))
         {
             GetAllScopes(nested, builder, offset, isScopeEndInclusive);
             if (offset >= 0)
             {
                 return;
             }
         }
     }
 }
Beispiel #3
0
        /// <summary>
        /// Get the (unprocessed) import strings for a given method.
        /// </summary>
        /// <remarks>
        /// Doesn't consider forwarding.
        ///
        /// CONSIDER: Dev12 doesn't just check the root scope - it digs around to find the best
        /// match based on the IL offset and then walks up to the root scope (see PdbUtil::GetScopeFromOffset).
        /// However, it's not clear that this matters, since imports can't be scoped in VB.  This is probably
        /// just based on the way they were extracting locals and constants based on a specific scope.
        /// </remarks>
        internal static ImmutableArray <string> GetImportStrings(this ISymUnmanagedMethod method)
        {
            if (method == null)
            {
                // In rare circumstances (only bad PDBs?) GetMethodByVersion can return null.
                // If there's no debug info for the method, then no import strings are available.
                return(ImmutableArray <string> .Empty);
            }

            ISymUnmanagedScope rootScope = method.GetRootScope();

            if (rootScope == null)
            {
                Debug.Assert(false, "Expected a root scope.");
                return(ImmutableArray <string> .Empty);
            }

            ImmutableArray <ISymUnmanagedScope> childScopes = rootScope.GetScopes();

            if (childScopes.Length == 0)
            {
                // It seems like there should always be at least one child scope, but we've
                // seen PDBs where that is not the case.
                return(ImmutableArray <string> .Empty);
            }

            // As in NamespaceListWrapper::Init, we only consider namespaces in the first
            // child of the root scope.
            ISymUnmanagedScope firstChildScope = childScopes[0];

            ImmutableArray <ISymUnmanagedNamespace> namespaces = firstChildScope.GetNamespaces();

            if (namespaces.Length == 0)
            {
                // It seems like there should always be at least one namespace (i.e. the global
                // namespace), but we've seen PDBs where that is not the case.
                return(ImmutableArray <string> .Empty);
            }

            return(ImmutableArray.CreateRange(namespaces, n => n.GetName()));
        }
Beispiel #4
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>
        }
        /// <summary>
        /// Get the (unprocessed) import strings for a given method.
        /// </summary>
        /// <remarks>
        /// Doesn't consider forwarding.
        /// </remarks>
        private static ImmutableArray <string> GetImportStrings(this ISymUnmanagedMethod method)
        {
            ISymUnmanagedScope rootScope = method.GetRootScope();

            if (rootScope == null)
            {
                Debug.Assert(false, "Expected a root scope.");
                return(ImmutableArray <string> .Empty);
            }

            ImmutableArray <ISymUnmanagedScope> childScopes = rootScope.GetScopes();

            if (childScopes.Length == 0)
            {
                //Debug.Assert(false, "Expected at least one child scope."); // TODO (acasey): Why can't we assume this?
                return(ImmutableArray <string> .Empty);
            }

            // As in NamespaceListWrapper::Init, we only consider namespaces in the first
            // child of the root scope.
            ISymUnmanagedScope firstChildScope = childScopes[0];

            ImmutableArray <ISymUnmanagedNamespace> namespaces = firstChildScope.GetNamespaces();

            if (namespaces.Length == 0)
            {
                //Debug.Assert(false, "Expected at least one namespace (i.e. the global namespace)."); // TODO (acasey): Why can't we assume this?
                return(ImmutableArray <string> .Empty);
            }

            ArrayBuilder <string> importsBuilder = ArrayBuilder <string> .GetInstance(namespaces.Length);

            foreach (ISymUnmanagedNamespace @namespace in namespaces)
            {
                importsBuilder.Add(@namespace.GetName());
            }
            return(importsBuilder.ToImmutableAndFree());
        }
Beispiel #6
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 #7
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 #8
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(); 
        }
 private void WriteScopes(ISymUnmanagedScope rootScope)
 {
     // The root scope is always empty. The first scope opened by SymWriter is the child of the root scope.
     if (rootScope.GetNamespaces().IsEmpty && rootScope.GetLocals().IsEmpty && rootScope.GetConstants().IsEmpty)
     {
         foreach (ISymUnmanagedScope child in rootScope.GetScopes())
         {
             WriteScope(child, isRoot: false);
         }
     }
     else
     {
         // This shouldn't be executed for PDBs generated via SymWriter.
         WriteScope(rootScope, isRoot: true);
     }
 }
Beispiel #10
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);
                }
            }
        }