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); }
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); }
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()); }
public MethodLineExtent(MethodId method, int version, int minLine, int maxLine) { Method = method; Version = version; MinLine = minLine; MaxLine = maxLine; }
internal bool TryGetLineDeltas(MethodId methodId, out MethodLineDeltas deltas) { if (_lazyMethodLineDeltas == null) { deltas = default(MethodLineDeltas); return(false); } return(_lazyMethodLineDeltas.TryGetValue(methodId, out deltas)); }
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]); }
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; } }
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); }
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)); } }
/// <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); }
private void RemoveLineDeltas(MethodId methodId) { _lazyMethodLineDeltas?.Remove(methodId); }
internal bool IsValidMethodId(MethodId id) => IsValidMethodRowId(id.Value);