Exemplo n.º 1
0
        private void WriteMethod(Method m)
        {
            SymbolToken methodToken = Util.AsSymToken(m.token);
            m_writer.OpenMethod(methodToken);

            SymbolToken? localSigToken = null;
            if (m.localSigMetadataToken != null)
            {
                localSigToken = new SymbolToken(Util.ToInt32(m.localSigMetadataToken, 16));
            }
            WriteSequencePoints(m.sequencePoints);
            WriteScopesAndLocals(m.rootScope, localSigToken, m);
            WriteSymAttributes(m.symAttributes, methodToken);

            if (m.csharpCDI != null)
                WriteCSharpCDI(m.csharpCDI, methodToken);

            m_writer.CloseMethod();
        }
Exemplo n.º 2
0
        private void WriteScopesAndLocals(Scope scope, SymbolToken? localSigToken, Method method)
        {
            // If this scope is marked implicit then we won't explicitly write it out
            // This is usually used for the root scope
            if (!scope.isImplicit)
                m_writer.OpenScope(scope.startOffset);

            foreach (Variable localVar in scope.locals)
            {
                // Note that local variables can have a start/end offset within their enclosing scope.
                // Infortunately ISymUnmanagedVariable.GetStartOffset() returns E_NOTIMPL, so we
                // can't tell whether this was used or not.  Passing 0 says to use the start/end for
                // the entire scope (which is probably usually the case anyway).

                // Diasymreader.dll always stores local signatures by token, and if we use the V1
                // API will attempt to emit a new token to the metadata (which we don't support here).
                // IldbSymbols.dll on the other hand always stores signatures inline, and doesn't support
                // the V2 API.  RefEmit uses the V1 API, so it's fine to use it here for ILDB too.
                if (m_symFormat == SymbolFormat.PDB)
                {
                    if (localSigToken.HasValue)
                    {
                        m_writer.DefineLocalVariable(
                            localVar.name,
                            localVar.attributes,
                            localSigToken.Value,
                            (int)SymAddressKind.ILOffset, localVar.ilIndex, 0, 0,
                            0, 0); // start/end offsets - get from current scope
                    }
                    else
                    {
                        // We want to handle this case as gracefully since there is a bug in the C# compiler that
                        // can prevent us from getting the local var sig token.
                        // Note that we don't want to just use the V1 API with PDBs because we're not saving the
                        // metadata, and so the call to ISymUnmanagedVariable::GetSignature will just fail because
                        // the token will be invalid.
                        if (!method.hasInvalidMethodBody)
                            throw new FormatException("Missing localVarsigToken in a method without hasInvalidMethodBody set");
                    }
                }
                else
                {
                    byte[] sig = Util.ToByteArray(localVar.signature);
                    m_writer.DefineLocalVariable(
                        localVar.name,
                        (FieldAttributes)localVar.attributes,
                        sig,
                        SymAddressKind.ILOffset, localVar.ilIndex, 0, 0,
                        0, 0);   // start/end offsets - get from current scope
                }
            }

            foreach (Constant constant in scope.constants)
            {
                m_writer.DefineConstant(constant.name, constant.value, Util.ToByteArray(constant.signature));
            }

            // Now recursively write out any child scopes
            foreach (Scope childScope in scope.scopes)
            {
                WriteScopesAndLocals(childScope, localSigToken, method);
            }

            foreach (Namespace ns in scope.usedNamespaces)
            {
                m_writer.UsingNamespace(ns.name);
            }

            if (!scope.isImplicit)
                m_writer.CloseScope(scope.endOffset);
        }
Exemplo n.º 3
0
        // Dump all of the methods in the given ISymbolReader to the SymbolData provided
        private List<Method> ReadAllMethods(ISymbolReader reader)
        {
            List<Method> methods = new List<Method>();

            // Use reflection to enumerate all methods
            foreach (MethodBase methodReflection in GetAllMethods(m_assembly))
            {
                int token = methodReflection.MetadataToken;
                ISymbolMethod methodSymbol = reader.GetMethod(new SymbolToken(token));
                if (methodSymbol != null)
                {
                    Method methodData = new Method();
                    methodData.token = Util.AsToken(token);
                    methodData.name = methodReflection.DeclaringType.FullName + "::" + methodReflection.Name;

                    // This localSigMetadataToken information actually comes from the metadata in the assembly because the symbol reading API does not provide it.
                    try
                    {
                        MethodBody body = methodReflection.GetMethodBody();
                        int lSMT = body.LocalSignatureMetadataToken;
                        if (lSMT != 0)
                        {
                            methodData.localSigMetadataToken = Util.AsToken(lSMT);
                        }
                    }
                    catch (System.Security.VerificationException)
                    {
                        // Work around a CLR or C# compiler bug with Void& types in signatures
                        // <strip>See DevDiv Bugs 146662</strip>
                        methodData.hasInvalidMethodBody = true;
                    }

                    methodData.sequencePoints = ReadSequencePoints(methodSymbol);
                    methodData.rootScope = ReadScope(methodSymbol.RootScope);

                    // Read symbol attributes, except on ILDB where it isn't supported
                    if (m_symFormat != SymbolFormat.ILDB)
                    {
                        if (m_expandAttributes)
                            methodData.csharpCDI = ReadCSharpCDI(reader, methodSymbol);
                        methodData.symAttributes = ReadSymAttributes(reader, methodSymbol, methodData.csharpCDI != null);
                    }

                    if (m_symFormat == SymbolFormat.PDB)
                        WorkAroundDiasymreaderScopeBug(methodData.rootScope);

                    methods.Add(methodData);
                }
            }

            return methods;
        }