/// <summary> /// Gets a <see cref="MetadataReader"/> from a <see cref="MetadataReaderProvider"/>. /// </summary> /// <remarks> /// The caller must keep the <see cref="MetadataReaderProvider"/> undisposed throughout the lifetime of the metadata reader. /// /// If this method is called multiple times each call with arguments equal to the arguments passed to the previous successful call /// returns the same instance of <see cref="MetadataReader"/> as the previous call. /// </remarks> /// <exception cref="ArgumentException">The encoding of <paramref name="utf8Decoder"/> is not <see cref="UTF8Encoding"/>.</exception> /// <exception cref="PlatformNotSupportedException">The current platform is big-endian.</exception> /// <exception cref="IOException">IO error while reading from the underlying stream.</exception> /// <exception cref="ObjectDisposedException">Provider has been disposed.</exception> public unsafe MetadataReader GetMetadataReader(MetadataReaderOptions options = MetadataReaderOptions.Default, MetadataStringDecoder?utf8Decoder = null) { var cachedReader = _lazyMetadataReader; if (CanReuseReader(cachedReader, options, utf8Decoder)) { return(cachedReader !); } // If multiple threads attempt to open a metadata reader with the same options and decoder // it's cheaper to wait for the other thread to finish initializing the reader than to open // two readers and discard one. // Note that it's rare to reader the same metadata using different options. lock (_metadataReaderGuard) { cachedReader = _lazyMetadataReader; if (CanReuseReader(cachedReader, options, utf8Decoder)) { return(cachedReader !); } AbstractMemoryBlock metadata = GetMetadataBlock(); var newReader = new MetadataReader(metadata.Pointer, metadata.Size, options, utf8Decoder, memoryOwner: this); _lazyMetadataReader = newReader; return(newReader); } }
public PEInfo(RuntimeAssemblyName name, MetadataReader?reader, PEReader?pe, MemoryMappedViewAccessor?memoryMappedView = null) { Name = name; Reader = reader; PE = pe; MemoryMappedView = memoryMappedView; }
/// <summary> /// Disposes all memory allocated by the reader. /// </summary> /// <remarks> /// <see cref="Dispose"/> can be called multiple times (but not in parallel). /// It is not safe to call <see cref="Dispose"/> in parallel with any other operation on the <see cref="MetadataReaderProvider"/> /// or reading from the underlying memory. /// </remarks> public void Dispose() { _blockProviderOpt?.Dispose(); _blockProviderOpt = null; _lazyMetadataBlock?.Dispose(); _lazyMetadataBlock = null; _lazyMetadataReader = null; }
private MetadataAggregator( MetadataReader?baseReader, IReadOnlyList <int>?baseTableRowCounts, IReadOnlyList <int>?baseHeapSizes, IReadOnlyList <MetadataReader>?deltaReaders) { if (baseTableRowCounts == null) { if (baseReader == null) { Throw.ArgumentNull(nameof(baseReader)); } if (baseReader.GetTableRowCount(TableIndex.EncMap) != 0) { throw new ArgumentException(SR.BaseReaderMustBeFullMetadataReader, nameof(baseReader)); } CalculateBaseCounts(baseReader, out baseTableRowCounts, out baseHeapSizes); Debug.Assert(baseTableRowCounts != null); } else { if (baseTableRowCounts.Count != MetadataTokens.TableCount) { throw new ArgumentException(SR.Format(SR.ExpectedListOfSize, MetadataTokens.TableCount), nameof(baseTableRowCounts)); } if (baseHeapSizes == null) { Throw.ArgumentNull(nameof(baseHeapSizes)); } if (baseHeapSizes.Count != MetadataTokens.HeapCount) { throw new ArgumentException(SR.Format(SR.ExpectedListOfSize, MetadataTokens.HeapCount), nameof(baseTableRowCounts)); } } if (deltaReaders == null || deltaReaders.Count == 0) { throw new ArgumentException(SR.ExpectedNonEmptyList, nameof(deltaReaders)); } for (int i = 0; i < deltaReaders.Count; i++) { if (deltaReaders[i].GetTableRowCount(TableIndex.EncMap) == 0 || !deltaReaders[i].IsMinimalDelta) { throw new ArgumentException(SR.ReadersMustBeDeltaReaders, nameof(deltaReaders)); } } _heapSizes = CalculateHeapSizes(baseHeapSizes, deltaReaders); _rowCounts = CalculateRowCounts(baseTableRowCounts, deltaReaders); }
/// <summary> /// Returns the source file and line number information for the method. /// </summary> /// <param name="assembly">managed assembly</param> /// <param name="assemblyPath">file path of the assembly or null</param> /// <param name="loadedPeAddress">loaded PE image address or zero</param> /// <param name="loadedPeSize">loaded PE image size</param> /// <param name="inMemoryPdbAddress">in memory PDB address or zero</param> /// <param name="inMemoryPdbSize">in memory PDB size</param> /// <param name="methodToken">method token</param> /// <param name="ilOffset">il offset of the stack frame</param> /// <param name="sourceFile">source file return</param> /// <param name="sourceLine">line number return</param> /// <param name="sourceColumn">column return</param> internal void GetSourceLineInfo(Assembly assembly, string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset, out string?sourceFile, out int sourceLine, out int sourceColumn) { sourceFile = null; sourceLine = 0; sourceColumn = 0; MetadataReader?reader = TryGetReader(assembly, assemblyPath, loadedPeAddress, loadedPeSize, inMemoryPdbAddress, inMemoryPdbSize); if (reader != null) { Handle handle = MetadataTokens.Handle(methodToken); if (handle.Kind == HandleKind.MethodDefinition) { MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle(); MethodDebugInformation methodInfo = reader.GetMethodDebugInformation(methodDebugHandle); if (!methodInfo.SequencePointsBlob.IsNil) { SequencePointCollection sequencePoints = methodInfo.GetSequencePoints(); SequencePoint?bestPointSoFar = null; foreach (SequencePoint point in sequencePoints) { if (point.Offset > ilOffset) { break; } if (point.StartLine != SequencePoint.HiddenLine) { bestPointSoFar = point; } } if (bestPointSoFar.HasValue) { sourceLine = bestPointSoFar.Value.StartLine; sourceColumn = bestPointSoFar.Value.StartColumn; sourceFile = reader.GetString(reader.GetDocument(bestPointSoFar.Value.Document).Name); } } } } }
private static bool CanReuseReader(MetadataReader?reader, MetadataReaderOptions options, MetadataStringDecoder?utf8DecoderOpt) { return(reader != null && reader.Options == options && ReferenceEquals(reader.UTF8Decoder, utf8DecoderOpt ?? MetadataStringDecoder.DefaultUTF8)); }
public GenericContext(TypeDefinitionHandle declaringType, MetadataReader metadata) { this.metadata = metadata; this.declaringType = declaringType; }
public GenericContext(TypeDefinitionHandle declaringType, PEFile module) { this.metadata = module.Metadata; this.declaringType = declaringType; }
public GenericContext(MethodDefinitionHandle method, MetadataReader metadata) { this.metadata = metadata; this.method = method; this.declaringType = metadata.GetMethodDefinition(method).GetDeclaringType(); }
public GenericContext(MethodDefinitionHandle method, PEFile module) { this.metadata = module.Metadata; this.method = method; this.declaringType = module.Metadata.GetMethodDefinition(method).GetDeclaringType(); }