void ReadLines(DbiFunction[] funcs, Dictionary <uint, DbiDocument> documents, ref DataReader reader, uint end) { var address = PdbAddress.ReadAddress(ref reader); int first = 0; int last = funcs.Length - 1; int found = -1; while (first <= last) { var index = first + ((last - first) >> 1); var addr = funcs[index].Address; if (addr < address) { first = index + 1; } else if (addr > address) { last = index - 1; } else { found = index; break; } } if (found == -1) { return; } var flags = reader.ReadUInt16(); reader.Position += 4; if (funcs[found].Lines == null) { while (found > 0) { var prevFunc = funcs[found - 1]; if (prevFunc != null || prevFunc.Address != address) { break; } found--; } } else { while (found < funcs.Length - 1 && funcs[found] != null) { var nextFunc = funcs[found + 1]; if (nextFunc.Address != address) { break; } found++; } } var func = funcs[found]; if (func.Lines != null) { return; } func.Lines = new List <SymbolSequencePoint>(); while (reader.Position < end) { var document = documents[reader.ReadUInt32()]; var count = reader.ReadUInt32(); reader.Position += 4; const int LINE_ENTRY_SIZE = 8; const int COL_ENTRY_SIZE = 4; var lineTablePos = reader.Position; var colTablePos = reader.Position + count * LINE_ENTRY_SIZE; for (uint i = 0; i < count; i++) { reader.Position = lineTablePos + i * LINE_ENTRY_SIZE; var line = new SymbolSequencePoint { Document = document }; line.Offset = reader.ReadInt32(); var lineFlags = reader.ReadUInt32(); line.Line = (int)(lineFlags & 0x00ffffff); line.EndLine = line.Line + (int)((lineFlags >> 24) & 0x7F); if ((flags & 1) != 0) { reader.Position = colTablePos + i * COL_ENTRY_SIZE; line.Column = reader.ReadUInt16(); line.EndColumn = reader.ReadUInt16(); } func.Lines.Add(line); } } }
SymbolSequencePoint[] ReadSequencePoints(uint methodRid) { if (!pdbMetadata.TablesStream.MethodDebugInformationTable.IsValidRID(methodRid)) { return(null); } if (!pdbMetadata.TablesStream.TryReadMethodDebugInformationRow(methodRid, out var row)) { return(null); } if (row.SequencePoints == 0) { return(null); } uint documentRid = row.Document; if (!pdbMetadata.BlobStream.TryCreateReader(row.SequencePoints, out var seqPointsReader)) { return(null); } var seqPointsBuilder = ListCache <SymbolSequencePoint> .AllocList(); uint localSig = seqPointsReader.ReadCompressedUInt32(); if (documentRid == 0) { documentRid = seqPointsReader.ReadCompressedUInt32(); } TryGetSymbolDocument(documentRid, out var document); uint ilOffset = uint.MaxValue; int line = -1, column = 0; bool canReadDocumentRecord = false; while (seqPointsReader.Position < seqPointsReader.Length) { uint data = seqPointsReader.ReadCompressedUInt32(); if (data == 0 && canReadDocumentRecord) { // document-record documentRid = seqPointsReader.ReadCompressedUInt32(); TryGetSymbolDocument(documentRid, out document); } else { // SequencePointRecord Debug.Assert(document is not null); if (document is null) { return(null); } var symSeqPoint = new SymbolSequencePoint { Document = document, }; if (ilOffset == uint.MaxValue) { ilOffset = data; } else { Debug.Assert(data != 0); if (data == 0) { return(null); } ilOffset += data; } symSeqPoint.Offset = (int)ilOffset; uint dlines = seqPointsReader.ReadCompressedUInt32(); int dcolumns = dlines == 0 ? (int)seqPointsReader.ReadCompressedUInt32() : seqPointsReader.ReadCompressedInt32(); if (dlines == 0 && dcolumns == 0) { // hidden-sequence-point-record symSeqPoint.Line = SequencePointConstants.HIDDEN_LINE; symSeqPoint.EndLine = SequencePointConstants.HIDDEN_LINE; symSeqPoint.Column = SequencePointConstants.HIDDEN_COLUMN; symSeqPoint.EndColumn = SequencePointConstants.HIDDEN_COLUMN; } else { // sequence-point-record if (line < 0) { line = (int)seqPointsReader.ReadCompressedUInt32(); column = (int)seqPointsReader.ReadCompressedUInt32(); } else { line += seqPointsReader.ReadCompressedInt32(); column += seqPointsReader.ReadCompressedInt32(); } symSeqPoint.Line = line; symSeqPoint.EndLine = line + (int)dlines; symSeqPoint.Column = column; symSeqPoint.EndColumn = column + dcolumns; } seqPointsBuilder.Add(symSeqPoint); } canReadDocumentRecord = true; } Debug.Assert(seqPointsReader.Position == seqPointsReader.Length); return(ListCache <SymbolSequencePoint> .FreeAndToArray(ref seqPointsBuilder)); }