Beispiel #1
0
        internal bool TryGetMethodHandle(MethodId id, out MethodDebugInformationHandle handle)
        {
            if (id.IsDefault)
            {
                handle = default(MethodDebugInformationHandle);
                return(false);
            }

            if (_methodHandleToIdMapOpt.IsDefault)
            {
                if (id.Value > _metadataReader.MethodDebugInformation.Count)
                {
                    handle = default(MethodDebugInformationHandle);
                    return(false);
                }

                handle = MetadataTokens.MethodDebugInformationHandle(id.Value);
                return(true);
            }

            int index = _methodHandleToIdMapOpt.BinarySearch(id);

            if (index >= 0)
            {
                handle = MetadataTokens.MethodDebugInformationHandle(index + 1);
                return(true);
            }

            handle = default(MethodDebugInformationHandle);
            return(false);
        }
Beispiel #2
0
        private bool TryGetDebuggableMethod(int methodToken, out PortablePdbReader pdbReader, out MethodDebugInformationHandle handle)
        {
            if (!MetadataUtilities.IsMethodToken(methodToken))
            {
                pdbReader = null;
                handle    = default(MethodDebugInformationHandle);
                return(false);
            }

            var methodId = MethodId.FromToken(methodToken);

            if (Version == 1)
            {
                pdbReader = GetReader(version: 1);
                if (pdbReader.TryGetMethodHandle(methodId, out handle))
                {
                    return(pdbReader.HasDebugInfo(handle));
                }
            }
            else
            {
                var methodMap = GetMethodMap();
                if (methodMap.IsValidMethodRowId(methodId.Value))
                {
                    var info = methodMap.GetInfo(methodId);
                    pdbReader = GetReader(info.Version);
                    handle    = info.Handle;
                    return(pdbReader.HasDebugInfo(handle));
                }
            }

            pdbReader = null;
            handle    = default(MethodDebugInformationHandle);
            return(false);
        }
Beispiel #3
0
        private static ImmutableArray <MethodId> CreateHandleToIdMap(MetadataReader reader, List <MethodInfo> infos, int version)
        {
            var handleToIdMapBuilder = ImmutableArray.CreateBuilder <MethodId>(reader.MethodDebugInformation.Count);

            // Consider: Ideally MetadataReader would expose GetEditAndContinueMapEntries(TableIndex) and do binary search.
            // However, the only records in the table for Portable PDBs are currently MethodDebugInformation handles.
            foreach (EntityHandle encMapHandle in reader.GetEditAndContinueMapEntries())
            {
                if (encMapHandle.Kind == HandleKind.MethodDebugInformation)
                {
                    var id = new MethodId(MetadataTokens.GetRowNumber(encMapHandle));
                    handleToIdMapBuilder.Add(id);
                    var methodHandle = MetadataTokens.MethodDebugInformationHandle(handleToIdMapBuilder.Count);

                    int index = id.Value - 1;
                    while (infos.Count <= index)
                    {
                        infos.Add(default(MethodInfo));
                    }

                    // an existing info is overwritten with new version:
                    infos[index] = new MethodInfo(methodHandle, version);
                }
            }

            return(handleToIdMapBuilder.MoveToImmutable());
        }
Beispiel #4
0
 public MethodLineExtent(MethodId method, int version, int minLine, int maxLine)
 {
     Method  = method;
     Version = version;
     MinLine = minLine;
     MaxLine = maxLine;
 }
Beispiel #5
0
        internal bool TryGetLineDeltas(MethodId methodId, out MethodLineDeltas deltas)
        {
            if (_lazyMethodLineDeltas == null)
            {
                deltas = default(MethodLineDeltas);
                return(false);
            }

            return(_lazyMethodLineDeltas.TryGetValue(methodId, out deltas));
        }
Beispiel #6
0
        internal MethodInfo GetInfo(MethodId methodId)
        {
            int rowId = methodId.Value;

            if (_lazyInfos == null)
            {
                // Infos are initialized by an EnC update. If not initialized the symreader hasn't been updated.
                Debug.Assert(rowId <= _baselineMethodCount);
                return(new MethodInfo(MetadataTokens.MethodDebugInformationHandle(rowId), version: 1));
            }

            return(_lazyInfos[rowId - 1]);
        }
Beispiel #7
0
        private void UpdateLineDeltas(MethodId methodId, MethodLineDeltas deltas)
        {
            if (_lazyMethodLineDeltas == null)
            {
                _lazyMethodLineDeltas = new Dictionary <MethodId, MethodLineDeltas>();
            }

            if (_lazyMethodLineDeltas.TryGetValue(methodId, out var existing))
            {
                _lazyMethodLineDeltas[methodId] = existing.Merge(deltas);
            }
            else
            {
                _lazyMethodLineDeltas[methodId] = deltas;
            }
        }
