Exemplo n.º 1
0
        public static EditAndContinueMethodDebugInformation GetEncMethodDebugInfo(byte[] customDebugInfoBlob)
        {
            var localSlots = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBlob, CustomDebugInfoKind.EditAndContinueLocalSlotMap);
            var lambdaMap  = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBlob, CustomDebugInfoKind.EditAndContinueLambdaMap);

            return(EditAndContinueMethodDebugInformation.Create(localSlots, lambdaMap));
        }
Exemplo n.º 2
0
        public void BadPdb_Cycle()
        {
            const int methodToken1 = 0x600057a; // Forwards to itself

            var getMethodCustomDebugInfo = new Func <int, int, byte[]>((token, _) =>
            {
                switch (token)
                {
                case methodToken1: return(new MethodDebugInfoBytes.Builder().AddForward(methodToken1).Build().Bytes.ToArray());

                default: throw null;
                }
            });

            var getMethodImportStrings = new Func <int, int, ImmutableArray <string> >((token, _) =>
            {
                return(ImmutableArray <string> .Empty);
            });

            ImmutableArray <string> externAliasStrings;
            var importStrings = CustomDebugInfoReader.GetCSharpGroupedImportStrings(methodToken1, 0, getMethodCustomDebugInfo, getMethodImportStrings, out externAliasStrings);

            Assert.True(importStrings.IsDefault);
            Assert.True(externAliasStrings.IsDefault);
        }
        private static bool TryCreateImportRecordFromCSharpImportString(EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, string importString, out ImportRecord record)
        {
            ImportTargetKind targetKind;
            string           externAlias;
            string           alias;
            string           targetString;

            if (CustomDebugInfoReader.TryParseCSharpImportString(importString, out alias, out externAlias, out targetString, out targetKind))
            {
                ITypeSymbol type = null;
                if (targetKind == ImportTargetKind.Type)
                {
                    type         = symbolProvider.GetTypeSymbolForSerializedType(targetString);
                    targetString = null;
                }

                record = new ImportRecord(
                    targetKind: targetKind,
                    alias: alias,
                    targetType: type,
                    targetString: targetString,
                    targetAssembly: null,
                    targetAssemblyAlias: externAlias);

                return(true);
            }

            record = default(ImportRecord);
            return(false);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        public void InvalidAlignment_KindDoesntSupportAlignment()
        {
            // CDIs that don't support alignment:
            var bytes = new byte[]
            {
                0x04, // version
                0x01, // count
                0x00,
                0x00,

                0x04, // version
                0x01, // kind
                0x11, // invalid data
                0x14, // invalid data

                // body size
                0x0c, 0x00, 0x00, 0x00,

                // payload
                0x01, 0x00, 0x00, 0x06
            };

            var records = CustomDebugInfoReader.GetCustomDebugInfoRecords(bytes).ToArray();

            Assert.Equal(1, records.Length);

            Assert.Equal(CustomDebugInfoKind.ForwardInfo, records[0].Kind);
            Assert.Equal(4, records[0].Version);
            AssertEx.Equal(new byte[] { 0x01, 0x00, 0x00, 0x06 }, records[0].Data);
        }
Exemplo n.º 6
0
 public static ImmutableArray <byte> GetEditAndContinueLambdaMapRecord(
     byte[] customDebugInfoBlob
     )
 {
     return(CustomDebugInfoReader.TryGetCustomDebugInfoRecord(
                customDebugInfoBlob,
                CustomDebugInfoKind.EditAndContinueLambdaMap
                ));
 }
        private static void ReadVisualBasicImportsDebugInfo(
            ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion,
            out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups,
            out string defaultNamespaceName)
        {
            importRecordGroups = ImmutableArray <ImmutableArray <ImportRecord> > .Empty;

            var importStrings = CustomDebugInfoReader.GetVisualBasicImportStrings(
                methodToken,
                KeyValuePairUtil.Create(reader, methodVersion),
                (token, arg) => GetImportStrings(arg.Key, token, arg.Value));

            if (importStrings.IsDefault)
            {
                defaultNamespaceName = "";
                return;
            }

            string?lazyDefaultNamespaceName  = null;
            var    projectLevelImportRecords = ArrayBuilder <ImportRecord> .GetInstance();

            var fileLevelImportRecords = ArrayBuilder <ImportRecord> .GetInstance();

            foreach (var importString in importStrings)
            {
                RoslynDebug.AssertNotNull(importString);

                if (importString.Length > 0 && importString[0] == '*')
                {
                    string?alias  = null;
                    string?target = null;

                    if (!CustomDebugInfoReader.TryParseVisualBasicImportString(importString, out alias, out target, out var kind, out var scope))
                    {
                        Debug.WriteLine($"Unable to parse import string '{importString}'");
                        continue;
                    }
                    else if (kind == ImportTargetKind.Defunct)
                    {
                        continue;
                    }

                    Debug.Assert(alias == null); // The default namespace is never aliased.
                    Debug.Assert(target != null);
                    Debug.Assert(kind == ImportTargetKind.DefaultNamespace);

                    // We only expect to see one of these, but it looks like ProcedureContext::LoadImportsAndDefaultNamespaceNormal
                    // implicitly uses the last one if there are multiple.
                    Debug.Assert(lazyDefaultNamespaceName == null);

                    lazyDefaultNamespaceName = target;
                }
Exemplo n.º 8
0
        /// <summary>
        /// Given a byte array of custom debug info, parse the array and write out XML describing
        /// its structure and contents.
        /// </summary>
        private void WriteCustomDebugInfo(byte[] bytes)
        {
            var records = CustomDebugInfoReader.GetCustomDebugInfoRecords(bytes).ToArray();

            writer.WriteStartElement("customDebugInfo");

            foreach (var record in records)
            {
                if (record.Version != CDIC.CdiVersion)
                {
                    WriteUnknownCustomDebugInfo(record);
                }
                else
                {
                    switch (record.Kind)
                    {
                    case CustomDebugInfoKind.UsingInfo:
                        WriteUsingCustomDebugInfo(record);
                        break;

                    case CustomDebugInfoKind.ForwardInfo:
                        WriteForwardCustomDebugInfo(record);
                        break;

                    case CustomDebugInfoKind.ForwardToModuleInfo:
                        WriteForwardToModuleCustomDebugInfo(record);
                        break;

                    case CustomDebugInfoKind.StateMachineHoistedLocalScopes:
                        WriteStatemachineHoistedLocalScopesCustomDebugInfo(record);
                        break;

                    case CustomDebugInfoKind.ForwardIterator:
                        WriteForwardIteratorCustomDebugInfo(record);
                        break;

                    case CustomDebugInfoKind.DynamicLocals:
                        WriteDynamicLocalsCustomDebugInfo(record);
                        break;

                    case CustomDebugInfoKind.EditAndContinueLocalSlotMap:
                        WriteEditAndContinueLocalSlotMap(record);
                        break;

                    default:
                        WriteUnknownCustomDebugInfo(record);
                        break;
                    }
                }
            }

            writer.WriteEndElement(); //customDebugInfo
        }
            public override EditAndContinueMethodDebugInformation GetDebugInfo(
                MethodDefinitionHandle methodHandle
                )
            {
                var methodToken = MetadataTokens.GetToken(methodHandle);

                byte[] debugInfo;
                try
                {
                    debugInfo = _symReader.GetCustomDebugInfo(methodToken, _version);
                }
                catch (ArgumentOutOfRangeException)
                {
                    // Sometimes the debugger returns the HRESULT for ArgumentOutOfRangeException, rather than E_FAIL,
                    // for methods without custom debug info (https://github.com/dotnet/roslyn/issues/4138).
                    debugInfo = null;
                }
                catch (Exception e) when(FatalError.ReportAndCatch(e))  // likely a bug in the compiler/debugger
                {
                    throw new InvalidDataException(e.Message, e);
                }

                try
                {
                    ImmutableArray <byte> localSlots,
                                          lambdaMap;
                    if (debugInfo != null)
                    {
                        localSlots = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(
                            debugInfo,
                            CustomDebugInfoKind.EditAndContinueLocalSlotMap
                            );
                        lambdaMap = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(
                            debugInfo,
                            CustomDebugInfoKind.EditAndContinueLambdaMap
                            );
                    }
                    else
                    {
                        localSlots = lambdaMap = default;
                    }

                    return(EditAndContinueMethodDebugInformation.Create(localSlots, lambdaMap));
                }
                catch (InvalidOperationException e) when(FatalError.ReportAndCatch(e))  // likely a bug in the compiler/debugger
                {
                    // TODO: CustomDebugInfoReader should throw InvalidDataException
                    throw new InvalidDataException(e.Message, e);
                }
            }
Exemplo n.º 10
0
        /// <exception cref="InvalidOperationException">Bad data.</exception>
        private static void GetCSharpDynamicLocalInfo(
            byte[] customDebugInfo,
            int methodToken,
            int methodVersion,
            IEnumerable <ISymUnmanagedScope> scopes,
            out ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap,
            out ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap)
        {
            dynamicLocalMap         = ImmutableDictionary <int, ImmutableArray <bool> > .Empty;
            dynamicLocalConstantMap = ImmutableDictionary <string, ImmutableArray <bool> > .Empty;

            var record = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.DynamicLocals);

            if (record.IsDefault)
            {
                return;
            }

            ImmutableDictionary <int, ImmutableArray <bool> > .Builder    localBuilder    = null;
            ImmutableDictionary <string, ImmutableArray <bool> > .Builder constantBuilder = null;

            var dynamicLocals = RemoveAmbiguousLocals(CustomDebugInfoReader.DecodeDynamicLocalsRecord(record), scopes);

            foreach (var dynamicLocal in dynamicLocals)
            {
                int slot  = dynamicLocal.SlotId;
                var flags = GetFlags(dynamicLocal);
                if (slot < 0)
                {
                    constantBuilder = constantBuilder ?? ImmutableDictionary.CreateBuilder <string, ImmutableArray <bool> >();
                    constantBuilder[dynamicLocal.Name] = flags;
                }
                else
                {
                    localBuilder       = localBuilder ?? ImmutableDictionary.CreateBuilder <int, ImmutableArray <bool> >();
                    localBuilder[slot] = flags;
                }
            }

            if (localBuilder != null)
            {
                dynamicLocalMap = localBuilder.ToImmutable();
            }

            if (constantBuilder != null)
            {
                dynamicLocalConstantMap = constantBuilder.ToImmutable();
            }
        }
        private static void GetTupleElementNamesLocalInfo(
            byte[] customDebugInfo,
            out ImmutableDictionary <int, ImmutableArray <string> > tupleLocalMap,
            out ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > tupleLocalConstantMap)
        {
            tupleLocalMap         = null;
            tupleLocalConstantMap = null;

            var record = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.TupleElementNames);

            if (record.IsDefault)
            {
                return;
            }

            ImmutableDictionary <int, ImmutableArray <string> > .Builder localBuilder = null;
            ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > .Builder constantBuilder = null;

            var tuples = CustomDebugInfoReader.DecodeTupleElementNamesRecord(record);

            foreach (var tuple in tuples)
            {
                var slotIndex    = tuple.SlotIndex;
                var elementNames = tuple.ElementNames;
                if (slotIndex < 0)
                {
                    constantBuilder = constantBuilder ?? ImmutableDictionary.CreateBuilder <LocalNameAndScope, ImmutableArray <string> >();
                    var localAndScope = new LocalNameAndScope(tuple.LocalName, tuple.ScopeStart, tuple.ScopeEnd);
                    constantBuilder[localAndScope] = elementNames;
                }
                else
                {
                    localBuilder            = localBuilder ?? ImmutableDictionary.CreateBuilder <int, ImmutableArray <string> >();
                    localBuilder[slotIndex] = elementNames;
                }
            }

            if (localBuilder != null)
            {
                tupleLocalMap = localBuilder.ToImmutable();
            }

            if (constantBuilder != null)
            {
                tupleLocalConstantMap = constantBuilder.ToImmutable();
            }
        }
Exemplo n.º 12
0
        public void BadPdb_ForwardChain()
        {
            const int    methodToken1 = 0x600057a; // Forwards to 2
            const int    methodToken2 = 0x600055d; // Forwards to 3
            const int    methodToken3 = 0x6000540; // Has a using
            const string importString = "USystem";

            var getMethodCustomDebugInfo = new Func <int, int, byte[]>((token, _) =>
            {
                switch (token)
                {
                case methodToken1: return(new MethodDebugInfoBytes.Builder().AddForward(methodToken2).Build().Bytes.ToArray());

                case methodToken2: return(new MethodDebugInfoBytes.Builder().AddForward(methodToken3).Build().Bytes.ToArray());

                case methodToken3: return(new MethodDebugInfoBytes.Builder(new[] { new[] { importString } }).Build().Bytes.ToArray());

                default: throw null;
                }
            });

            var getMethodImportStrings = new Func <int, int, ImmutableArray <string> >((token, _) =>
            {
                switch (token)
                {
                case methodToken3: return(ImmutableArray.Create(importString));

                default: throw null;
                }
            });

            ImmutableArray <string> externAliasStrings;
            var importStrings = CustomDebugInfoReader.GetCSharpGroupedImportStrings(methodToken1, 0, getMethodCustomDebugInfo, getMethodImportStrings, out externAliasStrings);

            Assert.True(importStrings.IsDefault);
            Assert.True(externAliasStrings.IsDefault);

            importStrings = CustomDebugInfoReader.GetCSharpGroupedImportStrings(methodToken2, 0, getMethodCustomDebugInfo, getMethodImportStrings, out externAliasStrings);
            Assert.Equal(importString, importStrings.Single().Single());
            Assert.Equal(0, externAliasStrings.Length);

            importStrings = CustomDebugInfoReader.GetCSharpGroupedImportStrings(methodToken2, 0, getMethodCustomDebugInfo, getMethodImportStrings, out externAliasStrings);
            Assert.Equal(importString, importStrings.Single().Single());
            Assert.Equal(0, externAliasStrings.Length);
        }
        public static bool TryCreateFromVisualBasicImportString(string importString, out ImportRecord record, out ImportScope scope)
        {
            ImportTargetKind targetKind;
            string           alias;
            string           targetString;

            if (CustomDebugInfoReader.TryParseVisualBasicImportString(importString, out alias, out targetString, out targetKind, out scope))
            {
                record = new NativeImportRecord(
                    targetKind,
                    externAlias: null,
                    alias: alias,
                    targetString: targetString);
                return(true);
            }

            record = default(ImportRecord);
            return(false);
        }
        public static bool TryCreateFromCSharpImportString(string importString, out ImportRecord record)
        {
            ImportTargetKind targetKind;
            string           externAlias;
            string           alias;
            string           targetString;

            if (CustomDebugInfoReader.TryParseCSharpImportString(importString, out alias, out externAlias, out targetString, out targetKind))
            {
                record = new NativeImportRecord(
                    targetKind,
                    externAlias,
                    alias,
                    targetString);
                return(true);
            }

            record = default(ImportRecord);
            return(false);
        }
        private static bool TryParseImportString(string importString, out ImportInfo import, bool vbSemantics)
        {
            ImportTargetKind kind;
            string           target;
            string           alias;
            string           externAlias = null;
            var scope = VBImportScopeKind.Unspecified;

            if (vbSemantics ?
                CustomDebugInfoReader.TryParseVisualBasicImportString(importString, out alias, out target, out kind, out scope) :
                CustomDebugInfoReader.TryParseCSharpImportString(importString, out alias, out externAlias, out target, out kind))
            {
                import = new ImportInfo(kind, target, alias, externAlias, scope);
                return(true);
            }

            // TODO: report warning
            import = default(ImportInfo);
            return(false);
        }
        private static bool TryCreateImportRecordFromVisualBasicImportString(string importString, out ImportRecord record, out VBImportScopeKind scope)
        {
            ImportTargetKind targetKind;
            string           alias;
            string           targetString;

            if (CustomDebugInfoReader.TryParseVisualBasicImportString(importString, out alias, out targetString, out targetKind, out scope))
            {
                record = new ImportRecord(
                    targetKind: targetKind,
                    alias: alias,
                    targetType: null,
                    targetString: targetString,
                    targetAssembly: null,
                    targetAssemblyAlias: null);

                return(true);
            }

            record = default(ImportRecord);
            return(false);
        }
Exemplo n.º 17
0
        public void InvalidAlignment2()
        {
            // CDIs that don't support alignment:
            var bytes = new byte[]
            {
                0x04, // version
                0x01, // count
                0x00,
                0x00,

                0x04, // version
                0x06, // kind
                0x00,
                0x03, // bad alignment

                // body size
                0x02, 0x00, 0x00, 0x00,

                // payload
                0x01, 0x00, 0x00, 0x06
            };

            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.GetCustomDebugInfoRecords(bytes).ToArray());
        }
        public static void Convert(Stream peStream, Stream sourcePdbStream, Stream targetPdbStream)
        {
            var metadataBuilder = new MetadataBuilder();
            ImmutableArray <int> typeSystemRowCounts;
            var debugEntryPointToken = default(MethodDefinitionHandle);
            var pdbId = default(BlobContentId);

            try
            {
                using (var peReader = new PEReader(peStream))
                {
                    pdbId = ReadPdbId(peReader);

                    var symReader = SymReaderFactory.CreateWindowsPdbReader(sourcePdbStream, peReader);

                    var metadataReader = peReader.GetMetadataReader();
                    var metadataModel  = new MetadataModel(metadataReader);

                    typeSystemRowCounts  = metadataModel.GetRowCounts();
                    debugEntryPointToken = ReadEntryPointHandle(symReader);

                    // documents:
                    var documentIndex = new Dictionary <string, DocumentHandle>(StringComparer.Ordinal);
                    var documents     = symReader.GetDocuments();
                    metadataBuilder.SetCapacity(TableIndex.Document, documents.Length);

                    bool vbSemantics = false;

                    foreach (var document in documents)
                    {
                        string name     = document.GetName();
                        Guid   language = document.GetLanguage();

                        // TODO:
                        // won't work for IL-merged assmemblies
                        vbSemantics |= language == SymReaderHelpers.VisualBasicLanguageGuid;

                        var rid = metadataBuilder.AddDocument(
                            name: metadataBuilder.GetOrAddDocumentName(name),
                            hashAlgorithm: metadataBuilder.GetOrAddGuid(document.GetHashAlgorithm()),
                            hash: metadataBuilder.GetOrAddBlob(document.GetChecksum()),
                            language: metadataBuilder.GetOrAddGuid(language));

                        documentIndex.Add(name, rid);
                    }

                    var lastLocalVariableHandle = default(LocalVariableHandle);
                    var lastLocalConstantHandle = default(LocalConstantHandle);

                    var importStringsByMethod = new Dictionary <int, ImmutableArray <string> >();
                    var importScopesByMethod  = new Dictionary <int, ImportScopeHandle>();

                    // Maps import scope content to import scope handles
                    var importScopeIndex = new Dictionary <ImportScopeInfo, ImportScopeHandle>();
                    var importScopes     = new List <ImportScopeInfo>();

                    // reserve slot for module import scope:
                    importScopes.Add(default(ImportScopeInfo));

                    var externAliasImports   = new List <ImportInfo>();
                    var externAliasStringSet = new HashSet <string>(StringComparer.Ordinal);

                    string vbDefaultNamespace    = null;
                    var    vbProjectLevelImports = new List <ImportInfo>();

                    // first pass:
                    foreach (var methodHandle in metadataReader.MethodDefinitions)
                    {
                        int methodToken = MetadataTokens.GetToken(methodHandle);
                        ImmutableArray <ImmutableArray <ImportInfo> > importGroups;

                        if (vbSemantics)
                        {
                            var importStrings = CustomDebugInfoReader.GetVisualBasicImportStrings(
                                methodToken,
                                symReader,
                                getMethodImportStrings: (token, sr) => GetImportStrings(token, importStringsByMethod, sr));

                            if (importStrings.IsEmpty)
                            {
                                // no debug info
                                continue;
                            }

                            var vbFileLevelImports = ArrayBuilder <ImportInfo> .GetInstance();

                            foreach (var importString in importStrings)
                            {
                                if (TryParseImportString(importString, out var import, vbSemantics: true))
                                {
                                    if (import.Kind == ImportTargetKind.DefaultNamespace)
                                    {
                                        vbDefaultNamespace = import.Target;
                                    }
                                    else if (import.Scope == VBImportScopeKind.Project)
                                    {
                                        vbProjectLevelImports.Add(import);
                                    }
                                    else
                                    {
                                        vbFileLevelImports.Add(import);
                                    }
                                }
                            }

                            importGroups = ImmutableArray.Create(vbFileLevelImports.ToImmutableAndFree());
                        }
                        else
                        {
                            var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings(
                                methodToken,
                                symReader,
                                getMethodCustomDebugInfo: (token, sr) => sr.GetCustomDebugInfo(token, methodVersion: 1),
                                getMethodImportStrings: (token, sr) => GetImportStrings(token, importStringsByMethod, sr),
                                externAliasStrings: out var localExternAliasStrings);

                            if (importStringGroups.IsDefault)
                            {
                                // no debug info
                                continue;
                            }

                            if (!localExternAliasStrings.IsDefault)
                            {
                                foreach (var externAlias in localExternAliasStrings)
                                {
                                    if (externAliasStringSet.Add(externAlias) &&
                                        TryParseImportString(externAlias, out var import, vbSemantics: false))
                                    {
                                        externAliasImports.Add(import);
                                    }
                                }
                            }

                            importGroups = ImmutableArray.CreateRange(importStringGroups.Select(g => ParseImportStrings(g, vbSemantics: false)));
                        }

                        var importScopeHandle = DefineImportScope(importGroups, importScopeIndex, importScopes);
                        importScopesByMethod.Add(methodToken, importScopeHandle);
                    }

                    // import scopes:
                    metadataBuilder.AddImportScope(
                        parentScope: default(ImportScopeHandle),
                        imports: SerializeModuleImportScope(metadataBuilder, externAliasImports, vbProjectLevelImports, vbDefaultNamespace, metadataModel));

                    for (int i = 1; i < importScopes.Count; i++)
                    {
                        metadataBuilder.AddImportScope(
                            parentScope: importScopes[i].Parent,
                            imports: SerializeImportsBlob(metadataBuilder, importScopes[i].Imports, metadataModel));
                    }

                    var dynamicNames = new Dictionary <string, DynamicLocalInfo>();
                    var dynamicSlots = new Dictionary <int, DynamicLocalInfo>();

                    // methods:
                    metadataBuilder.SetCapacity(TableIndex.MethodDebugInformation, metadataReader.MethodDefinitions.Count);
                    foreach (var methodHandle in metadataReader.MethodDefinitions)
                    {
                        var methodDef   = metadataReader.GetMethodDefinition(methodHandle);
                        int methodToken = MetadataTokens.GetToken(methodHandle);

                        var symMethod = symReader.GetMethod(methodToken);
                        if (symMethod == null)
                        {
                            metadataBuilder.AddMethodDebugInformation(default(DocumentHandle), sequencePoints: default(BlobHandle));
                            continue;
                        }

                        // method debug info:
                        int localSignatureRowId;
                        if (methodDef.RelativeVirtualAddress != 0)
                        {
                            var methodBody = peReader.GetMethodBody(methodDef.RelativeVirtualAddress);
                            localSignatureRowId = methodBody.LocalSignature.IsNil ? 0 : MetadataTokens.GetRowNumber(methodBody.LocalSignature);
                        }
                        else
                        {
                            localSignatureRowId = 0;
                        }

                        var symSequencePoints = symMethod.GetSequencePoints().ToImmutableArray();

                        DocumentHandle singleDocumentHandle;
                        BlobHandle     sequencePointsBlob = SerializeSequencePoints(metadataBuilder, localSignatureRowId, symSequencePoints, documentIndex, out singleDocumentHandle);

                        metadataBuilder.AddMethodDebugInformation(
                            document: singleDocumentHandle,
                            sequencePoints: sequencePointsBlob);

                        // state machine and async info:
                        var symAsyncMethod = symMethod.AsAsyncMethod();
                        if (symAsyncMethod != null)
                        {
                            var kickoffToken = MetadataTokens.Handle(symAsyncMethod.GetKickoffMethod());
                            metadataBuilder.AddStateMachineMethod(
                                moveNextMethod: methodHandle,
                                kickoffMethod: (MethodDefinitionHandle)kickoffToken);

                            metadataBuilder.AddCustomDebugInformation(
                                parent: methodHandle,
                                kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.AsyncMethodSteppingInformationBlob),
                                value: SerializeAsyncMethodSteppingInfo(metadataBuilder, symAsyncMethod, MetadataTokens.GetRowNumber(methodHandle)));
                        }

                        // custom debug information:
                        var dynamicLocals = default(ImmutableArray <DynamicLocalInfo>);

                        byte[] customDebugInfoBytes = symReader.GetCustomDebugInfo(methodToken, methodVersion: 1);
                        if (customDebugInfoBytes != null)
                        {
                            foreach (var record in CustomDebugInfoReader.GetCustomDebugInfoRecords(customDebugInfoBytes))
                            {
                                switch (record.Kind)
                                {
                                case CustomDebugInfoKind.DynamicLocals:
                                    dynamicLocals = CustomDebugInfoReader.DecodeDynamicLocalsRecord(record.Data);
                                    break;

                                case CustomDebugInfoKind.StateMachineHoistedLocalScopes:
                                    metadataBuilder.AddCustomDebugInformation(
                                        parent: methodHandle,
                                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.EncLocalSlotMap),
                                        value: SerializeStateMachineHoistedLocalsBlob(metadataBuilder, CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(record.Data)));
                                    break;

                                case CustomDebugInfoKind.EditAndContinueLocalSlotMap:
                                    metadataBuilder.AddCustomDebugInformation(
                                        parent: methodHandle,
                                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.EncLocalSlotMap),
                                        value: metadataBuilder.GetOrAddBlob(record.Data));
                                    break;

                                case CustomDebugInfoKind.EditAndContinueLambdaMap:
                                    metadataBuilder.AddCustomDebugInformation(
                                        parent: methodHandle,
                                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.EncLambdaAndClosureMap),
                                        value: metadataBuilder.GetOrAddBlob(record.Data));
                                    break;
                                }
                            }
                        }

                        var rootScope = symMethod.GetRootScope();
                        if (rootScope.GetNamespaces().Length == 0 || rootScope.GetLocals().Length == 0 || rootScope.GetConstants().Length == 0)
                        {
                            dynamicNames.Clear();
                            dynamicSlots.Clear();

                            foreach (var dynamicLocal in dynamicLocals)
                            {
                                if (dynamicLocal.SlotId == 0)
                                {
                                    // All dynamic constants have slot id == 0,
                                    // but a variable can also have slot id == 0
                                    if (!dynamicNames.ContainsKey(dynamicLocal.LocalName))
                                    {
                                        dynamicNames.Add(dynamicLocal.LocalName, dynamicLocal);
                                    }
                                    else
                                    {
                                        // TODO: warning
                                    }
                                }
                                else if (!dynamicSlots.ContainsKey(dynamicLocal.SlotId))
                                {
                                    dynamicSlots.Add(dynamicLocal.SlotId, dynamicLocal);
                                }
                                else
                                {
                                    // TODO: warning
                                }
                            }

                            foreach (ISymUnmanagedScope scope in rootScope.GetChildren())
                            {
                                SerializeScope(
                                    metadataBuilder,
                                    metadataModel,
                                    methodHandle,
                                    importScopesByMethod[methodToken],
                                    scope,
                                    dynamicSlots,
                                    dynamicNames,
                                    vbSemantics,
                                    ref lastLocalVariableHandle,
                                    ref lastLocalConstantHandle);
                            }
                        }
                        else
                        {
                            // TODO: warning:
                            // "Root scope must be empty (method 0x{0:x8})", MetadataTokens.GetToken(methodHandle))
                        }
                    }
                }
            }
            catch (COMException e)
            {
                // TODO: loc
                throw new BadImageFormatException("Invalid PDB format: " + e.Message, e);
            }

            var         serializer  = new PortablePdbBuilder(metadataBuilder, typeSystemRowCounts, debugEntryPointToken, idProvider: _ => pdbId);
            BlobBuilder blobBuilder = new BlobBuilder();

            serializer.Serialize(blobBuilder);
            blobBuilder.WriteContentTo(targetPdbStream);
        }
