コード例 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbStringTable"/> class.
        /// </summary>
        /// <param name="reader">Stream binary reader.</param>
        public PdbStringTable(IBinaryReader reader)
        {
            // Read header
            Signature         = reader.ReadUint();
            HashVersion       = reader.ReadUint();
            StringsStreamSize = reader.ReadUint();

            // Read strings table
            StringsStream = reader.ReadSubstream(StringsStreamSize);
            stringsCache  = new DictionaryCache <uint, string>((uint offset) =>
            {
                StringsStream.Position = offset;
                return(StringsStream.ReadCString().String);
            });

            // Read table of offsets that can be accessed by hash function
            uint offsetsCount = reader.ReadUint();

            Offsets = reader.ReadUintArray((int)offsetsCount);

            // Read epilogue
            StringsCount = reader.ReadInt();

            dictionaryCache = SimpleCache.CreateStruct(() =>
            {
                Dictionary <uint, string> strings = new Dictionary <uint, string>();

                foreach (uint offset in Offsets)
                {
                    strings[offset] = stringsCache[offset];
                }
                return(strings);
            });
        }
コード例 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NamedStreamMap"/> class.
        /// </summary>
        /// <param name="reader">Stream binary reader.</param>
        public NamedStreamMap(IBinaryReader reader)
        {
            uint stringsSizeInBytes = reader.ReadUint();

            StringsStream = reader.ReadSubstream(stringsSizeInBytes);
            HashTable     = new HashTable(reader);
            streamsCache  = SimpleCache.CreateStruct(() =>
            {
                Dictionary <string, int> streams = new Dictionary <string, int>();
                IBinaryReader stringsReader      = StringsStream.Duplicate();

                foreach (var kvp in HashTable.Dictionary)
                {
                    stringsReader.Position = kvp.Key;
                    streams.Add(stringsReader.ReadCString().String, (int)kvp.Value);
                }
                return(streams);
            });
            streamsUppercaseCache = SimpleCache.CreateStruct(() =>
            {
                Dictionary <string, int> streams = new Dictionary <string, int>();

                foreach (var kvp in Streams)
                {
                    streams.Add(kvp.Key.ToUpperInvariant(), kvp.Value);
                }
                return(streams);
            });
        }
コード例 #3
0
        public void Assignment()
        {
            int count = 0;
            SimpleCacheStruct <int> cache = SimpleCache.CreateStruct(() =>
            {
                count++;
                return(42);
            });
            var cache2 = cache;

            Assert.Equal(0, count);
            Assert.False(cache.Cached);
            Assert.Equal(42, cache.Value);
            Assert.Equal(1, count);
            Assert.True(cache.Cached);
            Assert.False(cache2.Cached);
            Assert.Equal(42, cache2.Value);
            Assert.Equal(2, count);
            Assert.True(cache2.Cached);
            var cache3 = cache;

            Assert.True(cache3.Cached);
            Assert.Equal(42, cache3.Value);
            Assert.Equal(2, count);
        }
コード例 #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbModule"/> class.
        /// </summary>
        /// <param name="module">The XML module description.</param>
        /// <param name="pdbFile">Already opened PDB file.</param>
        public PdbModule(XmlModule module, PdbFile pdbFile)
        {
            PdbFile             = pdbFile;
            Name                = !string.IsNullOrEmpty(module.Name) ? module.Name : Path.GetFileNameWithoutExtension(module.SymbolsPath).ToLower();
            Namespace           = module.Namespace;
            globalScopeCache    = SimpleCache.CreateStruct(() => new PdbGlobalScope(this));
            builtinSymbolsCache = new DictionaryCache <TypeIndex, PdbSymbol>(CreateBuiltinSymbol);
            allSymbolsCache     = new ArrayCache <PdbSymbol>(PdbFile.TpiStream.TypeRecordCount, CreateSymbol);
            definedSymbolsCache = new ArrayCache <PdbSymbol>(PdbFile.TpiStream.TypeRecordCount, true, GetDefinedSymbol);
            constantsCache      = SimpleCache.CreateStruct(() =>
            {
                Dictionary <string, ConstantSymbol> constants = new Dictionary <string, ConstantSymbol>();

                foreach (SymbolRecordKind kind in ConstantSymbol.Kinds)
                {
                    foreach (ConstantSymbol c in PdbFile.PdbSymbolStream[kind].OfType <ConstantSymbol>())
                    {
                        if (!constants.ContainsKey(c.Name))
                        {
                            constants.Add(c.Name, c);
                        }
                    }
                }
                return((IReadOnlyDictionary <string, ConstantSymbol>)constants);
            });
        }
コード例 #5
0
ファイル: PdbSource.cs プロジェクト: southpolenator/SharpPdb
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbSource"/> class.
 /// </summary>
 /// <param name="pdbFile">Portable PDB file reader.</param>
 /// <param name="handle">Our metadata reader handle.</param>
 internal PdbSource(PdbFile pdbFile, DocumentHandle handle)
 {
     PdbFile       = pdbFile;
     documentCache = SimpleCache.CreateStruct(() => PdbFile.Reader.GetDocument(handle));
     hashCache     = SimpleCache.CreateStruct(() => PdbFile.Reader.GetBlobBytes(Document.Hash));
     nameCache     = SimpleCache.CreateStruct(() => PdbFile.Reader.GetString(Document.Name));
 }
コード例 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PublicsStream"/> class.
        /// </summary>
        /// <param name="file">PDB file containing this stream.</param>
        /// <param name="reader">Binary stream reader.</param>
        public PublicsStream(PdbFile file, IBinaryReader reader)
        {
            if (reader.BytesRemaining < PublicsStreamHeader.Size)
            {
                throw new Exception("Publics Stream does not contain a header.");
            }

            // Read header
            Header = PublicsStreamHeader.Read(reader);

            // Read globals hash table
            if (reader.BytesRemaining < Header.SymbolHashStreamSize)
            {
                throw new Exception("Publics Stream does not contain a header.");
            }
            GlobalsStream = new GlobalsStream(file, reader.ReadSubstream(Header.SymbolHashStreamSize));

            // Read address map
            if (reader.BytesRemaining < Header.AddressMapSize)
            {
                throw new Exception("Could not read an address map.");
            }
            AddressMap = reader.ReadUintArray((int)(Header.AddressMapSize / 4)); // 4 = sizeof(uint)

            // Read thunk map
            if (reader.BytesRemaining < Header.NumberOfThunks * 4) // 4 = sizeof(uint)
            {
                throw new Exception("Could not read a thunk map.");
            }
            ThunkMap = reader.ReadUintArray((int)Header.NumberOfThunks);

            // Read sections
            if (reader.BytesRemaining < Header.NumberOfSections * PublicsStreamSectionOffset.Size)
            {
                throw new Exception("Publics stream doesn't contain all sections specified in the header.");
            }
            PublicsStreamSectionOffset[] sections = new PublicsStreamSectionOffset[Header.NumberOfSections];
            for (int i = 0; i < sections.Length; i++)
            {
                sections[i] = PublicsStreamSectionOffset.Read(reader);
            }
            Sections = sections;

            if (reader.BytesRemaining > 0)
            {
                throw new Exception("Corrupted publics stream.");
            }

            publicSymbolsCache = SimpleCache.CreateStruct(() =>
            {
                Public32Symbol[] publicSymbols = new Public32Symbol[GlobalsStream.Symbols.Count];

                for (int i = 0; i < publicSymbols.Length; i++)
                {
                    publicSymbols[i] = GlobalsStream.Symbols[i] as Public32Symbol;
                }
                return(publicSymbols);
            });
        }
