private void ReadCustomMetadata(BitAccess bits) { int savedPosition = bits.Position; byte version; bits.ReadUInt8(out version); if (version != 4) { throw new PdbDebugException("Unknown custom metadata item version: {0}", version); } byte kind; bits.ReadUInt8(out kind); bits.Align(4); uint numberOfBytesInItem; bits.ReadUInt32(out numberOfBytesInItem); switch (kind) { case 0: this.ReadUsingInfo(bits); break; case 1: break; // this.ReadForwardInfo(bits); break; case 2: break; // this.ReadForwardedToModuleInfo(bits); break; case 3: this.ReadIteratorLocals(bits); break; case 4: this.ReadForwardIterator(bits); break; default: throw new PdbDebugException("Unknown custom metadata item kind: {0}", kind); } bits.Position = savedPosition + (int)numberOfBytesInItem; }
internal DbiModuleInfo(BitAccess bits, bool readStrings) { bits.ReadInt32(out opened); new DbiSecCon(bits); bits.ReadUInt16(out flags); bits.ReadInt16(out stream); bits.ReadInt32(out cbSyms); bits.ReadInt32(out cbOldLines); bits.ReadInt32(out cbLines); bits.ReadInt16(out files); bits.ReadInt16(out pad1); bits.ReadUInt32(out offsets); bits.ReadInt32(out niSource); bits.ReadInt32(out niCompiler); if (readStrings) { bits.ReadCString(out moduleName); bits.ReadCString(out objectName); } else { bits.SkipCString(out moduleName); bits.SkipCString(out objectName); } bits.Align(4); //if (opened != 0 || pad1 != 0) { // throw new PdbException("Invalid DBI module. "+ // "(opened={0}, pad={1})", opened, pad1); //} }
internal DbiModuleInfo(BitAccess bits, bool readStrings) { bits.ReadInt32(out opened); new DbiSecCon(bits); bits.ReadUInt16(out flags); bits.ReadInt16(out stream); bits.ReadInt32(out cbSyms); bits.ReadInt32(out cbOldLines); bits.ReadInt32(out cbLines); bits.ReadInt16(out files); bits.ReadInt16(out pad1); bits.ReadUInt32(out offsets); bits.ReadInt32(out niSource); bits.ReadInt32(out niCompiler); if (readStrings) { bits.ReadCString(out moduleName); bits.ReadCString(out objectName); } else { bits.SkipCString(out moduleName); bits.SkipCString(out objectName); } bits.Align(4); }
private static void LoadManagedLines( PdbFunction[] funcs, Dictionary <int, string> names, BitAccess bits, MsfDirectory dir, Dictionary <string, int> nameIndex, PdbStreamHelper reader, uint limit, Dictionary <string, PdbSource> sources) { Array.Sort(funcs, PdbFunction.byAddressAndToken); Dictionary <int, PdbSource> checks = new Dictionary <int, PdbSource>(); // 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 = names[(int)chk.name]; PdbSource src; if (!sources.TryGetValue(name.ToUpperInvariant(), out src)) { int guidStream; Guid doctypeGuid = Guid.Empty; Guid languageGuid = Guid.Empty; Guid vendorGuid = Guid.Empty; Guid algorithmId = Guid.Empty; byte[] checksum = null; byte[] source = null; if (nameIndex.TryGetValue("/SRC/FILES/" + name.ToUpperInvariant(), out guidStream)) { BitAccess guidBits = new BitAccess(0x100); dir._streams[guidStream].Read(reader, guidBits); LoadGuidStream(guidBits, out doctypeGuid, out languageGuid, out vendorGuid, out algorithmId, out checksum, out source); } src = new PdbSource(/*(uint)ni,*/ name, doctypeGuid, languageGuid, vendorGuid, algorithmId, checksum, source); sources.Add(name.ToUpperInvariant(), src); } 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; } PdbFunction func = funcs[funcIndex]; if (func.SequencePoints == null) { while (funcIndex > 0) { PdbFunction f = funcs[funcIndex - 1]; if (f.SequencePoints != null || f.Segment != sec.sec || f.Address != sec.off) { break; } func = f; funcIndex--; } } else { while (funcIndex < funcs.Length - 1 && func.SequencePoints != null) { PdbFunction f = funcs[funcIndex + 1]; if (f.Segment != sec.sec || f.Address != sec.off) { break; } func = f; funcIndex++; } } if (func.SequencePoints != 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.SequencePoints = new PdbSequencePointCollection[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 = checks[(int)file.index]; PdbSequencePointCollection tmp = new PdbSequencePointCollection(src, file.count); func.SequencePoints[block++] = tmp; PdbSequencePoint[] 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 PdbSequencePoint( line.offset, lineBegin, column.offColumnStart, lineBegin + delta, column.offColumnEnd); } } break; } } bits.Position = endSym; } }
internal PdbFunction(/*string module, */ ManProcSym proc, BitAccess bits) { Token = proc.token; //this.module = module; //this.name = proc.name; //this.flags = proc.flags; Segment = proc.seg; Address = proc.off; //this.length = proc.len; if (proc.seg != 1) { throw new PdbDebugException("Segment is {0}, not 1.", proc.seg); } if (proc.parent != 0 || proc.next != 0) { throw new PdbDebugException( "Warning parent={0}, next={1}", proc.parent, proc.next); } //if (proc.dbgStart != 0 || proc.dbgEnd != 0) { // throw new PdbDebugException("Warning DBG start={0}, end={1}", // proc.dbgStart, proc.dbgEnd); //} int constantCount; int scopeCount; int slotCount; int usedNamespacesCount; CountScopesAndSlots(bits, proc.end, out constantCount, out scopeCount, out slotCount, out usedNamespacesCount); int scope = constantCount > 0 || slotCount > 0 || usedNamespacesCount > 0 ? 1 : 0; int slot = 0; int constant = 0; int usedNs = 0; Scopes = new PdbScope[scopeCount + scope]; Slots = new PdbSlot[slotCount]; Constants = new PdbConstant[constantCount]; Namespaces = new string[usedNamespacesCount]; if (scope > 0) { Scopes[0] = new PdbScope(Address, proc.len, Slots, Constants, Namespaces); } while (bits.Position < proc.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_OEM: { // 0x0404 OemSymbol oem; bits.ReadGuid(out oem.idOem); bits.ReadUInt32(out oem.typind); // internal byte[] rgl; // user data, force 4-byte alignment if (oem.idOem == msilMetaData) { string name = bits.ReadString(); if (name == "MD2") { byte version; bits.ReadUInt8(out version); if (version == 4) { byte count; bits.ReadUInt8(out count); bits.Align(4); unchecked { while (count-- > 0) { ReadCustomMetadata(bits); } } } } bits.Position = stop; break; } throw new PdbDebugException( "OEM section: guid={0} ti={1}", oem.idOem, oem.typind); // bits.Position = stop; } case SYM.S_BLOCK32: { BlockSym32 block = new BlockSym32(); bits.ReadUInt32(out block.parent); bits.ReadUInt32(out block.end); bits.ReadUInt32(out block.len); bits.ReadUInt32(out block.off); bits.ReadUInt16(out block.seg); bits.SkipCString(out block.name); bits.Position = stop; Scopes[scope++] = new PdbScope(Address, block, bits, out slotToken); bits.Position = (int)block.end; break; } case SYM.S_MANSLOT: uint typind; Slots[slot++] = new PdbSlot(bits, out typind); bits.Position = stop; break; case SYM.S_MANCONSTANT: Constants[constant++] = new PdbConstant(bits); bits.Position = stop; break; case SYM.S_UNAMESPACE: bits.ReadCString(out Namespaces[usedNs++]); bits.Position = stop; break; case SYM.S_END: bits.Position = stop; break; default: { //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec); bits.Position = stop; break; } } } if (bits.Position != proc.end) { throw new PdbDebugException("Not at S_END"); } ushort esiz; ushort erec; bits.ReadUInt16(out esiz); bits.ReadUInt16(out erec); if (erec != (ushort)SYM.S_END) { throw new PdbDebugException("Missing S_END"); } }
private static void LoadManagedLines(PdbFunction[] funcs, Dictionary<int, string> names, BitAccess bits, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbStreamHelper reader, uint limit, Dictionary<string, PdbSource> sources) { Array.Sort(funcs, PdbFunction.byAddressAndToken); Dictionary<int, PdbSource> checks = new Dictionary<int, PdbSource>(); // 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 = names[(int)chk.name]; PdbSource src; if (!sources.TryGetValue(name.ToUpperInvariant(), out src)) { int guidStream; Guid doctypeGuid = Guid.Empty; Guid languageGuid = Guid.Empty; Guid vendorGuid = Guid.Empty; Guid algorithmId = Guid.Empty; byte[] checksum = null; byte[] source = null; 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, out algorithmId, out checksum, out source); } src = new PdbSource(/*(uint)ni,*/ name, doctypeGuid, languageGuid, vendorGuid, algorithmId, checksum, source); sources.Add(name.ToUpperInvariant(), src); } 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.SequencePoints == null) { while (funcIndex > 0) { var f = funcs[funcIndex - 1]; if (f.SequencePoints != null || f.Segment != sec.sec || f.Address != sec.off) break; func = f; funcIndex--; } } else { while (funcIndex < funcs.Length - 1 && func.SequencePoints != null) { var f = funcs[funcIndex + 1]; if (f.Segment != sec.sec || f.Address != sec.off) break; func = f; funcIndex++; } } if (func.SequencePoints != 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.SequencePoints = new PdbSequencePointCollection[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]; PdbSequencePointCollection tmp = new PdbSequencePointCollection(src, file.count); func.SequencePoints[block++] = tmp; PdbSequencePoint[] 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 PdbSequencePoint(line.offset, lineBegin, column.offColumnStart, lineBegin + delta, column.offColumnEnd); } } break; } } bits.Position = endSym; } }
internal PdbFunction(/*string module, */ManProcSym proc, BitAccess bits) { this.Token = proc.token; //this.module = module; //this.name = proc.name; //this.flags = proc.flags; this.Segment = proc.seg; this.Address = proc.off; //this.length = proc.len; if (proc.seg != 1) { throw new PdbDebugException("Segment is {0}, not 1.", proc.seg); } if (proc.parent != 0 || proc.next != 0) { throw new PdbDebugException("Warning parent={0}, next={1}", proc.parent, proc.next); } //if (proc.dbgStart != 0 || proc.dbgEnd != 0) { // throw new PdbDebugException("Warning DBG start={0}, end={1}", // proc.dbgStart, proc.dbgEnd); //} int constantCount; int scopeCount; int slotCount; int usedNamespacesCount; CountScopesAndSlots(bits, proc.end, out constantCount, out scopeCount, out slotCount, out usedNamespacesCount); int scope = constantCount > 0 || slotCount > 0 || usedNamespacesCount > 0 ? 1 : 0; int slot = 0; int constant = 0; int usedNs = 0; Scopes = new PdbScope[scopeCount + scope]; Slots = new PdbSlot[slotCount]; Constants = new PdbConstant[constantCount]; Namespaces = new string[usedNamespacesCount]; if (scope > 0) Scopes[0] = new PdbScope(this.Address, proc.len, Slots, Constants, Namespaces); while (bits.Position < proc.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_OEM: { // 0x0404 OemSymbol oem; bits.ReadGuid(out oem.idOem); bits.ReadUInt32(out oem.typind); // internal byte[] rgl; // user data, force 4-byte alignment if (oem.idOem == msilMetaData) { string name = bits.ReadString(); if (name == "MD2") { byte version; bits.ReadUInt8(out version); if (version == 4) { byte count; bits.ReadUInt8(out count); bits.Align(4); while (count-- > 0) this.ReadCustomMetadata(bits); } } bits.Position = stop; break; } else { throw new PdbDebugException("OEM section: guid={0} ti={1}", oem.idOem, oem.typind); // bits.Position = stop; } } case SYM.S_BLOCK32: { BlockSym32 block = new BlockSym32(); bits.ReadUInt32(out block.parent); bits.ReadUInt32(out block.end); bits.ReadUInt32(out block.len); bits.ReadUInt32(out block.off); bits.ReadUInt16(out block.seg); bits.SkipCString(out block.name); bits.Position = stop; Scopes[scope++] = new PdbScope(this.Address, block, bits, out slotToken); bits.Position = (int)block.end; break; } case SYM.S_MANSLOT: uint typind; Slots[slot++] = new PdbSlot(bits, out typind); bits.Position = stop; break; case SYM.S_MANCONSTANT: Constants[constant++] = new PdbConstant(bits); bits.Position = stop; break; case SYM.S_UNAMESPACE: bits.ReadCString(out Namespaces[usedNs++]); bits.Position = stop; break; case SYM.S_END: bits.Position = stop; break; default: { //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec); bits.Position = stop; break; } } } if (bits.Position != proc.end) { throw new PdbDebugException("Not at S_END"); } ushort esiz; ushort erec; bits.ReadUInt16(out esiz); bits.ReadUInt16(out erec); if (erec != (ushort)SYM.S_END) { throw new PdbDebugException("Missing S_END"); } }