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