コード例 #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserTypeTransformation"/> class.
 /// </summary>
 /// <param name="transformation">The XML transformation definition.</param>
 /// <param name="typeConverter">The type converter.</param>
 /// <param name="ownerUserType">The owner user type.</param>
 /// <param name="type">The type that should be transformed to user type.</param>
 public UserTypeTransformation(XmlTypeTransformation transformation, Func <string, string> typeConverter, UserType ownerUserType, Symbol type)
 {
     Transformation     = transformation;
     this.typeConverter = typeConverter;
     this.ownerUserType = ownerUserType;
     this.type          = type;
     typeStringCache    = SimpleCache.CreateStruct(() => Transformation.TransformType(type.Name, typeConverter));
 }
コード例 #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="InteractiveExecutionBehavior"/> class.
 /// </summary>
 public InteractiveExecutionBehavior()
 {
     userTypeMetadata      = Context.UserTypeMetadata;
     interactiveScriptBase = SimpleCache.CreateStruct(() =>
     {
         return(new InteractiveScriptBase
         {
             ObjectWriter = new DefaultObjectWriter(),
             _InternalObjectWriter_ = new ConsoleObjectWriter(),
         });
     });
 }
コード例 #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserType"/> class.
 /// </summary>
 /// <param name="symbol">The symbol we are generating this user type from.</param>
 /// <param name="xmlType">The XML description of the type.</param>
 /// <param name="nameSpace">The namespace it belongs to.</param>
 /// <param name="factory">User type factory that contains this element.</param>
 public UserType(Symbol symbol, XmlType xmlType, string nameSpace, UserTypeFactory factory)
 {
     Symbol                  = symbol;
     Factory                 = factory;
     InnerTypes              = new List <UserType>();
     DerivedClasses          = new HashSet <UserType>();
     typeNameCache           = SimpleCache.CreateStruct(() => GetTypeName());
     fullTypeNameCache       = SimpleCache.CreateStruct(() => GetFullTypeName());
     constructorNameCache    = SimpleCache.CreateStruct(() => GetConstructorName());
     namespaceCache          = SimpleCache.CreateStruct(() => GetNamespace(nameSpace));
     membersCache            = SimpleCache.CreateStruct(() => GetMembers().ToArray());
     constructorsCache       = SimpleCache.CreateStruct(() => GetConstructors().ToArray());
     baseClassCache          = SimpleCache.CreateStruct(() => GetBaseClass(Symbol));
     memoryBufferOffsetCache = SimpleCache.CreateStruct(() => GetMemoryBufferOffset());
 }
コード例 #10
0
        public void Disposable()
        {
            int disposedCount = 0;

            using (SimpleCacheStruct <DisposableAction> cache = SimpleCache.CreateStruct(() => new DisposableAction(() => disposedCount++)))
            {
                var v0 = cache.Value;

                cache.InvalidateCache();
                Assert.Equal(1, disposedCount);

                var v1 = cache.Value;
            }
            Assert.Equal(2, disposedCount);
        }
コード例 #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="HashTable"/> class.
        /// </summary>
        /// <param name="reader">Stream binary reader.</param>
        public HashTable(IBinaryReader reader)
        {
            Size     = reader.ReadUint();
            Capacity = reader.ReadUint();
            if (Capacity == 0)
            {
                throw new Exception("Invalid Hash Table Capacity");
            }
            if (Size > MaxLoad(Capacity))
            {
                throw new Exception("Invalid Hash Table Size");
            }
            buckets = new Tuple <uint, uint> [Capacity];
            present = ReadSparseBitArray(reader);
            if (CountBits(present) != Size)
            {
                throw new Exception("Present bit vector does not match size!");
            }
            deleted = ReadSparseBitArray(reader);
            if (BitsIntersect(present, deleted))
            {
                throw new Exception("Present bit vector interesects deleted!");
            }
            for (int i = 0, index = 0; i < present.Length; i++)
            {
                for (uint j = 0, bit = 1; j < 32; j++, bit <<= 1, index++)
                {
                    if ((present[i] & bit) != 0)
                    {
                        buckets[index] = Tuple.Create(reader.ReadUint(), reader.ReadUint());
                    }
                }
            }
            dictionaryCache = SimpleCache.CreateStruct(() =>
            {
                Dictionary <uint, uint> dictionary = new Dictionary <uint, uint>();

                foreach (var tuple in buckets)
                {
                    if (tuple != null)
                    {
                        dictionary.Add(tuple.Item1, tuple.Item2);
                    }
                }
                return(dictionary);
            });
        }
コード例 #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbLocalScope"/> class.
        /// </summary>
        /// <param name="function">Function that contains this scope.</param>
        /// <param name="block">Block symbol read from PDB.</param>
        /// <param name="parent">Parent scope.</param>
        internal PdbLocalScope(PdbFunction function, BlockSymbol block, PdbLocalScope parent = null)
        {
            Function      = function;
            Block         = block;
            Parent        = parent;
            childrenCache = SimpleCache.CreateStruct(() =>
            {
                IEnumerable <BlockSymbol> blocks = Block.Children.OfType <BlockSymbol>();
                int count = blocks.Count();
                IPdbLocalScope[] children = new IPdbLocalScope[count];
                int i = 0;

                foreach (BlockSymbol b in blocks)
                {
                    children[i++] = new PdbLocalScope(Function, b, this);
                }
                return(children);
            });
            constantsCache = SimpleCache.CreateStruct(() =>
            {
                IEnumerable <ConstantSymbol> symbols = Block.Children.OfType <ConstantSymbol>();
                int count = symbols.Count();
                IPdbLocalConstant[] constants = new IPdbLocalConstant[count];
                int i = 0;

                foreach (ConstantSymbol symbol in symbols)
                {
                    constants[i++] = new PdbLocalConstant(this, symbol);
                }
                return(constants);
            });
            variablesCache = SimpleCache.CreateStruct(() =>
            {
                IEnumerable <AttributeSlotSymbol> slots = Block.Children.OfType <AttributeSlotSymbol>();
                int count = slots.Count();
                IPdbLocalVariable[] variables = new IPdbLocalVariable[count];
                int i = 0;

                foreach (AttributeSlotSymbol slot in slots)
                {
                    variables[i++] = new PdbLocalVariable(this, slot);
                }
                return(variables);
            });
        }
