Example #1
0
        public void Read(PageAwarePdbReader reader, byte[] buffer)
        {
            if (buffer.Length < this.contentSize)
            {
                ThrowInsufficientBufferSizeException();
            }

            this.Read(reader, 0, buffer, 0, contentSize);
        }
Example #2
0
        private void Read(PageAwarePdbReader reader, int position, byte[] bytes, int offset, int data)
        {
            if (position + data > this.contentSize)
            {
                ThrowDataStreamEndOfFileException(position, data);
            }

            if (position == this.contentSize)
            {
                return;
            }

            int left = data;
            int page = position / reader.PageSize;
            int rema = position % reader.PageSize;

            // First get remained of first page.
            if (rema != 0)
            {
                int todo = reader.PageSize - rema;
                if (todo > left)
                {
                    todo = left;
                }

                reader.Seek(this.pages[page], rema);
                reader.Read(bytes, offset, todo);

                offset += todo;
                left   -= todo;
                page++;
            }

            // Now get the remaining pages.
            while (left > 0)
            {
                int todo = reader.PageSize;
                if (todo > left)
                {
                    todo = left;
                }

                reader.Seek(this.pages[page], 0);
                reader.Read(bytes, offset, todo);

                offset += todo;
                left   -= todo;
                page++;
            }
        }
Example #3
0
        // @@BPerfIgnoreAllocation@@ -- directoryRoot (not poolable due to MemoryMarshal), pageAwarePdbReader (elidable per escape analysis), msf (elidable per future escape analysis), nameIndexStreamData (poolable), namesStreamData (poolable), dbiStreamData (poolable)
        private static bool GetSourceLineInfo(Stream fs, uint token, uint iloffset, out int age, out Guid guid, out string sourceFile, out int sourceLine, out int sourceColumn)
        {
            if (ReadPdbHeader(fs, out var pageSize, out var freePageMap, out var pagesUsed, out var directorySize, out var zero))
            {
                int directoryPages = ((directorySize + pageSize - 1) / pageSize * 4 + pageSize - 1) / pageSize;

                var directoryRoot = new int[directoryPages];
                fs.Read(MemoryMarshal.Cast <int, byte>(directoryRoot));

                var pageAwarePdbReader = new PageAwarePdbReader(fs, pageSize);
                var msf = new MsfDirectory(pageAwarePdbReader, pageSize, directorySize, directoryRoot);

                var nameIndexStream     = msf.Streams[1];
                var nameIndexStreamData = new byte[nameIndexStream.Length];
                nameIndexStream.Read(pageAwarePdbReader, nameIndexStreamData);

                var nameIndex = LoadNameIndex(nameIndexStreamData, out age, out guid);
                if (nameIndex.TryGetValue("/NAMES", out var namesStreamIndex))
                {
                    var namesStream     = msf.Streams[namesStreamIndex];
                    var namesStreamData = new byte[namesStream.Length];
                    namesStream.Read(pageAwarePdbReader, namesStreamData);

                    var names = LoadNameStream(namesStreamData);

                    var dbiStream     = msf.Streams[3];
                    var dbiStreamData = new byte[dbiStream.Length];
                    dbiStream.Read(pageAwarePdbReader, dbiStreamData);

                    var modules = LoadModules(dbiStreamData, out DbiDbgHdr header);
                    GetSourceLineInfoInner(modules, msf, pageAwarePdbReader, names, token, iloffset, out sourceFile, out sourceLine, out sourceColumn);

                    return(true);
                }
            }

            age          = 0;
            guid         = Guid.Empty;
            sourceFile   = null;
            sourceLine   = 0;
            sourceColumn = 0;

            return(false);
        }
        // @@BPerfIgnoreAllocation@@ -- pages (not poolable due to MemoryMarshal), stream (meh), List<DataStream> lifetime extends method, dsPages lifetime on DataStream, Lifetime outside of scope for DataStream objects
        public MsfDirectory(PageAwarePdbReader reader, int pageSize, int directorySize, int[] directoryRoot)
        {
            int numPages = reader.PagesFromSize(directorySize);

            var pages = new int[numPages];
            var buf   = MemoryMarshal.Cast <int, byte>(pages);

            int offset       = 0;
            int pagesPerPage = pageSize / 4;
            int pagesToGo    = numPages;

            for (int i = 0; i < directoryRoot.Length; ++i)
            {
                int pagesInThisPage = pagesToGo <= pagesPerPage ? pagesToGo : pagesPerPage;
                reader.Seek(directoryRoot[i], 0);
                reader.Stream.Read(buf.Slice(offset, pagesInThisPage * 4));
                pagesToGo -= pagesInThisPage;
            }

            byte[] buffer = default;
            int[]  sizes  = default;
            try
            {
                buffer = ArrayPool <byte> .Shared.Rent(directorySize);

                var stream = new DataStream(directorySize, pages);
                stream.Read(reader, buffer);

                offset = 0;
                int count = InterpretInt32(buffer, ref offset);

                try
                {
                    // 4..n
                    sizes = ArrayPool <int> .Shared.Rent(count);

                    for (int i = 0; i < count; ++i)
                    {
                        sizes[i] = InterpretInt32(buffer, ref offset);
                    }

                    streams = new List <DataStream>(count);

                    for (int i = 0; i < count; ++i)
                    {
                        if (sizes[i] <= 0)
                        {
                            streams.Add(new DataStream());
                        }
                        else
                        {
                            int dsPagesCount = reader.PagesFromSize(sizes[i]);
                            if (dsPagesCount > 0)
                            {
                                var dsPages = new int[dsPagesCount];
                                for (int j = 0; j < dsPagesCount; ++j)
                                {
                                    dsPages[j] = InterpretInt32(buffer, ref offset);
                                }

                                streams.Add(new DataStream(sizes[i], dsPages));
                            }
                            else
                            {
                                streams.Add(new DataStream(sizes[i], null));
                            }
                        }
                    }
                }
                finally
                {
                    if (sizes != null)
                    {
                        ArrayPool <int> .Shared.Return(sizes);
                    }
                }
            }
            finally
            {
                if (buffer != null)
                {
                    ArrayPool <byte> .Shared.Return(buffer);
                }
            }
        }
Example #5
0
        private static void GetSourceLineInfoInner(List <DbiModuleInfo> modules, MsfDirectory dir, PageAwarePdbReader reader, Dictionary <int, string> names, uint token, uint iloffset, out string sourceFile, out int sourceLine, out int sourceColumn)
        {
            sourceFile   = null;
            sourceLine   = 0;
            sourceColumn = 0;

            for (int m = 0; m < modules.Count; ++m)
            {
                var module = modules[m];
                if (module.stream > 0)
                {
                    byte[] bits = default;
                    try
                    {
                        var stream = dir.Streams[module.stream];
                        bits = ArrayPool <byte> .Shared.Rent(stream.Length);

                        stream.Read(reader, bits);

                        if (TryGetManProcSym(bits, ref module, token, out ManProcSym sym))
                        {
                            GetLineNumberInformation(bits, ref module, sym.off + iloffset, names, out sourceFile, out sourceLine, out sourceColumn);
                        }
                    }
                    finally
                    {
                        if (bits != null)
                        {
                            ArrayPool <byte> .Shared.Return(bits);
                        }
                    }
                }
            }
        }