/// <summary> /// </summary> /// <param name="bits"> /// </param> /// <returns> /// </returns> /// <exception cref="PdbDebugException"> /// </exception> private static IntHashTable LoadNameStream(BitAccess bits) { var ht = new IntHashTable(); uint sig; int ver; bits.ReadUInt32(out sig); // 0..3 Signature bits.ReadInt32(out ver); // 4..7 Version // Read (or skip) string buffer. int buf; bits.ReadInt32(out buf); // 8..11 Bytes of Strings if (sig != 0xeffeeffe || ver != 1) { throw new PdbDebugException("Unsupported Name Stream version. " + "(sig={0:x8}, ver={1})", sig, ver); } var beg = bits.Position; var nxt = bits.Position + buf; bits.Position = nxt; // Read hash table. int siz; bits.ReadInt32(out siz); // n+0..3 Number of hash buckets. nxt = bits.Position; for (var i = 0; i < siz; i++) { int ni; string name; bits.ReadInt32(out ni); if (ni != 0) { var saved = bits.Position; bits.Position = beg + ni; bits.ReadCString(out name); bits.Position = saved; ht.Add(ni, name); } } bits.Position = nxt; return ht; }
/// <summary> /// </summary> /// <param name="module"> /// </param> /// <param name="bits"> /// </param> /// <param name="limit"> /// </param> /// <param name="readStrings"> /// </param> /// <returns> /// </returns> internal static PdbFunction[] LoadManagedFunctions(string module, BitAccess bits, uint limit, bool readStrings) { var mod = StripNamespace(module); var begin = bits.Position; var count = 0; while (bits.Position < limit) { ushort siz; ushort rec; bits.ReadUInt16(out siz); var star = bits.Position; var 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; var funcs = new PdbFunction[count]; var func = 0; while (bits.Position < limit) { ushort siz; ushort rec; bits.ReadUInt16(out siz); var star = bits.Position; var stop = bits.Position + siz; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_GMANPROC: case SYM.S_LMANPROC: ManProcSym proc; var 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; }
/// <summary> /// </summary> /// <param name="bits"> /// </param> /// <returns> /// </returns> /// <exception cref="PdbDebugException"> /// </exception> private static Dictionary<string, int> LoadNameIndex(BitAccess bits) { var result = new Dictionary<string, int>(); int ver; int sig; int age; Guid guid; bits.ReadInt32(out ver); // 0..3 Version bits.ReadInt32(out sig); // 4..7 Signature bits.ReadInt32(out age); // 8..11 Age bits.ReadGuid(out guid); // 12..27 GUID if (ver != 20000404) { throw new PdbDebugException("Unsupported PDB Stream version {0}", ver); } // Read string buffer. int buf; bits.ReadInt32(out buf); // 28..31 Bytes of Strings var beg = bits.Position; var nxt = bits.Position + buf; bits.Position = nxt; // Read map index. int cnt; // n+0..3 hash size. int max; // n+4..7 maximum ni. bits.ReadInt32(out cnt); bits.ReadInt32(out max); var present = new BitSet(bits); var deleted = new BitSet(bits); if (!deleted.IsEmpty) { throw new PdbDebugException("Unsupported PDB deleted bitset is not empty."); } var j = 0; for (var i = 0; i < max; i++) { if (present.IsSet(i)) { int ns; int ni; bits.ReadInt32(out ns); bits.ReadInt32(out ni); string name; var saved = bits.Position; bits.Position = beg + ns; bits.ReadCString(out name); bits.Position = saved; result.Add(name, ni); j++; } } if (j != cnt) { throw new PdbDebugException("Count mismatch. ({0} != {1})", j, cnt); } return result; }
/// <summary> /// </summary> /// <param name="block"> /// </param> /// <param name="bits"> /// </param> /// <param name="typind"> /// </param> /// <exception cref="PdbException"> /// </exception> /// <exception cref="Exception"> /// </exception> internal PdbScope(BlockSym32 block, BitAccess bits, out uint typind) { this.segment = block.seg; this.address = block.off; 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); this.constants = new PdbConstant[constantCount]; this.scopes = new PdbScope[scopeCount]; this.slots = new PdbSlot[slotCount]; this.usedNamespaces = new string[namespaceCount]; var constant = 0; var scope = 0; var slot = 0; var usedNs = 0; while (bits.Position < block.end) { ushort siz; ushort rec; bits.ReadUInt16(out siz); var star = bits.Position; var stop = bits.Position + siz; bits.Position = star; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_BLOCK32: { var 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; this.scopes[scope++] = new PdbScope(sub, bits, out typind); break; } case SYM.S_MANSLOT: this.slots[slot++] = new PdbSlot(bits, out typind); bits.Position = stop; break; case SYM.S_UNAMESPACE: bits.ReadCString(out this.usedNamespaces[usedNs++]); bits.Position = stop; break; case SYM.S_END: bits.Position = stop; break; case SYM.S_MANCONSTANT: this.constants[constant++] = new PdbConstant(bits); bits.Position = stop; break; default: throw new PdbException("Unknown SYM in scope {0}", (SYM)rec); // bits.Position = stop; } } 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"); } }