コード例 #13
0
ファイル: PdbFile.cs プロジェクト: southpolenator/SharpPdb
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFile"/> class.
        /// </summary>
        /// <param name="reader">Portable PDB metadata reader.</param>
        internal PdbFile(MetadataReader reader)
        {
            Reader         = reader;
            idCache        = SimpleCache.CreateStruct(() => new BlobContentId(Reader.DebugMetadataHeader.Id));
            functionsCache = SimpleCache.CreateStruct(() =>
            {
                IPdbFunction[] functions = new IPdbFunction[Reader.MethodDebugInformation.Count];
                int i = 0;

                foreach (var f in Reader.MethodDebugInformation)
                {
                    functions[i++] = functionsByHandle[f];
                }
                return(functions);
            });
            sourcesCache      = new DictionaryCache <DocumentHandle, IPdbSource>(GetSource);
            functionsByHandle = new DictionaryCache <MethodDebugInformationHandle, PdbFunction>(f => new PdbFunction(this, f));
        }
コード例 #14
0
        public void SingleEvaluation()
        {
            int count = 0;
            SimpleCacheStruct <int> cache = SimpleCache.CreateStruct(() =>
            {
                count++;
                return(42);
            });

            Assert.Equal(0, count);
            Assert.False(cache.Cached);
            Assert.Equal(42, cache.Value);
            Assert.Equal(1, count);
            Assert.True(cache.Cached);
            Assert.Equal(42, cache.Value);
            Assert.Equal(1, count);
            Assert.Single(cache, 42);
        }
コード例 #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFile"/> class.
        /// </summary>
        /// <param name="file">File loaded into memory for faster parsing.</param>
        public PdbFile(MemoryLoadedFile file)
        {
            Reader         = new SharpPdb.Windows.PdbFile(file);
            functionsCache = SimpleCache.CreateStruct(() =>
            {
                List <IPdbFunction> functions = new List <IPdbFunction>();

                foreach (var dbiModule in Reader.DbiStream.Modules)
                {
                    var symbolStream = dbiModule.LocalSymbolStream;

                    foreach (var kind in ManagedProcedureSymbol.Kinds)
                    {
                        foreach (ManagedProcedureSymbol procedure in symbolStream[kind])
                        {
                            functions.Add(new PdbFunction(this, procedure, dbiModule));
                        }
                    }
                }
                return(functions);
            });
            sourcesCache          = new DictionaryCache <FileChecksumSubsection, PdbSource>(checksum => new PdbSource(this, checksum));
            functionsByTokenCache = SimpleCache.CreateStruct(() => Functions.ToDictionary(f => f.Token));
            tokenRidMapCache      = SimpleCache.CreateStruct(() =>
            {
                var reader = Reader.DbiStream.GetKnownDebugStream(KnownDebugStreamIndex.TokenRidMap)?.Reader;

                if (reader == null)
                {
                    return(null);
                }

                int count          = (int)(reader.Length / 4); // 4 = sizeof(uint)
                uint[] tokenRidMap = new uint[count];

                for (int i = 0; i < count; i++)
                {
                    tokenRidMap[i] = reader.ReadUint();
                }
                return(tokenRidMap);
            });
            this.file = file;
        }
コード例 #16
0
        public void EvaluationAfterInvalidate()
        {
            int count = 0;
            SimpleCacheStruct <int> cache = SimpleCache.CreateStruct(() =>
            {
                count++;
                return(42);
            });

            Assert.Equal(0, count);
            Assert.Equal(42, cache.Value);
            Assert.Equal(1, count);
            Assert.Equal(42, cache.Value);
            Assert.Equal(1, count);
            cache.InvalidateCache();
            Assert.Equal(1, count);
            Assert.Equal(42, cache.Value);
            Assert.Equal(2, count);
        }
コード例 #17
0
        public void SettingValue()
        {
            int count = 0;
            SimpleCacheStruct <int> cache = SimpleCache.CreateStruct(() =>
            {
                count++;
                return(42);
            });

            Assert.Equal(0, count);
            Assert.Equal(42, cache.Value);
            Assert.Equal(1, count);
            cache.Value = 12345;
            Assert.Equal(12345, cache.Value);
            Assert.Equal(1, count);
            cache.InvalidateCache();
            Assert.Equal(1, count);
            Assert.Equal(42, cache.Value);
            Assert.Equal(2, count);
        }
コード例 #18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFunction"/> class.
        /// </summary>
        /// <param name="pdbFile">Portable PDB file reader.</param>
        /// <param name="procedure">Managed procedure symbol from PDB.</param>
        /// <param name="dbiModule">DBI module descriptor from PDB.</param>
        internal PdbFunction(PdbFile pdbFile, ManagedProcedureSymbol procedure, DbiModuleDescriptor dbiModule)
        {
            PdbFile          = pdbFile;
            Procedure        = procedure;
            DbiModule        = dbiModule;
            localScopesCache = SimpleCache.CreateStruct(() =>
            {
                IEnumerable <BlockSymbol> blocks = Procedure.Children.OfType <BlockSymbol>();
                int count = blocks.Count();
                IPdbLocalScope[] scopes = new IPdbLocalScope[count];
                int i = 0;

                foreach (BlockSymbol block in blocks)
                {
                    scopes[i++] = new PdbLocalScope(this, block);
                }
                return(scopes);
            });
            sequencePointsCache = SimpleCache.CreateStruct(() =>
            {
                var checksums        = DbiModule.DebugSubsectionStream[DebugSubsectionKind.FileChecksums];
                var linesSubsections = dbiModule.DebugSubsectionStream[DebugSubsectionKind.Lines];
                List <IPdbSequencePoint> sequencePoints = new List <IPdbSequencePoint>();

                foreach (LinesSubsection linesSubsection in linesSubsections)
                {
                    foreach (var file in linesSubsection.Files)
                    {
                        var checksum = (FileChecksumSubsection)checksums[file.Index];
                        var source   = PdbFile[checksum];

                        foreach (var line in file.Lines)
                        {
                            sequencePoints.Add(new PdbSequencePoint(this, source, line));
                        }
                    }
                }

                return(sequencePoints);
            });
        }