Exemplo n.º 19
0
        public void EncCdiAlignment()
        {
            var slots = ImmutableArray.Create(
                new LocalSlotDebugInfo(SynthesizedLocalKind.UserDefined, new LocalDebugId(-1, 10)),
                new LocalSlotDebugInfo(SynthesizedLocalKind.TryAwaitPendingCaughtException, new LocalDebugId(-20000, 10)));

            var closures = ImmutableArray.Create(
                new ClosureDebugInfo(-100, new DebugId(0, 0)),
                new ClosureDebugInfo(10, new DebugId(1, 0)),
                new ClosureDebugInfo(-200, new DebugId(2, 0)));

            var lambdas = ImmutableArray.Create(
                new LambdaDebugInfo(20, new DebugId(0, 0), 1),
                new LambdaDebugInfo(-50, new DebugId(1, 0), 0),
                new LambdaDebugInfo(-180, new DebugId(2, 0), LambdaDebugInfo.StaticClosureOrdinal));

            var debugInfo = new EditAndContinueMethodDebugInformation(1, slots, closures, lambdas);
            var records   = new ArrayBuilder <Cci.PooledBlobBuilder>();

            Cci.CustomDebugInfoWriter.SerializeCustomDebugInformation(debugInfo, records);
            var cdi = Cci.CustomDebugInfoWriter.SerializeCustomDebugMetadata(records);

            Assert.Equal(2, records.Count);

            AssertEx.Equal(new byte[]
            {
                0x04, // version
                0x06, // record kind
                0x00,
                0x02, // alignment size

                // aligned record size
                0x18, 0x00, 0x00, 0x00,

                // payload (4B aligned)
                0xFF, 0xC0, 0x00, 0x4E,
                0x20, 0x81, 0xC0, 0x00,
                0x4E, 0x1F, 0x0A, 0x9A,
                0x00, 0x0A, 0x00, 0x00
            }, records[0].ToArray());

            AssertEx.Equal(new byte[]
            {
                0x04, // version
                0x07, // record kind
                0x00,
                0x00, // alignment size

                // aligned record size
                0x18, 0x00, 0x00, 0x00,

                // payload (4B aligned)
                0x02, 0x80, 0xC8, 0x03,
                0x64, 0x80, 0xD2, 0x00,
                0x80, 0xDC, 0x03, 0x80,
                0x96, 0x02, 0x14, 0x01
            }, records[1].ToArray());

            var deserialized = CustomDebugInfoReader.GetCustomDebugInfoRecords(cdi).ToArray();

            Assert.Equal(CustomDebugInfoKind.EditAndContinueLocalSlotMap, deserialized[0].Kind);
            Assert.Equal(4, deserialized[0].Version);

            Assert.Equal(new byte[]
            {
                0xFF, 0xC0, 0x00, 0x4E,
                0x20, 0x81, 0xC0, 0x00,
                0x4E, 0x1F, 0x0A, 0x9A,
                0x00, 0x0A
            }, deserialized[0].Data);

            Assert.Equal(CustomDebugInfoKind.EditAndContinueLambdaMap, deserialized[1].Kind);
            Assert.Equal(4, deserialized[1].Version);

            Assert.Equal(new byte[]
            {
                0x02, 0x80, 0xC8, 0x03,
                0x64, 0x80, 0xD2, 0x00,
                0x80, 0xDC, 0x03, 0x80,
                0x96, 0x02, 0x14, 0x01
            }, deserialized[1].Data);
        }
