示例#1
0
        private static void ReadCSharpNativeCustomDebugInfo(
            ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion,
            IEnumerable <ISymUnmanagedScope> scopes,
            out ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopeRecords,
            out ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap,
            out ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap)
        {
            hoistedLocalScopeRecords = ImmutableArray <HoistedLocalScopeRecord> .Empty;
            dynamicLocalMap          = ImmutableDictionary <int, ImmutableArray <bool> > .Empty;
            dynamicLocalConstantMap  = ImmutableDictionary <string, ImmutableArray <bool> > .Empty;

            byte[] customDebugInfoBytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion);
            if (customDebugInfoBytes == null)
            {
                return;
            }

            var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBytes, CustomDebugInfoKind.StateMachineHoistedLocalScopes);

            if (!customDebugInfoRecord.IsDefault)
            {
                hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord)
                                           .SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.EndOffset - s.StartOffset + 1));
            }

            CustomDebugInfoReader.GetCSharpDynamicLocalInfo(
                customDebugInfoBytes,
                methodToken,
                methodVersion,
                scopes,
                out dynamicLocalMap,
                out dynamicLocalConstantMap);
        }
示例#2
0
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            int ilOffset,
            int localSignatureToken)
        {
            Debug.Assert(MetadataTokens.Handle(methodToken).Kind == HandleKind.MethodDefinition);

            var typedSymReader = (ISymUnmanagedReader)symReader;
            var scopes         = ArrayBuilder <ISymUnmanagedScope> .GetInstance();

            typedSymReader.GetScopes(methodToken, methodVersion, ilOffset, IsLocalScopeEndInclusive, scopes);
            var scope = scopes.GetMethodScope(methodToken, methodVersion);

            // Re-use the previous compilation if possible.
            CSharpCompilation compilation;

            if (metadataBlocks.HaveNotChanged(previous))
            {
                // Re-use entire context if method scope has not changed.
                var previousContext = previous.EvaluationContext;
                if ((scope != null) && (previousContext != null) && scope.Equals(previousContext.MethodScope))
                {
                    return(previousContext);
                }
                compilation = previous.Compilation;
            }
            else
            {
                compilation = metadataBlocks.ToCompilation();
            }

            var localNames = scopes.GetLocalNames();

            var dynamicLocalMap            = ImmutableDictionary <int, ImmutableArray <bool> > .Empty;
            var dynamicLocalConstantMap    = ImmutableDictionary <string, ImmutableArray <bool> > .Empty;
            var inScopeHoistedLocalIndices = ImmutableSortedSet <int> .Empty;
            var methodDebugInfo            = default(MethodDebugInfo);

            if (typedSymReader != null)
            {
                try
                {
                    var cdi = typedSymReader.GetCustomDebugInfoBytes(methodToken, methodVersion);
                    if (cdi != null)
                    {
                        CustomDebugInfoReader.GetCSharpDynamicLocalInfo(
                            cdi,
                            methodToken,
                            methodVersion,
                            localNames.FirstOrDefault(),
                            out dynamicLocalMap,
                            out dynamicLocalConstantMap);

                        inScopeHoistedLocalIndices = CustomDebugInfoReader.GetCSharpInScopeHoistedLocalIndices(
                            cdi,
                            methodToken,
                            methodVersion,
                            ilOffset);
                    }

                    // TODO (acasey): switch on the type of typedSymReader and call the appropriate helper. (GH #702)
                    methodDebugInfo = typedSymReader.GetMethodDebugInfo(methodToken, methodVersion);
                }
                catch (InvalidOperationException)
                {
                    // bad CDI, ignore
                }
            }

            var methodHandle = (MethodDefinitionHandle)MetadataTokens.Handle(methodToken);
            var currentFrame = compilation.GetMethod(moduleVersionId, methodHandle);

            Debug.Assert((object)currentFrame != null);
            var metadataDecoder = new MetadataDecoder((PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
            var localInfo       = metadataDecoder.GetLocalInfo(localSignatureToken);
            var localBuilder    = ArrayBuilder <LocalSymbol> .GetInstance();

            var sourceAssembly = compilation.SourceAssembly;

            GetLocals(localBuilder, currentFrame, localNames, localInfo, dynamicLocalMap, sourceAssembly);
            GetConstants(localBuilder, currentFrame, scopes.GetConstantSignatures(), metadataDecoder, dynamicLocalConstantMap, sourceAssembly);
            scopes.Free();

            var locals = localBuilder.ToImmutableAndFree();

            return(new EvaluationContext(
                       metadataBlocks,
                       scope,
                       compilation,
                       metadataDecoder,
                       currentFrame,
                       locals,
                       inScopeHoistedLocalIndices,
                       methodDebugInfo));
        }
示例#3
0
        public static MethodDebugInfo GetMethodDebugInfo(
            this ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion,
            ArrayBuilder <ISymUnmanagedScope> scopes)
        {
            ImmutableArray <string> externAliasStrings;
            var importStringGroups = reader.GetCSharpGroupedImportStrings(methodToken, methodVersion, out externAliasStrings);

            Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault);

            ArrayBuilder <ImmutableArray <ImportRecord> > importRecordGroupBuilder = null;
            ArrayBuilder <ExternAliasRecord> externAliasRecordBuilder = null;

            if (!importStringGroups.IsDefault)
            {
                importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length);

                foreach (var importStringGroup in importStringGroups)
                {
                    var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length);

                    foreach (var importString in importStringGroup)
                    {
                        ImportRecord record;
                        if (NativeImportRecord.TryCreateFromCSharpImportString(importString, out record))
                        {
                            groupBuilder.Add(record);
                        }
                        else
                        {
                            Debug.WriteLine($"Failed to parse import string {importString}");
                        }
                    }
                    importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree());
                }

                if (!externAliasStrings.IsDefault)
                {
                    externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length);

                    foreach (string externAliasString in externAliasStrings)
                    {
                        string           alias;
                        string           externAlias;
                        string           target;
                        ImportTargetKind kind;
                        if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind))
                        {
                            Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'");
                            continue;
                        }

                        Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?");
                        Debug.Assert(alias != null);       // Name of the extern alias.
                        Debug.Assert(externAlias == null); // Not used.
                        Debug.Assert(target != null);      // Name of the target assembly.

                        AssemblyIdentity targetIdentity;
                        if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity))
                        {
                            Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'");
                            continue;
                        }

                        externAliasRecordBuilder.Add(new NativeExternAliasRecord <AssemblySymbol>(alias, targetIdentity));
                    }
                }
            }

            var hoistedLocalScopeRecords = ImmutableArray <HoistedLocalScopeRecord> .Empty;
            var dynamicLocalMap          = ImmutableDictionary <int, ImmutableArray <bool> > .Empty;
            var dynamicLocalConstantMap  = ImmutableDictionary <string, ImmutableArray <bool> > .Empty;

            byte[] customDebugInfoBytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion);

            if (customDebugInfoBytes != null)
            {
                var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBytes, CustomDebugInfoKind.StateMachineHoistedLocalScopes);
                if (!customDebugInfoRecord.IsDefault)
                {
                    hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord)
                                               .SelectAsArray(s => HoistedLocalScopeRecord.FromNative(s.StartOffset, s.EndOffset));
                }

                CustomDebugInfoReader.GetCSharpDynamicLocalInfo(
                    customDebugInfoBytes,
                    methodToken,
                    methodVersion,
                    scopes,
                    out dynamicLocalMap,
                    out dynamicLocalConstantMap);
            }

            return(new MethodDebugInfo(
                       hoistedLocalScopeRecords,
                       importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty,
                       externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty,
                       dynamicLocalMap,
                       dynamicLocalConstantMap,
                       defaultNamespaceName: "")); // Unused in C#.
        }