コード例 #19
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbLocalScope"/> class.
        /// </summary>
        /// <param name="function">Function that contains this scope.</param>
        /// <param name="handle">Our metadata reader handle.</param>
        /// <param name="parent">Parent scope.</param>
        internal PdbLocalScope(PdbFunction function, LocalScopeHandle handle, IPdbLocalScope parent = null)
        {
            Function        = function;
            localScopeCache = SimpleCache.CreateStruct(() => function.PdbFile.Reader.GetLocalScope(handle));
            childrenCache   = SimpleCache.CreateStruct(() =>
            {
                var enumerator = LocalScope.GetChildren();
                List <IPdbLocalScope> children = new List <IPdbLocalScope>();

                while (enumerator.MoveNext())
                {
                    children.Add(new PdbLocalScope(function, enumerator.Current, this));
                }
                return(children);
            });
            constantsCache = SimpleCache.CreateStruct(() =>
            {
                var localConstants            = LocalScope.GetLocalConstants();
                IPdbLocalConstant[] constants = new IPdbLocalConstant[localConstants.Count];
                int i = 0;

                foreach (var c in localConstants)
                {
                    constants[i++] = new PdbLocalConstant(this, c);
                }
                return(constants);
            });
            variablesCache = SimpleCache.CreateStruct(() =>
            {
                var localVariables            = LocalScope.GetLocalVariables();
                IPdbLocalVariable[] variables = new IPdbLocalVariable[localVariables.Count];
                int i = 0;

                foreach (var v in localVariables)
                {
                    variables[i++] = new PdbLocalVariable(this, v);
                }
                return(variables);
            });
        }
コード例 #20
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DbiModuleDescriptor"/> class.
        /// </summary>
        /// <param name="reader">Stream binary reader.</param>
        /// <param name="moduleList">Owning module list.</param>
        public DbiModuleDescriptor(IBinaryReader reader, DbiModuleList moduleList)
        {
            ModuleList = moduleList;
            filesCache = SimpleCache.CreateStruct(() =>
            {
                string[] files = new string[NumberOfFiles];

                for (int i = 0; i < files.Length; i++)
                {
                    files[i] = ModuleList.GetFileName(i + StartingFileIndex);
                }
                return(files);
            });
            Header         = ModuleInfoHeader.Read(reader);
            ModuleName     = reader.ReadCString();
            ObjectFileName = reader.ReadCString();

            // Descriptors should be aligned at 4 bytes
            if (reader.Position % 4 != 0)
            {
                reader.Position += 4 - reader.Position % 4;
            }
        }
コード例 #21
0
ファイル: PdbSource.cs プロジェクト: southpolenator/SharpPdb
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbSource"/> class.
        /// </summary>
        /// <param name="pdbFile">Portable PDB file reader.</param>
        /// <param name="checksum">File checksum subsection.</param>
        internal PdbSource(PdbFile pdbFile, FileChecksumSubsection checksum)
        {
            PdbFile         = pdbFile;
            Checksum        = checksum;
            hashCache       = SimpleCache.CreateStruct(() => GuidStream?.ChecksumReader.ReadAllBytes() ?? Checksum.HashReader.ReadAllBytes());
            nameCache       = SimpleCache.CreateStruct(() => PdbFile.NamesStream.Dictionary[checksum.NameIndex]);
            guidStreamCache = SimpleCache.CreateStruct(() =>
            {
                int guidStreamIndex;

                if (PdbFile.Reader.InfoStream.NamedStreamMap.Streams.TryGetValue("/src/files/" + Name, out guidStreamIndex) ||
                    PdbFile.Reader.InfoStream.NamedStreamMap.StreamsUppercase.TryGetValue("/SRC/FILES/" + Name.ToUpperInvariant(), out guidStreamIndex))
                {
                    PdbStream guidStream = PdbFile.Reader.GetStream(guidStreamIndex);

                    if (guidStream != null)
                    {
                        return(new GuidStream(guidStream));
                    }
                }
                return(null);
            });
        }
コード例 #22
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFunction"/> class.
        /// </summary>
        /// <param name="pdbFile">Portable PDB file reader.</param>
        /// <param name="handle">Our metadata reader handle.</param>
        internal PdbFunction(PdbFile pdbFile, MethodDebugInformationHandle handle)
        {
            PdbFile = pdbFile;
            methodDebugInformationCache = SimpleCache.CreateStruct(() => pdbFile.Reader.GetMethodDebugInformation(handle));
            localScopesCache            = SimpleCache.CreateStruct(() =>
            {
                var localScopes         = pdbFile.Reader.GetLocalScopes(handle);
                IPdbLocalScope[] scopes = new IPdbLocalScope[localScopes.Count];
                int i = 0;

                foreach (var l in localScopes)
                {
                    scopes[i++] = new PdbLocalScope(this, l);
                }
                return(scopes);
            });
            sequencePointsCache = SimpleCache.CreateStruct(() =>
            {
                var sequencePoints = MethodDebugInformation.GetSequencePoints();

                return(sequencePoints.Select(sp => new PdbSequencePoint(this, sp)).OfType <IPdbSequencePoint>().ToArray());
            });
            Token = System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(handle.ToDefinitionHandle());
        }
コード例 #23
0
ファイル: Symbol.cs プロジェクト: sdmaclea/SharpDebug
        /// <summary>
        /// Initializes a new instance of the <see cref="Symbol"/> class.
        /// </summary>
        /// <param name="module">The module.</param>
        public Symbol(Module module)
        {
            Module            = module;
            fields            = SimpleCache.CreateStruct(() => GetFields().ToArray());
            baseClasses       = SimpleCache.CreateStruct(() => GetBaseClasses().ToArray());
            elementType       = SimpleCache.CreateStruct(() => GetElementType());
            pointerType       = SimpleCache.CreateStruct(() => GetPointerType());
            enumValues        = SimpleCache.CreateStruct(() => GetEnumValues().ToArray());
            enumValuesByValue = SimpleCache.CreateStruct(() =>
            {
                Dictionary <string, string> values = new Dictionary <string, string>();

                foreach (var kvp in EnumValues)
                {
                    if (!values.ContainsKey(kvp.Item2))
                    {
                        values.Add(kvp.Item2, kvp.Item1);
                    }
                }
                return(values);
            });
            namespaces = SimpleCache.CreateStruct(() => SymbolNameHelper.GetSymbolNamespaces(Name));
            userType   = SimpleCache.CreateStruct(() => (UserType)null);
        }
