internal static PdbFunction[] LoadFunctions(Stream read, BitAccess bits, bool readAllStrings, out int age, out Guid guid)
        {
            PdbFileHeader head   = new PdbFileHeader(read, bits);
            PdbReader     reader = new PdbReader(read, head.pageSize);
            MsfDirectory  dir    = new MsfDirectory(reader, head, bits);

            DbiModuleInfo[] modules = null;
            DbiDbgHdr       header;

            dir.streams[1].Read(reader, bits);
            Dictionary <string, int> nameIndex = LoadNameIndex(bits, out age, out guid);
            int nameStream;

            if (!nameIndex.TryGetValue("/names", out nameStream))
            {
                throw new PdbException("No `name' stream");
            }

            dir.streams[nameStream].Read(reader, bits);
            IntHashTable names = LoadNameStream(bits);

            dir.streams[3].Read(reader, bits);
            LoadDbiStream(bits, out modules, out header, readAllStrings);

            var funcList = new List <PdbFunction>();

            if (modules != null)
            {
                for (int m = 0; m < modules.Length; m++)
                {
                    if (modules[m].stream > 0)
                    {
                        dir.streams[modules[m].stream].Read(reader, bits);
                        LoadFuncsFromDbiModule(bits, modules[m], names, funcList,
                                               readAllStrings, dir, nameIndex, reader);
                    }
                }
            }

            PdbFunction[] funcs = funcList.ToArray();

            // After reading the functions, apply the token remapping table if it exists.
            if (header.snTokenRidMap != 0 && header.snTokenRidMap != 0xffff)
            {
                dir.streams[header.snTokenRidMap].Read(reader, bits);
                uint[] ridMap = new uint[dir.streams[header.snTokenRidMap].Length / 4];
                bits.ReadUInt32(ridMap);

                foreach (PdbFunction func in funcs)
                {
                    func.token = 0x06000000 | ridMap[func.token & 0xffffff];
                }
            }

            //
            Array.Sort(funcs, PdbFunction.byAddress);
            //Array.Sort(funcs, PdbFunction.byToken);
            return(funcs);
        }
        static void LoadFuncsFromDbiModule(BitAccess bits,
                                           DbiModuleInfo info,
                                           IntHashTable names,
                                           ICollection <PdbFunction> funcList,
                                           bool readStrings,
                                           MsfDirectory dir,
                                           Dictionary <string, int> nameIndex,
                                           PdbReader reader)
        {
            PdbFunction[] funcs = null;

            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);
            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]);
                }
            }
        }
        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  = new Guid("5a869d0b-6611-11d3-bd2a-0000f80849bd");
                        Guid   languageGuid = new Guid("3f5162f8-07c6-11d3-9053-00c04fa302a1");
                        Guid   vendorGuid   = new Guid("994b45c4-e6e9-11d2-903f-00c04fa302a1");
                        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;
            }
        }