Beispiel #1
0
        /// <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;
 }
Beispiel #3
0
        /// <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);
                        }
                    }
                }
            }
        }
Beispiel #6
0
 private static bool CanReuseReader(MetadataReader?reader, MetadataReaderOptions options, MetadataStringDecoder?utf8DecoderOpt)
 {
     return(reader != null && reader.Options == options && ReferenceEquals(reader.UTF8Decoder, utf8DecoderOpt ?? MetadataStringDecoder.DefaultUTF8));
 }
Beispiel #7
0
 public GenericContext(TypeDefinitionHandle declaringType, MetadataReader metadata)
 {
     this.metadata      = metadata;
     this.declaringType = declaringType;
 }
Beispiel #8
0
 public GenericContext(TypeDefinitionHandle declaringType, PEFile module)
 {
     this.metadata      = module.Metadata;
     this.declaringType = declaringType;
 }
Beispiel #9
0
 public GenericContext(MethodDefinitionHandle method, MetadataReader metadata)
 {
     this.metadata      = metadata;
     this.method        = method;
     this.declaringType = metadata.GetMethodDefinition(method).GetDeclaringType();
 }
Beispiel #10
0
 public GenericContext(MethodDefinitionHandle method, PEFile module)
 {
     this.metadata      = module.Metadata;
     this.method        = method;
     this.declaringType = module.Metadata.GetMethodDefinition(method).GetDeclaringType();
 }