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 is null) { while (found > 0) { var prevFunc = funcs[found - 1]; if (prevFunc is not null || prevFunc.Address != address) { break; } found--; } } else { while (found < funcs.Length - 1 && funcs[found] is not null) { var nextFunc = funcs[found + 1]; if (nextFunc.Address != address) { break; } found++; } } var func = funcs[found]; if (func.Lines is not 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); } } }
public void Read(RecursionCounter counter, ref DataReader reader, uint scopeEnd) { if (!counter.Increment()) { throw new PdbException("Scopes too deep"); } while (reader.Position < scopeEnd) { var size = reader.ReadUInt16(); var begin = reader.Position; var end = begin + size; var type = (SymbolType)reader.ReadUInt16(); DbiScope child = null; uint? childEnd = null; string name; switch (type) { case SymbolType.S_BLOCK32: { reader.Position += 4; childEnd = reader.ReadUInt32(); var len = reader.ReadUInt32(); var addr = PdbAddress.ReadAddress(ref reader); name = PdbReader.ReadCString(ref reader); child = new DbiScope(method, this, name, addr.Offset, len); break; } case SymbolType.S_UNAMESPACE: namespacesList.Add(new DbiNamespace(PdbReader.ReadCString(ref reader))); break; case SymbolType.S_MANSLOT: { var variable = new DbiVariable(); if (variable.Read(ref reader)) { localsList.Add(variable); } break; } case SymbolType.S_OEM: if ((ulong)reader.Position + 20 > end) { break; } if (!ReadAndCompareBytes(ref reader, end, dotNetOemGuid)) { Debug.Fail("Unknown OEM record GUID, not .NET GUID"); break; } reader.Position += 4; // typeIndex or 0 name = ReadUnicodeString(ref reader, end); Debug.Assert(name is not null); if (name is null) { break; } var data = reader.ReadBytes((int)(end - reader.Position)); if (oemInfos is null) { oemInfos = new List <OemInfo>(1); } oemInfos.Add(new OemInfo(name, data)); break; case SymbolType.S_MANCONSTANT: uint signatureToken = reader.ReadUInt32(); object value; if (!NumericReader.TryReadNumeric(ref reader, end, out value)) { break; } name = PdbReader.ReadCString(ref reader); if (constants is null) { constants = new List <ConstantInfo>(); } constants.Add(new ConstantInfo(name, signatureToken, value)); break; case SymbolType.S_END: break; default: break; } reader.Position = end; if (child is not null) { child.Read(counter, ref reader, childEnd.Value); childrenList.Add(child); child = null; } } counter.Decrement(); if (reader.Position != scopeEnd) { Debugger.Break(); } }