コード例 #24
0
ファイル: PDBFile.cs プロジェクト: wy182000/PadAnalyzer
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFile"/> class.
        /// </summary>
        /// <param name="path">Path to PDB file.</param>
        public PdbFile(string path)
        {
            File   = new MMFile(path);
            Reader = new MMFileReader(File);

            // Parse file headers

            // Initialize MSF super block
            SuperBlock = MSF.SuperBlock.Read(Reader);

            SuperBlock.Validate();
            if (File.Length % SuperBlock.BlockSize != 0)
            {
                throw new Exception("File size is not a multiple of block size");
            }

            // Initialize Free Page Map.
            // The Fpm exists either at block 1 or block 2 of the MSF. However, this
            // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and
            // thusly an equal number of total blocks in the file. For a block size
            // of 4KiB (very common), this would yield 32KiB total blocks in file, for a
            // maximum file size of 32KiB * 4KiB = 128MiB. Obviously this won't do, so
            // the Fpm is split across the file at `getBlockSize()` intervals.  As a
            // result, every block whose index is of the form |{1,2} + getBlockSize() * k|
            // for any non-negative integer k is an Fpm block. In theory, we only really
            // need to reserve blocks of the form |{1,2} + getBlockSize() * 8 * k|, but
            // current versions of the MSF format already expect the Fpm to be arranged
            // at getBlockSize() intervals, so we have to be compatible.
            // See the function fpmPn() for more information:
            // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
            uint fpmIntervals = (SuperBlock.NumBlocks + 8 * SuperBlock.BlockSize - 1) / (8 * SuperBlock.BlockSize);

            uint[] fpmBlocks       = new uint[fpmIntervals];
            uint   currentFpmBlock = SuperBlock.FreeBlockMapBlock;

            for (int i = 0; i < fpmBlocks.Length; i++)
            {
                fpmBlocks[i]     = currentFpmBlock;
                currentFpmBlock += SuperBlock.BlockSize;
            }

            IBinaryReader fpmStream = new MappedBlockBinaryReader <MMFileReader>(fpmBlocks, SuperBlock.BlockSize, (SuperBlock.NumBlocks + 7) / 8, Reader);

            FreePageMap = Reader.ReadByteArray((int)fpmStream.Length);

            // Read directory blocks
            Reader.Position = (long)SuperBlock.BlockMapOffset;
            uint[] directoryBlocks = Reader.ReadUintArray((int)SuperBlock.NumDirectoryBlocks);

            // Parse stream data
            uint      NumStreams      = 0;
            PdbStream directoryStream = new PdbStream(directoryBlocks, SuperBlock.NumDirectoryBytes, this);

            NumStreams = directoryStream.Reader.ReadUint();
            streams    = new PdbStream[NumStreams];
            uint[] streamSizes = directoryStream.Reader.ReadUintArray(streams.Length);
            for (int i = 0; i < streams.Length; i++)
            {
                uint   streamSize = streamSizes[i];
                uint   NumExpectedStreamBlocks = streamSize == uint.MaxValue ? 0 : SuperBlock.BytesToBlocks(streamSize);
                uint[] blocks = directoryStream.Reader.ReadUintArray((int)NumExpectedStreamBlocks);

                foreach (uint block in blocks)
                {
                    ulong blockEndOffset = SuperBlock.BlocksToBytes(block + 1);

                    if (blockEndOffset > (ulong)File.Length)
                    {
                        throw new Exception("Stream block map is corrupt.");
                    }
                }

                streams[i] = new PdbStream(blocks, streamSize, this);
            }

            if (directoryStream.Reader.Position != SuperBlock.NumDirectoryBytes)
            {
                throw new Exception("Not whole directory stream was read");
            }

            dbiStreamCache       = SimpleCache.CreateStruct(() => new DbiStream(streams[(uint)SpecialStream.StreamDBI]));
            pdbSymbolStreamCache = SimpleCache.CreateStruct(() => new SymbolStream(streams[DbiStream.SymbolRecordStreamIndex]));
            tpiStreamCache       = SimpleCache.CreateStruct(() => new TpiStream(streams[(uint)SpecialStream.StreamTPI]));
            ipiStreamCache       = SimpleCache.CreateStruct(() => new TpiStream(streams[(uint)SpecialStream.StreamIPI]));
        }
コード例 #25
0
ファイル: TpiStream.cs プロジェクト: southpolenator/SharpPdb
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbStream"/> class.
        /// </summary>
        /// <param name="stream">PDB symbol stream.</param>
        public TpiStream(PdbStream stream)
        {
            Stream = stream;
            if (stream.Reader.BytesRemaining < TpiStreamHeader.Size)
            {
                throw new Exception("TPI Stream does not contain a header.");
            }
            Header = TpiStreamHeader.Read(stream.Reader);

            if (Header.Version != PdbTpiVersion.V80)
            {
                throw new Exception("Unsupported TPI Version.");
            }

            if (Header.HeaderSize != TpiStreamHeader.Size)
            {
                throw new Exception("Corrupt TPI Header size.");
            }

            if (Header.HashKeySize != 4) // 4 = sizeof(uint)
            {
                throw new Exception("TPI Stream expected 4 byte hash key size.");
            }

            if (Header.HashBucketsCount < MinTpiHashBuckets || Header.HashBucketsCount > MaxTpiHashBuckets)
            {
                throw new Exception("TPI Stream Invalid number of hash buckets.");
            }

            // The actual type records themselves come from this stream
            TypeRecordsSubStream          = Stream.Reader.ReadSubstream(Header.TypeRecordBytes);
            typeRecordsSubStreamPerThread = new System.Threading.ThreadLocal <IBinaryReader>(() => TypeRecordsSubStream.Duplicate());

            IBinaryReader reader = TypeRecordsSubStream;
            long          position = reader.Position, end = reader.Length;

            references = new List <RecordReference>();
            while (position < end)
            {
                RecordPrefix prefix = RecordPrefix.Read(reader);

                if (prefix.RecordLength < 2)
                {
                    throw new Exception("CV corrupt record");
                }

                TypeLeafKind kind    = (TypeLeafKind)prefix.RecordKind;
                ushort       dataLen = prefix.DataLen;

                references.Add(new RecordReference
                {
                    DataOffset = (uint)position + RecordPrefix.Size,
                    Kind       = kind,
                    DataLen    = dataLen,
                });
                position += dataLen + RecordPrefix.Size;
                reader.Move(dataLen);
            }
            typesCache       = new ArrayCache <TypeRecord>(references.Count, true, ReadType);
            typesByKindCache = new DictionaryCache <TypeLeafKind, TypeRecord[]>(GetTypesByKind);

            // Hash indices, hash values, etc come from the hash stream.
            HashSubstream   = Stream.File.GetStream(Header.HashStreamIndex)?.Reader;
            hashValuesCache = SimpleCache.CreateStruct(() =>
            {
                if (HashSubstream != null)
                {
                    // There should be a hash value for every type record, or no hashes at all.
                    uint numHashValues = Header.HashValueBuffer.Length / 4; // 4 = sizeof(uint)
                    if (numHashValues != references.Count && numHashValues != 0)
                    {
                        throw new Exception("TPI hash count does not match with the number of type records.");
                    }

                    HashSubstream.Position = Header.HashValueBuffer.Offset;
                    return(HashSubstream.ReadUintArray(references.Count));
                }
                return(null);
            });
            typeIndexOffsetsCache = SimpleCache.CreateStruct(() =>
            {
                if (HashSubstream != null)
                {
                    HashSubstream.Position             = Header.IndexOffsetBuffer.Offset;
                    uint numTypeIndexOffsets           = Header.IndexOffsetBuffer.Length / TypeIndexOffset.Size;
                    TypeIndexOffset[] typeIndexOffsets = new TypeIndexOffset[numTypeIndexOffsets];
                    for (uint i = 0; i < typeIndexOffsets.Length; i++)
                    {
                        typeIndexOffsets[i] = TypeIndexOffset.Read(HashSubstream);
                    }
                    return(typeIndexOffsets);
                }
                return(null);
            });
            hashAdjustersCache = SimpleCache.CreateStruct(() =>
            {
                if (HashSubstream != null && Header.HashAdjustersBuffer.Length > 0)
                {
                    HashSubstream.Position = Header.HashAdjustersBuffer.Offset;
                    return(new HashTable(HashSubstream));
                }
                return(null);
            });
            hashTableCache = SimpleCache.CreateStruct(() =>
            {
                uint[] hashes = HashValues;

                if (hashes != null)
                {
                    // Construct hash table
                    TypeIndexListItem[] hashTable = new TypeIndexListItem[Header.HashBucketsCount];

                    for (uint ti = Header.TypeIndexBegin, i = 0; ti < Header.TypeIndexEnd; ti++, i++)
                    {
                        uint bucket = hashes[i] % Header.HashBucketsCount;

                        hashTable[bucket] = new TypeIndexListItem(new TypeIndex(ti), hashTable[bucket]);
                    }

                    // Use hash adjusters to improve hash table
                    if (HashAdjusters != null)
                    {
                        var namesMap = Stream.File.InfoStream.NamesMap;

                        foreach (var kvp in HashAdjusters.Dictionary)
                        {
                            uint nameIndex      = kvp.Key;
                            TypeIndex typeIndex = new TypeIndex(kvp.Value);
                            string name         = namesMap.GetString(nameIndex);
                            uint hash           = Windows.HashTable.HashStringV1(name) % (uint)hashTable.Length;

                            // Find type index hash adjusters wants to be head
                            for (TypeIndexListItem item = hashTable[hash], previousItem = null; item != null; previousItem = item, item = item.Next)
                            {
                                if (item.TypeIndex == typeIndex)
                                {
                                    if (previousItem == null)
                                    {
                                        // Our type index is already at the head
                                        break;
                                    }
                                    previousItem.Next = item.Next;
                                    item.Next         = hashTable[hash];
                                    hashTable[hash]   = item;
                                    break;
                                }
                            }
                        }
                    }

                    return(hashTable);
                }
                return(null);
            });
        }