Exemplo n.º 20
0
        public void TryGetCustomDebugInfoRecord1()
        {
            byte[] cdi;

            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.TryGetCustomDebugInfoRecord(new byte[0], CustomDebugInfoKind.EditAndContinueLocalSlotMap));
            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.TryGetCustomDebugInfoRecord(new byte[] { 1 }, CustomDebugInfoKind.EditAndContinueLocalSlotMap));
            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.TryGetCustomDebugInfoRecord(new byte[] { 1, 2 }, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // unknown version
            Assert.True(CustomDebugInfoReader.TryGetCustomDebugInfoRecord(new byte[] { 5, 1, 0, 0 }, CustomDebugInfoKind.EditAndContinueLocalSlotMap).IsDefault);

            // incomplete record header
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                4, (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap,
            };

            Assert.True(CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap).IsDefault);

            // record size too small
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0, 0, 0, 0,
            };

            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // invalid record size = Int32.MinValue
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x00, 0x00, 0x00, 0x80,
                0, 0, 0, 0
            };

            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // empty record
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x08, 0x00, 0x00, 0x00,
            };

            Assert.True(CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap).IsEmpty);

            // record size too big
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x0a, 0x00, 0x00, 0x00,
                0xab
            };

            Assert.Throws <InvalidOperationException>(() => CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // valid record
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xab
            };

            AssertEx.Equal(new byte[] { 0xab }, CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // record not matching
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.DynamicLocals, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xab
            };

            Assert.True(CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap).IsDefault);

            // unknown record kind
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ 0xff, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xab
            };

            Assert.True(CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap).IsDefault);

            // multiple records (number in global header is ignored, the first matching record is returned)
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xab,
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xcd
            };

            AssertEx.Equal(new byte[] { 0xab }, CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // multiple records (number in global header is ignored, the first record is returned)
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.DynamicLocals, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xab,
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xcd
            };

            AssertEx.Equal(new byte[] { 0xcd }, CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.EditAndContinueLocalSlotMap));

            // multiple records (number in global header is ignored, the first record is returned)
            cdi = new byte[]
            {
                4, 1, 0, 0, // global header
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.DynamicLocals, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xab,
                /*version*/ 4, /*kind*/ (byte)CustomDebugInfoKind.EditAndContinueLocalSlotMap, /*padding*/ 0, 0, /*size:*/ 0x09, 0x00, 0x00, 0x00,
                0xcd
            };

            AssertEx.Equal(new byte[] { 0xab }, CustomDebugInfoReader.TryGetCustomDebugInfoRecord(cdi, CustomDebugInfoKind.DynamicLocals));
        }