Beispiel #8
0
        private int UpdateSymbolStoreImpl(
            IStream stream,
            string fileName,
            SymUnmanagedLineDelta[] lineDeltas,
            int lineDeltaCount)
        {
            Debug.Assert(stream != null ^ fileName != null);
            Debug.Assert(lineDeltas != null);
            Debug.Assert(lineDeltaCount >= 0);

            lineDeltaCount = Math.Min(lineDeltas.Length, lineDeltaCount);
            var methodMap     = GetMethodMap();
            var documentMap   = GetDocumentMap();
            var methodExtents = GetMethodExtents();

            var lineDeltasByDocument = GroupLineDeltasByDocument(lineDeltas, lineDeltaCount);

            int newVersion = Version + 1;

            var provider = (stream != null) ? CreateProviderFromStream(stream) : CreateProviderFromFile(fileName);

            var pdbReader = new PortablePdbReader(provider, newVersion, documentMap.DocumentCount);

            documentMap.Update(this, pdbReader.MetadataReader, newVersion, out var documentHandleToIdMap);
            methodMap.Update(this, pdbReader.MetadataReader, newVersion, out var methodHandleToIdMap);
            pdbReader.InitializeHandleToIdMaps(documentHandleToIdMap, methodHandleToIdMap);
            methodExtents.Update(pdbReader, lineDeltasByDocument);

            // remove line deltas of methods updated in this generation:
            for (int i = 0; i < methodHandleToIdMap.Length; i++)
            {
                RemoveLineDeltas(methodHandleToIdMap[i]);
            }

            // apply line deltas of methods moved around in this generation:
            for (int i = 0; i < lineDeltaCount; i++)
            {
                UpdateLineDeltas(MethodId.FromToken(lineDeltas[i].MethodToken), new MethodLineDeltas(lineDeltas[i].Delta, ImmutableArray <int> .Empty));
            }

            _pdbReaders.Add(pdbReader);
            pdbReader.SymReader = this;

            return(HResult.S_OK);
        }
Beispiel #9
0
        private Dictionary <DocumentId, List <(MethodId, int)> > GroupLineDeltasByDocument(SymUnmanagedLineDelta[] lineDeltas, int lineDeltaCount)
        {
            var methodMap        = GetMethodMap();
            var deltasByDocument = new Dictionary <DocumentId, List <(MethodId, int)> >();

            for (int i = 0; i < lineDeltaCount; i++)
            {
                int methodToken = lineDeltas[i].MethodToken;
                if (!TryGetDebuggableMethod(methodToken, out var pdbReader, out var handle))
                {
                    continue;
                }

                var methodId = MethodId.FromToken(methodToken);
                var(single, multiple) = MethodExtents.GetMethodBodyDocuments(pdbReader.MetadataReader, handle);
                if (!single.IsNil)
                {
                    AddExtentForDocument(single);
                }
                else
                {
                    // method has debug info:
                    Debug.Assert(multiple != null);

                    foreach (var documentHandle in multiple)
                    {
                        AddExtentForDocument(documentHandle);
                    }
                }

                void AddExtentForDocument(DocumentHandle documentHandle)
                {
                    var documentId = pdbReader.GetDocumentId(documentHandle);

                    if (!deltasByDocument.TryGetValue(documentId, out var extents))
                    {
                        deltasByDocument.Add(documentId, extents = new List <(MethodId, int)>());
                    }

                    extents.Add((methodId, lineDeltas[i].Delta));
                }
            }
Beispiel #10
0
        /// <summary>
        /// Get a particular version of a method with specified token.
        /// </summary>
        public int GetMethodByVersion(
            int methodToken,
            int version,
            [MarshalAs(UnmanagedType.Interface)] out ISymUnmanagedMethod method)
        {
            if (!IsValidVersion(version))
            {
                method = null;
                return(HResult.E_INVALIDARG);
            }

            if (!MetadataUtilities.IsMethodToken(methodToken))
            {
                method = null;
                return(HResult.E_INVALIDARG);
            }

            var pdbReader = GetReader(version);

            if (!pdbReader.TryGetMethodHandle(MethodId.FromToken(methodToken), out var methodDebugHandle))
            {
                method = null;
                return(HResult.E_FAIL);
            }

            var debugInfo = pdbReader.MetadataReader.GetMethodDebugInformation(methodDebugHandle);

            if (debugInfo.SequencePointsBlob.IsNil)
            {
                // no debug info for the method
                method = null;
                return(HResult.E_FAIL);
            }

            method = new SymMethod(pdbReader, methodDebugHandle);
            return(HResult.S_OK);
        }
Beispiel #11
0
 private void RemoveLineDeltas(MethodId methodId)
 {
     _lazyMethodLineDeltas?.Remove(methodId);
 }
Beispiel #12
0
 internal bool IsValidMethodId(MethodId id) => IsValidMethodRowId(id.Value);