コード例 #26
0
 public DifferentCachesStruct(bool unused)
 {
     simpleCache       = SimpleCache.Create(() => 42);
     simpleCacheStruct = SimpleCache.CreateStruct(() => 42);
 }
コード例 #27
0
 public DifferentCaches()
 {
     simpleCache            = SimpleCache.Create(() => 42);
     simpleCacheStruct      = SimpleCache.CreateStruct(() => 42);
     simpleCacheWithContext = SimpleCache.CreateWithContext(this, simpleCacheWithContextStaticDelegate);
 }
コード例 #28
0
ファイル: DbiStream.cs プロジェクト: southpolenator/SharpPdb
        /// <summary>
        /// Initializes a new instance of the <see cref="DbiStream"/> class.
        /// </summary>
        /// <param name="stream">PDB stream that contains DBI stream.</param>
        public DbiStream(PdbStream stream)
        {
            Stream = stream;
            stream.Reader.Position = 0;
            if (Stream.Length < DbiStreamHeader.Size)
            {
                throw new Exception("DBI Stream does not contain a header.");
            }
            Header = DbiStreamHeader.Read(stream.Reader);
            if (Header.VersionSignature != -1)
            {
                throw new Exception("Invalid DBI version signature.");
            }

            // Require at least version 7, which should be present in all PDBs
            // produced in the last decade and allows us to avoid having to
            // special case all kinds of complicated arcane formats.
            if (Header.Version < DbiStreamVersion.V70)
            {
                throw new Exception("Unsupported DBI version.");
            }

            int expectedSize = DbiStreamHeader.Size + Header.ModuleInfoSubstreamSize + Header.SectionContributionSubstreamSize +
                               Header.SectionMapSize + Header.FileInfoSize + Header.TypeServerSize +
                               Header.OptionalDebugHeaderSize + Header.ECSubstreamSize;

            if (Stream.Length != expectedSize)
            {
                throw new Exception("DBI Length does not equal sum of substreams.");
            }

            // Only certain substreams are guaranteed to be aligned. Validate
            // them here.
            if (Header.ModuleInfoSubstreamSize % 4 != 0)
            {
                throw new Exception("DBI MODI substream not aligned.");
            }
            if (Header.SectionContributionSubstreamSize % 4 != 0)
            {
                throw new Exception("DBI section contribution substream not aligned.");
            }
            if (Header.SectionMapSize % 4 != 0)
            {
                throw new Exception("DBI section map substream not aligned.");
            }
            if (Header.FileInfoSize % 4 != 0)
            {
                throw new Exception("DBI file info substream not aligned.");
            }
            if (Header.TypeServerSize % 4 != 0)
            {
                throw new Exception("DBI type server substream not aligned.");
            }

            // Get substreams
            ModuleInfoSubstream          = stream.Reader.ReadSubstream(Header.ModuleInfoSubstreamSize);
            SectionContributionSubstream = stream.Reader.ReadSubstream(Header.SectionContributionSubstreamSize);
            SectionMapSubstream          = stream.Reader.ReadSubstream(Header.SectionMapSize);
            FileInfoSubstream            = stream.Reader.ReadSubstream(Header.FileInfoSize);
            TypeServerMapSubstream       = stream.Reader.ReadSubstream(Header.TypeServerSize);
            ECSubstream        = stream.Reader.ReadSubstream(Header.ECSubstreamSize);
            DebugStreamIndexes = stream.Reader.ReadUshortArray(Header.OptionalDebugHeaderSize / 2);
            if (stream.Reader.BytesRemaining > 0)
            {
                throw new Exception("Found unexpected bytes in DBI Stream.");
            }

            // Create caches for reading substreams
            modulesCache = SimpleCache.CreateStruct(() =>
            {
                ModuleInfoSubstream.Position = 0;
                FileInfoSubstream.Position   = 0;
                return(new DbiModuleList(ModuleInfoSubstream, FileInfoSubstream, this));
            });
            if (SectionContributionSubstream.Length > 0)
            {
                DbiSectionContributionVersion version = (DbiSectionContributionVersion)SectionContributionSubstream.ReadUint();

                if (version != DbiSectionContributionVersion.V60 && version != DbiSectionContributionVersion.V2)
                {
                    throw new Exception("Unsupported DBI Section Contribution version");
                }
            }
            sectionContributionsCache = SimpleCache.CreateStruct(() =>
            {
                SectionContributionEntry[] result = null;

                if (SectionContributionSubstream.Length > 0)
                {
                    SectionContributionSubstream.Position = 0;
                    DbiSectionContributionVersion version = (DbiSectionContributionVersion)SectionContributionSubstream.ReadUint();

                    if (version == DbiSectionContributionVersion.V60)
                    {
                        // Read array from the stream
                        result = new SectionContributionEntry[SectionContributionSubstream.BytesRemaining / SectionContributionEntry.Size];
                        for (int i = 0; i < result.Length; i++)
                        {
                            result[i] = SectionContributionEntry.Read(SectionContributionSubstream);
                        }
                    }
                    else
                    {
                        // Copy values from newer section contributions since it is expanded version of us.
                        SectionContributionEntry2[] result2 = SectionContributions2;

                        if (result2 != null)
                        {
                            result = new SectionContributionEntry[result2.Length];
                            for (int i = 0; i < result.Length; i++)
                            {
                                result[i] = result2[i].Base;
                            }
                        }
                    }
                }
                return(result);
            });
            sectionContributions2Cache = SimpleCache.CreateStruct(() =>
            {
                SectionContributionEntry2[] result = null;

                if (SectionContributionSubstream.Length > 0)
                {
                    SectionContributionSubstream.Position = 0;
                    DbiSectionContributionVersion version = (DbiSectionContributionVersion)SectionContributionSubstream.ReadUint();

                    if (version == DbiSectionContributionVersion.V2)
                    {
                        // Read array from the stream
                        result = new SectionContributionEntry2[SectionContributionSubstream.BytesRemaining / SectionContributionEntry2.Size];
                        for (int i = 0; i < result.Length; i++)
                        {
                            result[i] = SectionContributionEntry2.Read(SectionContributionSubstream);
                        }
                    }
                }
                return(result);
            });

            CoffSectionHeader[] ReadSectionHeadersStream(IBinaryReader sectionHeaderStream)
            {
                if (sectionHeaderStream != null)
                {
                    sectionHeaderStream.Position = 0;
                    if (sectionHeaderStream.Length % CoffSectionHeader.Size != 0)
                    {
                        throw new Exception("Corrupted section header stream.");
                    }

                    int numSections = (int)(sectionHeaderStream.Length / CoffSectionHeader.Size);
                    CoffSectionHeader[] sectionHeaders = new CoffSectionHeader[numSections];

                    for (int i = 0; i < numSections; i++)
                    {
                        sectionHeaders[i] = CoffSectionHeader.Read(sectionHeaderStream);
                    }
                    return(sectionHeaders);
                }
                return(null);
            };

            sectionHeadersCache         = SimpleCache.CreateStruct(() => ReadSectionHeadersStream(GetKnownDebugStream(KnownDebugStreamIndex.SectionHdr)?.Reader));
            originalSectionHeadersCache = SimpleCache.CreateStruct(() => ReadSectionHeadersStream(GetKnownDebugStream(KnownDebugStreamIndex.SectionHdrOrig)?.Reader));
            sectionMapCache             = SimpleCache.CreateStruct(() =>
            {
                if (SectionMapSubstream.Length > 0)
                {
                    SectionMapSubstream.Position = 0;
                    ushort secCount    = SectionMapSubstream.ReadUshort();
                    ushort secCountLog = SectionMapSubstream.ReadUshort();

                    SectionMapEntry[] sectionMap = new SectionMapEntry[secCount];
                    for (int i = 0; i < sectionMap.Length; i++)
                    {
                        sectionMap[i] = SectionMapEntry.Read(SectionMapSubstream);
                    }
                    return(sectionMap);
                }
                return(null);
            });
            fpoStreamCache  = SimpleCache.CreateStruct(() => GetKnownDebugStream(KnownDebugStreamIndex.FPO)?.Reader);
            fpoRecordsCache = SimpleCache.CreateStruct(() =>
            {
                if (FpoStream != null)
                {
                    FpoStream.Position = 0;
                    if (FpoStream.Length % FpoData.Size != 0)
                    {
                        throw new Exception("Corrupted New FPO stream.");
                    }

                    int numRecords       = (int)(FpoStream.Length / FpoData.Size);
                    FpoData[] fpoRecords = new FpoData[numRecords];

                    for (int i = 0; i < numRecords; i++)
                    {
                        fpoRecords[i] = FpoData.Read(FpoStream);
                    }
                    return(fpoRecords);
                }
                return(null);
            });
            OmapEntry[] LoadOmapStream(IBinaryReader omapReader)
            {
                if (omapReader != null)
                {
                    omapReader.Position = 0;
                    if (omapReader.Length % OmapEntry.Size != 0)
                    {
                        throw new Exception("Corrupted Omap stream.");
                    }

                    int         count   = (int)(omapReader.Length / OmapEntry.Size);
                    OmapEntry[] entries = new OmapEntry[count];

                    for (int i = 0; i < count; i++)
                    {
                        entries[i] = OmapEntry.Read(omapReader);
                    }
                    return(entries);
                }
                return(null);
            };

            omapToSourceEntriesCache   = SimpleCache.CreateStruct(() => LoadOmapStream(GetKnownDebugStream(KnownDebugStreamIndex.OmapToSrc)?.Reader));
            omapFromSourceEntriesCache = SimpleCache.CreateStruct(() => LoadOmapStream(GetKnownDebugStream(KnownDebugStreamIndex.OmapFromSrc)?.Reader));
            ecNamesCache = SimpleCache.CreateStruct(() => ECSubstream.Length > 0 ? new PdbStringTable(ECSubstream) : null);
        }
