static void LoadFuncsFromDbiModule(BitAccess bits, DbiModuleInfo info, IntHashTable names, IList funcList, bool readStrings, MsfDirectory dir, Dictionary <string, int> nameIndex, PdbReader reader) { bits.Position = 0; int sig; bits.ReadInt32(out sig); if (sig != 4) { throw new PdbDebugException("Invalid signature. (sig={0})", sig); } bits.Position = 4; // Console.WriteLine("{0}:", info.moduleName); PdbFunction[] funcs = PdbFunction.LoadManagedFunctions(info.moduleName, bits, (uint)info.cbSyms, readStrings); if (funcs != null) { bits.Position = info.cbSyms + info.cbOldLines; LoadManagedLines(funcs, names, bits, dir, nameIndex, reader, (uint)(info.cbSyms + info.cbOldLines + info.cbLines)); for (int i = 0; i < funcs.Length; i++) { funcList.Add(funcs[i]); } } }
/// <summary> /// Construct the converter writer used for building the CCI data graph representing the PDB. /// </summary> public PdbWriterForCci() { Functions = new List <PdbFunction>(); TokenToSourceMapping = new Dictionary <uint, PdbTokenLine>(); _sourceDocuments = new List <PdbSource>(); _currentMethod = null; }
/// <summary> /// Finalize method info emission and add the new element to the function list. /// </summary> public override void CloseMethod() { Contract.Assert(_currentMethod != null); List <PdbLines> documentLineSets = new List <PdbLines>(); foreach (KeyValuePair <int, List <PdbLine> > tokenLinePair in _linesForCurrentMethod) { int lineCount = tokenLinePair.Value.Count; PdbLines lines = new PdbLines(_sourceDocuments[tokenLinePair.Key], (uint)lineCount); for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) { lines.lines[lineIndex] = tokenLinePair.Value[lineIndex]; } documentLineSets.Add(lines); } _currentMethod.scopes = _topLevelScopesForCurrentMethod.ToArray(); _currentMethod.lines = documentLineSets.ToArray(); _currentMethod.usedNamespaces = _usedNamespacesForCurrentMethod.ToArray(); Functions.Add(_currentMethod); _currentMethod = null; _linesForCurrentMethod = null; _scopeStackForCurrentMethod = null; _currentScope = null; _topLevelScopesForCurrentMethod = null; _usedNamespacesForCurrentMethod = null; }
public int Compare(Object x, Object y) { PdbFunction fx = (PdbFunction)x; PdbFunction fy = (PdbFunction)y; if (fx.segment < fy.segment) { return(-1); } else if (fx.segment > fy.segment) { return(1); } else if (fx.address < fy.address) { return(-1); } else if (fx.address > fy.address) { return(1); } else { return(0); } }
public int Compare(Object x, Object y) { PdbFunction fx = (PdbFunction)x; PdbFunction fy = (PdbFunction)y; return(fx.Token < fy.Token ? -1 : (fx.Token > fy.Token ? 1 : 0)); }
private static int FindFunction(PdbFunction[] funcs, ushort sec, uint off) { var match = new PdbFunction { segment = sec, address = off, }; return(Array.BinarySearch(funcs, match, PdbFunction.byAddress)); }
public int Compare(Object x, Object y) { PdbFunction fx = (PdbFunction)x; PdbFunction fy = (PdbFunction)y; return(fx.Segment < fy.Segment ? -1 : (fx.Segment > fy.Segment ? 1 : (fx.Address < fy.Address ? -1 : (fx.Address > fy.Address ? 1 : 0)))); }
void ConvertSequencePoints (PdbFunction function, SourceFile file, SourceMethodBuilder builder) { foreach (var line in function.lines.SelectMany (lines => lines.lines)) builder.MarkSequencePoint ( (int) line.offset, file.CompilationUnit.SourceFile, (int) line.lineBegin, (int) line.colBegin, line.lineBegin == 0xfeefee); }
internal static void AssertFunction(PdbFunction originalFunction, PdbFunction function) { Assert.AreEqual(originalFunction.token, function.token); AssertLines(originalFunction.lines, function.lines); AssertScopes(originalFunction.scopes, function.scopes); AssertConstants(originalFunction.constants, function.constants); Assert.AreEqual(originalFunction.slotToken, function.slotToken); AssertSlots(originalFunction.slots, function.slots); Assert.AreEqual(originalFunction.iteratorClass, function.iteratorClass); AssertIteratorScopes(originalFunction.iteratorScopes, function.iteratorScopes); }
/// <summary> /// Start populating symbol information pertaining to a given method. /// </summary> /// <param name="methodToken">MSIL metadata token representing the method</param> public override void OpenMethod(int methodToken) { // Nested method opens are not supported Contract.Assert(_currentMethod == null); _currentMethod = new PdbFunction(); _currentMethod.token = (uint)methodToken; _linesForCurrentMethod = new Dictionary <int, List <PdbLine> >(); _scopeStackForCurrentMethod = new Stack <PdbScopeBuilder>(); _currentScope = null; _topLevelScopesForCurrentMethod = new List <PdbScope>(); _usedNamespacesForCurrentMethod = new HashSet <string>(); }
void ConvertFunction (PdbFunction function) { var method = new SourceMethod { Name = function.name, Token = (int) function.token }; var file = GetSourceFile (mdb, function); var builder = mdb.OpenMethod (file.CompilationUnit, 0, method); ConvertSequencePoints (function, file, builder); ConvertVariables (function); mdb.CloseMethod (); }
void ConvertSequencePoints (PdbFunction function, SourceFile file, SourceMethodBuilder builder) { int last_line = 0; foreach (var line in function.lines.SelectMany (lines => lines.lines)) { // 0xfeefee is an MS convention, we can't pass it into mdb files, so we use the last non-hidden line bool is_hidden = line.lineBegin == 0xfeefee; builder.MarkSequencePoint ( (int) line.offset, file.CompilationUnit.SourceFile, is_hidden ? last_line : (int) line.lineBegin, (int) line.colBegin, is_hidden); if (!is_hidden) last_line = (int) line.lineBegin; } }
public int Compare(Object x, Object y) { PdbFunction fx = (PdbFunction)x; PdbFunction fy = (PdbFunction)y; if (fx.token < fy.token) { return(-1); } else if (fx.token > fy.token) { return(1); } else { return(0); } }
void ReadSequencePoints(PdbFunction function, MethodDebugInformation info) { if (function.lines == null) return; info.sequence_points = new Collection<SequencePoint> (); foreach (PdbLines lines in function.lines) ReadLines (lines, info); }
private void ReadSources(PdbFunction function) { if (function.lines == null) return; sources.AddRange(function.lines.Select(l => new Source(l))); }
private void ReadIteratorScopes(PdbFunction function) { if (function.iteratorScopes == null) return; iteratorScopes.AddRange(function.iteratorScopes.Select(s => new IteratorScope(s))); }
private static PdbFunction FindFunction(PdbFunction[] funcs, ushort sec, uint off) { match.segment = sec; match.address = off; int item = Array.BinarySearch(funcs, match, PdbFunction.byAddress); if (item >= 0) { return funcs[item]; } return null; }
private static int FindFunction(PdbFunction[] funcs, ushort sec, uint off) { var match = new PdbFunction { segment = sec, address = off, }; return Array.BinarySearch(funcs, match, PdbFunction.byAddress); }
internal static PdbFunction[] LoadManagedFunctions(/*string module,*/ BitAccess bits, uint limit, bool readStrings) { //string mod = StripNamespace(module); int begin = bits.Position; int count = 0; while (bits.Position < limit) { ushort siz; ushort rec; bits.ReadUInt16(out siz); int star = bits.Position; int stop = bits.Position + siz; bits.Position = star; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_GMANPROC: case SYM.S_LMANPROC: ManProcSym proc; bits.ReadUInt32(out proc.parent); bits.ReadUInt32(out proc.end); bits.Position = (int)proc.end; count++; break; case SYM.S_END: bits.Position = stop; break; default: //Console.WriteLine("{0,6}: {1:x2} {2}", // bits.Position, rec, (SYM)rec); bits.Position = stop; break; } } if (count == 0) { return null; } bits.Position = begin; PdbFunction[] funcs = new PdbFunction[count]; int func = 0; while (bits.Position < limit) { ushort siz; ushort rec; bits.ReadUInt16(out siz); int star = bits.Position; int stop = bits.Position + siz; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_GMANPROC: case SYM.S_LMANPROC: ManProcSym proc; //int offset = bits.Position; bits.ReadUInt32(out proc.parent); bits.ReadUInt32(out proc.end); bits.ReadUInt32(out proc.next); bits.ReadUInt32(out proc.len); bits.ReadUInt32(out proc.dbgStart); bits.ReadUInt32(out proc.dbgEnd); bits.ReadUInt32(out proc.token); bits.ReadUInt32(out proc.off); bits.ReadUInt16(out proc.seg); bits.ReadUInt8(out proc.flags); bits.ReadUInt16(out proc.retReg); if (readStrings) { bits.ReadCString(out proc.name); } else { bits.SkipCString(out proc.name); } //Console.WriteLine("token={0:X8} [{1}::{2}]", proc.token, module, proc.name); bits.Position = stop; funcs[func++] = new PdbFunction(/*module,*/ proc, bits); break; default: { //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec); bits.Position = stop; break; } } } return funcs; }
private static int FindFunction(PdbFunction[] funcs, ushort sec, uint off) { match.segment = sec; match.address = off; return Array.BinarySearch(funcs, match, PdbFunction.byAddress); }
void ConvertVariables(PdbFunction function) { foreach (var scope in function.scopes) ConvertScope (scope); }
void ReadSequencePoints(PdbFunction function, MethodSymbols symbols) { if (function.lines == null) return; foreach (PdbLines lines in function.lines) ReadLines (lines, symbols); }
void ReadSequencePoints(PdbFunction function, InstructionMapper mapper) { if (function.lines == null) return; foreach (PdbLines lines in function.lines) ReadLines (lines, mapper); }
internal Function(PdbFunction function) : this() { this.Token = (int) function.token; this.VariablesToken = (int) function.slotToken; this.IteratorTypeName = function.iteratorClass ?? string.Empty; ReadIteratorScopes(function); ReadSources(function); this.ReadScope(function.slots, function.constants, function.scopes); }
SourceFile GetSourceFile(MonoSymbolWriter mdb, PdbFunction function) { var name = (from l in function.lines where l.file != null select l.file.name).First (); SourceFile file; if (files.TryGetValue (name, out file)) return file; var entry = mdb.DefineDocument (name); var unit = mdb.DefineCompilationUnit (entry); file = new SourceFile (unit, entry); files.Add (name, file); return file; }
void ReadSequencePoints (PdbFunction function, IDictionary instructions) { if (function.lines == null) return; foreach (PdbLines lines in function.lines) ReadLines (lines, instructions); }
static void LoadManagedLines(PdbFunction[] funcs, IntHashTable names, BitAccess bits, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbReader reader, uint limit) { Array.Sort(funcs, PdbFunction.byAddressAndToken); IntHashTable checks = new IntHashTable(); // Read the files first int begin = bits.Position; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); int place = bits.Position; int endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.FILECHKSMS: while (bits.Position < endSym) { CV_FileCheckSum chk; int ni = bits.Position - place; bits.ReadUInt32(out chk.name); bits.ReadUInt8(out chk.len); bits.ReadUInt8(out chk.type); string name = (string)names[(int)chk.name]; int guidStream; Guid doctypeGuid = SymDocumentType.Text; Guid languageGuid = Guid.Empty; Guid vendorGuid = Guid.Empty; if (nameIndex.TryGetValue("/SRC/FILES/"+name.ToUpperInvariant(), out guidStream)) { var guidBits = new BitAccess(0x100); dir.streams[guidStream].Read(reader, guidBits); LoadGuidStream(guidBits, out doctypeGuid, out languageGuid, out vendorGuid); } PdbSource src = new PdbSource(/*(uint)ni,*/ name, doctypeGuid, languageGuid, vendorGuid); checks.Add(ni, src); bits.Position += chk.len; bits.Align(4); } bits.Position = endSym; break; default: bits.Position = endSym; break; } } // Read the lines next. bits.Position = begin; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); int endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.LINES: { CV_LineSection sec; bits.ReadUInt32(out sec.off); bits.ReadUInt16(out sec.sec); bits.ReadUInt16(out sec.flags); bits.ReadUInt32(out sec.cod); int funcIndex = FindFunction(funcs, sec.sec, sec.off); if (funcIndex < 0) break; var func = funcs[funcIndex]; if (func.lines == null) { while (funcIndex > 0) { var f = funcs[funcIndex-1]; if (f.lines != null || f.segment != sec.sec || f.address != sec.off) break; func = f; funcIndex--; } } else { while (funcIndex < funcs.Length-1 && func.lines != null) { var f = funcs[funcIndex+1]; if (f.segment != sec.sec || f.address != sec.off) break; func = f; funcIndex++; } } if (func.lines != null) break; // Count the line blocks. int begSym = bits.Position; int blocks = 0; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. int linsiz = (int)file.count * (8 + ((sec.flags & 1) != 0 ? 4 : 0)); bits.Position += linsiz; blocks++; } func.lines = new PdbLines[blocks]; int block = 0; bits.Position = begSym; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. PdbSource src = (PdbSource)checks[(int)file.index]; PdbLines tmp = new PdbLines(src, file.count); func.lines[block++] = tmp; PdbLine[] lines = tmp.lines; int plin = bits.Position; int pcol = bits.Position + 8 * (int)file.count; for (int i = 0; i < file.count; i++) { CV_Line line; CV_Column column = new CV_Column(); bits.Position = plin + 8 * i; bits.ReadUInt32(out line.offset); bits.ReadUInt32(out line.flags); uint lineBegin = line.flags & (uint)CV_Line_Flags.linenumStart; uint delta = (line.flags & (uint)CV_Line_Flags.deltaLineEnd) >> 24; //bool statement = ((line.flags & (uint)CV_Line_Flags.fStatement) == 0); if ((sec.flags & 1) != 0) { bits.Position = pcol + 4 * i; bits.ReadUInt16(out column.offColumnStart); bits.ReadUInt16(out column.offColumnEnd); } lines[i] = new PdbLine(line.offset, lineBegin, column.offColumnStart, lineBegin+delta, column.offColumnEnd); } } break; } } bits.Position = endSym; } }
static void LoadManagedLines(PdbFunction[] funcs, IntHashTable names, BitAccess bits, MsfDirectory dir, Dictionary <string, int> nameIndex, PdbReader reader, uint limit) { Array.Sort(funcs, PdbFunction.byAddress); IntHashTable checks = new IntHashTable(); // Read the files first int begin = bits.Position; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); int place = bits.Position; int endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.FILECHKSMS: while (bits.Position < endSym) { CV_FileCheckSum chk; int ni = bits.Position - place; bits.ReadUInt32(out chk.name); bits.ReadUInt8(out chk.len); bits.ReadUInt8(out chk.type); string name = (string)names[(int)chk.name]; int guidStream; Guid doctypeGuid = SymDocumentType.Text; Guid languageGuid = SymLanguageType.CSharp; Guid vendorGuid = SymLanguageVendor.Microsoft; if (nameIndex.TryGetValue("/src/files/" + name, out guidStream)) { var guidBits = new BitAccess(0x100); dir.streams[guidStream].Read(reader, guidBits); LoadGuidStream(guidBits, out doctypeGuid, out languageGuid, out vendorGuid); } PdbSource src = new PdbSource((uint)ni, name, doctypeGuid, languageGuid, vendorGuid); checks.Add(ni, src); bits.Position += chk.len; bits.Align(4); } bits.Position = endSym; break; default: bits.Position = endSym; break; } } // Read the lines next. bits.Position = begin; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); int endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.LINES: { CV_LineSection sec; bits.ReadUInt32(out sec.off); bits.ReadUInt16(out sec.sec); bits.ReadUInt16(out sec.flags); bits.ReadUInt32(out sec.cod); PdbFunction func = FindFunction(funcs, sec.sec, sec.off); if (func == null) { break; } // Count the line blocks. int begSym = bits.Position; int blocks = 0; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. int linsiz = (int)file.count * (8 + ((sec.flags & 1) != 0 ? 4 : 0)); bits.Position += linsiz; blocks++; } func.lines = new PdbLines[blocks]; int block = 0; bits.Position = begSym; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. PdbSource src = (PdbSource)checks[(int)file.index]; PdbLines tmp = new PdbLines(src, file.count); func.lines[block++] = tmp; PdbLine[] lines = tmp.lines; int plin = bits.Position; int pcol = bits.Position + 8 * (int)file.count; for (int i = 0; i < file.count; i++) { CV_Line line; CV_Column column = new CV_Column(); bits.Position = plin + 8 * i; bits.ReadUInt32(out line.offset); bits.ReadUInt32(out line.flags); uint lineBegin = line.flags & (uint)CV_Line_Flags.linenumStart; uint delta = (line.flags & (uint)CV_Line_Flags.deltaLineEnd) >> 24; bool statement = ((line.flags & (uint)CV_Line_Flags.fStatement) == 0); if ((sec.flags & 1) != 0) { bits.Position = pcol + 4 * i; bits.ReadUInt16(out column.offColumnStart); bits.ReadUInt16(out column.offColumnEnd); } lines[i] = new PdbLine(line.offset, lineBegin, column.offColumnStart, lineBegin + delta, column.offColumnEnd); } } break; } } bits.Position = endSym; } }
internal void RunTest(string name, out PdbFunction original, out PdbFunction rewritten) { int originalAge; Guid originalGuid; PdbFunction[] originalFunctions; using (var file = File.OpenRead(pdbFileName)) originalFunctions = PdbFile.LoadFunctions(file, true, out originalAge, out originalGuid); var method = GetMethod(name); original = originalFunctions.Single(f => f.token == method.MetadataToken.ToUInt32()); var pdb = ProgramDatabase.Read(pdbFileName); pdb.Write(pdbFileName, new CecilMetadataProvider(module)); int rewrittenAge; Guid rewrittenGuid; PdbFunction[] rewrittenFunctions; using (var file = File.OpenRead(pdbFileName)) rewrittenFunctions = PdbFile.LoadFunctions(file, true, out rewrittenAge, out rewrittenGuid); rewritten = rewrittenFunctions.Single(f => f.token == method.MetadataToken.ToUInt32()); Assert.AreEqual(originalAge, rewrittenAge); Assert.AreEqual(originalGuid, rewrittenGuid); }
internal PdbScope(uint funcOffset, BlockSym32 block, BitAccess bits, out uint typind) { //this.segment = block.seg; this.address = block.off; this.offset = block.off - funcOffset; this.length = block.len; typind = 0; int constantCount; int scopeCount; int slotCount; int namespaceCount; PdbFunction.CountScopesAndSlots(bits, block.end, out constantCount, out scopeCount, out slotCount, out namespaceCount); constants = new PdbConstant[constantCount]; scopes = new PdbScope[scopeCount]; slots = new PdbSlot[slotCount]; usedNamespaces = new string[namespaceCount]; int constant = 0; int scope = 0; int slot = 0; int usedNs = 0; while (bits.Position < block.end) { ushort siz; ushort rec; bits.ReadUInt16(out siz); int star = bits.Position; int stop = bits.Position + siz; bits.Position = star; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_BLOCK32: { BlockSym32 sub = new BlockSym32(); bits.ReadUInt32(out sub.parent); bits.ReadUInt32(out sub.end); bits.ReadUInt32(out sub.len); bits.ReadUInt32(out sub.off); bits.ReadUInt16(out sub.seg); bits.SkipCString(out sub.name); bits.Position = stop; scopes[scope++] = new PdbScope(funcOffset, sub, bits, out typind); break; } case SYM.S_MANSLOT: slots[slot++] = new PdbSlot(bits, out typind); bits.Position = stop; break; case SYM.S_UNAMESPACE: bits.ReadCString(out usedNamespaces[usedNs++]); bits.Position = stop; break; case SYM.S_END: bits.Position = stop; break; case SYM.S_MANCONSTANT: constants[constant++] = new PdbConstant(bits); bits.Position = stop; break; default: //throw new PdbException("Unknown SYM in scope {0}", (SYM)rec); bits.Position = stop; break; } } if (bits.Position != block.end) { throw new Exception("Not at S_END"); } ushort esiz; ushort erec; bits.ReadUInt16(out esiz); bits.ReadUInt16(out erec); if (erec != (ushort)SYM.S_END) { throw new Exception("Missing S_END"); } }
internal static PdbFunction[] LoadManagedFunctions(string module, BitAccess bits, uint limit, bool readStrings) { string mod = StripNamespace(module); int begin = bits.Position; int count = 0; while (bits.Position < limit) { ushort siz; ushort rec; bits.ReadUInt16(out siz); int star = bits.Position; int stop = bits.Position + siz; bits.Position = star; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_GMANPROC: case SYM.S_LMANPROC: ManProcSym proc; bits.ReadUInt32(out proc.parent); bits.ReadUInt32(out proc.end); bits.Position = (int)proc.end; count++; break; case SYM.S_END: bits.Position = stop; break; default: //Console.WriteLine("{0,6}: {1:x2} {2}", // bits.Position, rec, (SYM)rec); bits.Position = stop; break; } } if (count == 0) { return(null); } bits.Position = begin; PdbFunction[] funcs = new PdbFunction[count]; int func = 0; while (bits.Position < limit) { ushort siz; ushort rec; bits.ReadUInt16(out siz); int star = bits.Position; int stop = bits.Position + siz; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_GMANPROC: case SYM.S_LMANPROC: ManProcSym proc; int offset = bits.Position; bits.ReadUInt32(out proc.parent); bits.ReadUInt32(out proc.end); bits.ReadUInt32(out proc.next); bits.ReadUInt32(out proc.len); bits.ReadUInt32(out proc.dbgStart); bits.ReadUInt32(out proc.dbgEnd); bits.ReadUInt32(out proc.token); bits.ReadUInt32(out proc.off); bits.ReadUInt16(out proc.seg); bits.ReadUInt8(out proc.flags); bits.ReadUInt16(out proc.retReg); if (readStrings) { bits.ReadCString(out proc.name); } else { bits.SkipCString(out proc.name); } //Console.WriteLine("token={0:X8} [{1}::{2}]", proc.token, module, proc.name); bits.Position = stop; funcs[func++] = new PdbFunction(module, proc, bits); break; default: { //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec); bits.Position = stop; break; } } } return(funcs); }
static void LoadManagedLines(PdbFunction[] funcs, IntHashTable names, BitAccess bits, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbReader reader, uint limit) { Array.Sort(funcs, PdbFunction.byAddressAndToken); int begin = bits.Position; IntHashTable checks = ReadSourceFileInfo(bits, limit, names, dir, nameIndex, reader); // Read the lines next. bits.Position = begin; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); int endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.LINES: { CV_LineSection sec; bits.ReadUInt32(out sec.off); bits.ReadUInt16(out sec.sec); bits.ReadUInt16(out sec.flags); bits.ReadUInt32(out sec.cod); int funcIndex = FindFunction(funcs, sec.sec, sec.off); if (funcIndex < 0) break; var func = funcs[funcIndex]; if (func.lines == null) { while (funcIndex > 0) { var f = funcs[funcIndex-1]; if (f.lines != null || f.segment != sec.sec || f.address != sec.off) break; func = f; funcIndex--; } } else { while (funcIndex < funcs.Length-1 && func.lines != null) { var f = funcs[funcIndex+1]; if (f.segment != sec.sec || f.address != sec.off) break; func = f; funcIndex++; } } if (func.lines != null) break; // Count the line blocks. int begSym = bits.Position; int blocks = 0; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. int linsiz = (int)file.count * (8 + ((sec.flags & 1) != 0 ? 4 : 0)); bits.Position += linsiz; blocks++; } func.lines = new PdbLines[blocks]; int block = 0; bits.Position = begSym; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. PdbSource src = (PdbSource)checks[(int)file.index]; PdbLines tmp = new PdbLines(src, file.count); func.lines[block++] = tmp; PdbLine[] lines = tmp.lines; int plin = bits.Position; int pcol = bits.Position + 8 * (int)file.count; for (int i = 0; i < file.count; i++) { CV_Line line; CV_Column column = new CV_Column(); bits.Position = plin + 8 * i; bits.ReadUInt32(out line.offset); bits.ReadUInt32(out line.flags); uint lineBegin = line.flags & (uint)CV_Line_Flags.linenumStart; uint delta = (line.flags & (uint)CV_Line_Flags.deltaLineEnd) >> 24; //bool statement = ((line.flags & (uint)CV_Line_Flags.fStatement) == 0); if ((sec.flags & 1) != 0) { bits.Position = pcol + 4 * i; bits.ReadUInt16(out column.offColumnStart); bits.ReadUInt16(out column.offColumnEnd); } lines[i] = new PdbLine(line.offset, lineBegin, column.offColumnStart, lineBegin+delta, column.offColumnEnd); } } break; } } bits.Position = endSym; } }