Exemplo n.º 21
0
        public static MethodDebugInfo GetMethodDebugInfo(
            this ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion)
        {
            ImmutableArray <string> externAliasStrings;
            var importStringGroups = reader.GetCSharpGroupedImportStrings(methodToken, methodVersion, out externAliasStrings);

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

            if (importStringGroups.IsDefault)
            {
                return(default(MethodDebugInfo));
            }

            var 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());
            }

            var 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));
            }

            return(new MethodDebugInfo(
                       importRecordGroupBuilder.ToImmutableAndFree(),
                       externAliasRecordBuilder.ToImmutableAndFree(),
                       defaultNamespaceName: "")); // Unused in C#.
        }
        public unsafe static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadMethodDebugInfo(
            ISymUnmanagedReader3 symReader,
            EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProviderOpt, // TODO: only null in DTEE case where we looking for default namesapace
            int methodToken,
            int methodVersion,
            int ilOffset,
            bool isVisualBasicMethod)
        {
            // no symbols
            if (symReader == null)
            {
                return(None);
            }

            if (symReader is ISymUnmanagedReader5 symReader5)
            {
                int hr = symReader5.GetPortableDebugMetadataByVersion(methodVersion, out byte *metadata, out int size);
                ThrowExceptionForHR(hr);

                if (hr == S_OK)
                {
                    var mdReader = new MetadataReader(metadata, size);
                    try
                    {
                        return(ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt, isVisualBasicMethod));
                    }
                    catch (BadImageFormatException)
                    {
                        // bad CDI, ignore
                        return(None);
                    }
                }
            }

            var allScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance();

            var containingScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance();

            try
            {
                var symMethod = symReader.GetMethodByVersion(methodToken, methodVersion);
                if (symMethod != null)
                {
                    symMethod.GetAllScopes(allScopes, containingScopes, ilOffset, isScopeEndInclusive: isVisualBasicMethod);
                }

                ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups;
                ImmutableArray <ExternAliasRecord> externAliasRecords;
                string defaultNamespaceName;

                if (isVisualBasicMethod)
                {
                    ReadVisualBasicImportsDebugInfo(
                        symReader,
                        methodToken,
                        methodVersion,
                        out importRecordGroups,
                        out defaultNamespaceName);

                    externAliasRecords = ImmutableArray <ExternAliasRecord> .Empty;
                }
                else
                {
                    Debug.Assert(symbolProviderOpt != null);

                    ReadCSharpNativeImportsInfo(
                        symReader,
                        symbolProviderOpt,
                        methodToken,
                        methodVersion,
                        out importRecordGroups,
                        out externAliasRecords);

                    defaultNamespaceName = "";
                }

                // VB should read hoisted scope information from local variables:
                var hoistedLocalScopeRecords = isVisualBasicMethod ?
                                               default(ImmutableArray <HoistedLocalScopeRecord>) :
                                               ImmutableArray <HoistedLocalScopeRecord> .Empty;

                ImmutableDictionary <int, ImmutableArray <bool> >    dynamicLocalMap                    = null;
                ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap            = null;
                ImmutableDictionary <int, ImmutableArray <string> >  tupleLocalMap                      = null;
                ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > tupleLocalConstantMap = null;

                byte[] customDebugInfo = GetCustomDebugInfoBytes(symReader, methodToken, methodVersion);
                if (customDebugInfo != null)
                {
                    if (!isVisualBasicMethod)
                    {
                        var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.StateMachineHoistedLocalScopes);
                        if (!customDebugInfoRecord.IsDefault)
                        {
                            hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord)
                                                       .SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.Length));
                        }

                        GetCSharpDynamicLocalInfo(
                            customDebugInfo,
                            allScopes,
                            out dynamicLocalMap,
                            out dynamicLocalConstantMap);
                    }

                    GetTupleElementNamesLocalInfo(
                        customDebugInfo,
                        out tupleLocalMap,
                        out tupleLocalConstantMap);
                }

                var constantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance();

                if (symbolProviderOpt != null) // TODO
                {
                    GetConstants(constantsBuilder, symbolProviderOpt, containingScopes, dynamicLocalConstantMap, tupleLocalConstantMap);
                }

                var reuseSpan = GetReuseSpan(allScopes, ilOffset, isVisualBasicMethod);

                return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>(
                           hoistedLocalScopeRecords,
                           importRecordGroups,
                           externAliasRecords,
                           dynamicLocalMap,
                           tupleLocalMap,
                           defaultNamespaceName,
                           containingScopes.GetLocalNames(),
                           constantsBuilder.ToImmutableAndFree(),
                           reuseSpan));
            }
            catch (InvalidOperationException)
            {
                // bad CDI, ignore
                return(None);
            }
            finally
            {
                allScopes.Free();
                containingScopes.Free();
            }
        }
        private static void ReadVisualBasicImportsDebugInfo(
            ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion,
            out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups,
            out string defaultNamespaceName)
        {
            importRecordGroups = ImmutableArray <ImmutableArray <ImportRecord> > .Empty;

            var importStrings = CustomDebugInfoReader.GetVisualBasicImportStrings(
                methodToken,
                KeyValuePair.Create(reader, methodVersion),
                (token, arg) => GetImportStrings(arg.Key, token, arg.Value));

            if (importStrings.IsDefault)
            {
                defaultNamespaceName = "";
                return;
            }

            defaultNamespaceName = null;
            var projectLevelImportRecords = ArrayBuilder <ImportRecord> .GetInstance();

            var fileLevelImportRecords = ArrayBuilder <ImportRecord> .GetInstance();

            foreach (string importString in importStrings)
            {
                Debug.Assert(importString != null);

                if (importString.Length > 0 && importString[0] == '*')
                {
                    string            alias  = null;
                    string            target = null;
                    ImportTargetKind  kind   = 0;
                    VBImportScopeKind scope  = 0;

                    if (!CustomDebugInfoReader.TryParseVisualBasicImportString(importString, out alias, out target, out kind, out scope))
                    {
                        Debug.WriteLine($"Unable to parse import string '{importString}'");
                        continue;
                    }
                    else if (kind == ImportTargetKind.Defunct)
                    {
                        continue;
                    }

                    Debug.Assert(alias == null); // The default namespace is never aliased.
                    Debug.Assert(target != null);
                    Debug.Assert(kind == ImportTargetKind.DefaultNamespace);

                    // We only expect to see one of these, but it looks like ProcedureContext::LoadImportsAndDefaultNamespaceNormal
                    // implicitly uses the last one if there are multiple.
                    Debug.Assert(defaultNamespaceName == null);

                    defaultNamespaceName = target;
                }
                else
                {
                    ImportRecord      importRecord;
                    VBImportScopeKind scope = 0;

                    if (TryCreateImportRecordFromVisualBasicImportString(importString, out importRecord, out scope))
                    {
                        if (scope == VBImportScopeKind.Project)
                        {
                            projectLevelImportRecords.Add(importRecord);
                        }
                        else
                        {
                            Debug.Assert(scope == VBImportScopeKind.File || scope == VBImportScopeKind.Unspecified);
                            fileLevelImportRecords.Add(importRecord);
                        }
                    }
                    else
                    {
                        Debug.WriteLine($"Failed to parse import string {importString}");
                    }
                }
            }

            importRecordGroups = ImmutableArray.Create(
                fileLevelImportRecords.ToImmutableAndFree(),
                projectLevelImportRecords.ToImmutableAndFree());

            defaultNamespaceName = defaultNamespaceName ?? "";
        }
        /// <exception cref="InvalidOperationException">Bad data.</exception>
        private static void GetCSharpDynamicLocalInfo(
            byte[] customDebugInfo,
            IEnumerable <ISymUnmanagedScope> scopes,
            out ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap,
            out ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap)
        {
            dynamicLocalMap         = null;
            dynamicLocalConstantMap = null;

            var record = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.DynamicLocals);

            if (record.IsDefault)
            {
                return;
            }

            var localKindsByName = PooledDictionary <string, LocalKind> .GetInstance();

            GetLocalKindByName(localKindsByName, scopes);

            ImmutableDictionary <int, ImmutableArray <bool> > .Builder    localBuilder    = null;
            ImmutableDictionary <string, ImmutableArray <bool> > .Builder constantBuilder = null;

            var dynamicLocals = CustomDebugInfoReader.DecodeDynamicLocalsRecord(record);

            foreach (var dynamicLocal in dynamicLocals)
            {
                int slot  = dynamicLocal.SlotId;
                var flags = dynamicLocal.Flags;
                if (slot == 0)
                {
                    LocalKind kind;
                    var       name = dynamicLocal.LocalName;
                    localKindsByName.TryGetValue(name, out kind);
                    switch (kind)
                    {
                    case LocalKind.DuplicateName:
                        // Drop locals with ambiguous names.
                        continue;

                    case LocalKind.ConstantName:
                        constantBuilder       = constantBuilder ?? ImmutableDictionary.CreateBuilder <string, ImmutableArray <bool> >();
                        constantBuilder[name] = CreateBoolArray(flags);
                        continue;
                    }
                }
                localBuilder       = localBuilder ?? ImmutableDictionary.CreateBuilder <int, ImmutableArray <bool> >();
                localBuilder[slot] = CreateBoolArray(flags);
            }


            if (localBuilder != null)
            {
                dynamicLocalMap = localBuilder.ToImmutable();
            }

            if (constantBuilder != null)
            {
                dynamicLocalConstantMap = constantBuilder.ToImmutable();
            }

            localKindsByName.Free();
        }
        private static void ReadCSharpNativeImportsInfo(
            ISymUnmanagedReader3 reader,
            EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider,
            int methodToken,
            int methodVersion,
            out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups,
            out ImmutableArray <ExternAliasRecord> externAliasRecords)
        {
            ImmutableArray <string> externAliasStrings;

            var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings(
                methodToken,
                KeyValuePair.Create(reader, methodVersion),
                getMethodCustomDebugInfo: (token, arg) => GetCustomDebugInfoBytes(arg.Key, token, arg.Value),
                getMethodImportStrings: (token, arg) => GetImportStrings(arg.Key, token, arg.Value),
                externAliasStrings: 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 (TryCreateImportRecordFromCSharpImportString(symbolProvider, 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 ExternAliasRecord(alias, targetIdentity));
                    }
                }
            }

            importRecordGroups = importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty;
            externAliasRecords = externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty;
        }
Exemplo n.º 26
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#.
        }
Exemplo n.º 27
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));
        }