コード例 #29
0
ファイル: DbiModuleList.cs プロジェクト: wy182000/PadAnalyzer
        /// <summary>
        /// Initializes a new instance of the <see cref="DbiModuleList"/> class.
        /// </summary>
        /// <param name="moduleInfoStream">Module info stream binary reader.</param>
        /// <param name="fileInfoStream">File info stream binary reader.</param>
        public DbiModuleList(IBinaryReader moduleInfoStream, IBinaryReader fileInfoStream)
        {
            ModuleInfoStream = moduleInfoStream;
            modulesCache     = SimpleCache.CreateStruct(() =>
            {
                var descriptors = new List <DbiModuleDescriptor>();
                while (ModuleInfoStream.BytesRemaining > 0)
                {
                    descriptors.Add(new DbiModuleDescriptor(ModuleInfoStream, this));
                }
                return(descriptors);
            });

            FileInfoStream = fileInfoStream;
            if (fileInfoStream.Length > 0)
            {
                // Header:
                //   ushort NumModules;
                //   ushort NumSourceFiles;
                // Following this header the File Info Substream is laid out as follows:
                //   ushort ModIndices[NumModules];
                //   ushort ModFileCounts[NumModules];
                //   uint FileNameOffsets[NumSourceFiles];
                //   char Names[][NumSourceFiles];
                // with the caveat that `NumSourceFiles` cannot be trusted, so
                // it is computed by summing the `ModFileCounts` array.
                ushort modulesCount           = fileInfoStream.ReadUshort();
                ushort headerSourceFilesCount = fileInfoStream.ReadUshort();

                // First is an array of `NumModules` module indices. This does not seem to be
                // used for anything meaningful, so we ignore it.
                ushort[] moduleIndexes = fileInfoStream.ReadUshortArray(modulesCount);

                ushort[] moduleFileCounts = fileInfoStream.ReadUshortArray(modulesCount);

                // Compute the real number of source files. We can't trust the value in
                // of headerSourceFilesCount because it is an ushort, and the sum of all
                // source file counts might be larger than an ushort. So we compute the real
                // count by summing up the individual counts.
                int sourceFilesCount = 0;

                for (int i = 0; i < moduleFileCounts.Length; i++)
                {
                    sourceFilesCount += moduleFileCounts[i];
                }

                // In the reference implementation, this array is where the pointer documented
                // at the definition of ModuleInfoHeader::FileNameOffs points to.  Note that
                // although the field in ModuleInfoHeader is ignored this array is not, as it
                // is the authority on where each filename begins in the names buffer.
                FileNameOffsets = fileInfoStream.ReadUintArray(sourceFilesCount);
                FileNamesStream = fileInfoStream.ReadSubstream();
                fileNameCache   = new DictionaryCache <uint, string>((uint namesOffset) =>
                {
                    FileNamesStream.Position = namesOffset;
                    return(FileNamesStream.ReadCString());
                });

                if (Modules.Count != modulesCount)
                {
                    throw new Exception("Inconsistent number of modules");
                }

                int nextFileIndex = 0;

                for (int i = 0; i < modulesCount; i++)
                {
                    Modules[i].StartingFileIndex = nextFileIndex;
                    nextFileIndex += moduleFileCounts[i];
                }
            }
        }
コード例 #30
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbStream"/> class.
        /// </summary>
        /// <param name="stream">PDB symbol stream.</param>
        public TpiStream(PdbStream stream)
        {
            Stream = stream;
            if (stream.Reader.BytesRemaining < TpiStreamHeader.Size)
            {
                throw new Exception("TPI Stream does not contain a header.");
            }
            Header = TpiStreamHeader.Read(stream.Reader);

            if (Header.Version != PdbTpiVersion.V80)
            {
                throw new Exception("Unsupported TPI Version.");
            }

            if (Header.HeaderSize != TpiStreamHeader.Size)
            {
                throw new Exception("Corrupt TPI Header size.");
            }

            if (Header.HashKeySize != 4) // 4 = sizeof(uint)
            {
                throw new Exception("TPI Stream expected 4 byte hash key size.");
            }

            if (Header.HashBucketsCount < MinTpiHashBuckets || Header.HashBucketsCount > MaxTpiHashBuckets)
            {
                throw new Exception("TPI Stream Invalid number of hash buckets.");
            }

            // The actual type records themselves come from this stream
            TypeRecordsSubStream          = Stream.Reader.ReadSubstream(Header.TypeRecordBytes);
            typeRecordsSubStreamPerThread = new System.Threading.ThreadLocal <IBinaryReader>(() => TypeRecordsSubStream.Duplicate());

            IBinaryReader reader = TypeRecordsSubStream;
            long          position = reader.Position, end = reader.Length;

            references = new List <RecordReference>();
            while (position < end)
            {
                RecordPrefix prefix = RecordPrefix.Read(reader);

                if (prefix.RecordLength < 2)
                {
                    throw new Exception("CV corrupt record");
                }

                TypeLeafKind kind    = (TypeLeafKind)prefix.RecordKind;
                ushort       dataLen = prefix.DataLen;

                references.Add(new RecordReference
                {
                    DataOffset = (uint)position + RecordPrefix.Size,
                    Kind       = kind,
                    DataLen    = dataLen,
                });
                position += dataLen + RecordPrefix.Size;
                reader.ReadFake(dataLen);
            }
            typesCache       = new ArrayCache <TypeRecord>(references.Count, true, ReadType);
            typesByKindCache = new DictionaryCache <TypeLeafKind, TypeRecord[]>(GetTypesByKind);

            // Hash indices, hash values, etc come from the hash stream.
            if (Header.HashStreamIndex != InvalidStreamIndex)
            {
                if (Header.HashStreamIndex >= Stream.File.Streams.Count)
                {
                    throw new Exception("Invalid TPI hash stream index.");
                }

                HashSubstream = Stream.File.Streams[Header.HashStreamIndex].Reader;
            }

            hashValuesCache = SimpleCache.CreateStruct(() =>
            {
                if (HashSubstream != null)
                {
                    // There should be a hash value for every type record, or no hashes at all.
                    uint numHashValues = Header.HashValueBuffer.Length / 4; // 4 = sizeof(uint)
                    if (numHashValues != references.Count && numHashValues != 0)
                    {
                        throw new Exception("TPI hash count does not match with the number of type records.");
                    }

                    HashSubstream.Position = Header.HashValueBuffer.Offset;
                    return(HashSubstream.ReadUintArray(references.Count));
                }
                return(null);
            });
            typeIndexOffsetsCache = SimpleCache.CreateStruct(() =>
            {
                if (HashSubstream != null)
                {
                    HashSubstream.Position             = Header.IndexOffsetBuffer.Offset;
                    uint numTypeIndexOffsets           = Header.IndexOffsetBuffer.Length / TypeIndexOffset.Size;
                    TypeIndexOffset[] typeIndexOffsets = new TypeIndexOffset[numTypeIndexOffsets];
                    for (uint i = 0; i < typeIndexOffsets.Length; i++)
                    {
                        typeIndexOffsets[i] = TypeIndexOffset.Read(HashSubstream);
                    }
                    return(typeIndexOffsets);
                }
                return(null);
            });
            hashAdjustersCache = SimpleCache.CreateStruct(() =>
            {
                if (HashSubstream != null && Header.HashAdjustersBuffer.Length > 0)
                {
                    HashSubstream.Position = Header.HashAdjustersBuffer.Offset;
                    return(new HashTable(HashSubstream));
                }
                return(null);
            });
        }