예제 #1
0
        private void Test(TpiStream tpiStream)
        {
            Assert.Equal(tpiStream.TypeRecordCount, tpiStream.references.Count);
            Assert.NotEmpty(tpiStream.HashValues);
            if (tpiStream.HashAdjusters != null)
            {
                Assert.NotEmpty(tpiStream.HashAdjusters.Dictionary);
            }

            // Verify that type offsets are correct in references array
            foreach (TypeIndexOffset offset in tpiStream.TypeIndexOffsets)
            {
                var reference = tpiStream.references[(int)offset.Type.ArrayIndex];
                Assert.Equal(offset.Offset, reference.DataOffset - RecordPrefix.Size);
            }

            // Verify that all types can be read
            for (int i = 0; i < tpiStream.references.Count; i++)
            {
                Assert.NotNull(tpiStream[TypeIndex.FromArrayIndex(i)]);
            }

            // Check that getting types by kind works correctly
            TypeLeafKind[] kinds = tpiStream.references.Select(r => r.Kind).Distinct().ToArray();

            foreach (TypeLeafKind kind in kinds)
            {
                Assert.Equal(tpiStream.references.Count(r => r.Kind == kind), tpiStream[kind].Length);
            }
        }
예제 #2
0
        public void ToStringTest()
        {
            TypeIndex typeIndexByte    = new TypeIndex(SimpleTypeKind.Byte, SimpleTypeMode.Direct);
            TypeIndex typeIndexArray10 = TypeIndex.FromArrayIndex(10);

            Assert.NotNull(typeIndexByte.ToString());
            Assert.NotNull(typeIndexArray10.ToString());
        }
예제 #3
0
        public void ArrayIndex()
        {
            TypeIndex typeIndex = TypeIndex.FromArrayIndex(10);

            Assert.False(typeIndex.IsSimple);
            Assert.False(typeIndex.IsNoneType);
            Assert.Equal(10U, typeIndex.ArrayIndex);
        }
예제 #4
0
 /// <summary>
 /// Gets all type indexes for the specified type record kind.
 /// </summary>
 /// <param name="kind">Type record kind.</param>
 public IEnumerable <TypeIndex> GetIndexes(TypeLeafKind kind)
 {
     for (int i = 0; i < references.Count; i++)
     {
         if (references[i].Kind == kind)
         {
             yield return(TypeIndex.FromArrayIndex(i));
         }
     }
 }
예제 #5
0
        private void ReadTpiStream(TpiStream tpiStream)
        {
            if (tpiStream.HashSubstream != null)
            {
                Assert.NotNull(tpiStream.HashValues);
                Assert.NotEmpty(tpiStream.TypeIndexOffsets);
            }
            else
            {
                Assert.Null(tpiStream.HashValues);
                Assert.Null(tpiStream.TypeIndexOffsets);
            }
            if (tpiStream.HashSubstream != null && tpiStream.Header.HashAdjustersBuffer.Length > 0)
            {
                Assert.NotNull(tpiStream.HashAdjusters);
            }
            else
            {
                Assert.Null(tpiStream.HashAdjusters);
            }
            var references = tpiStream.References;

            Assert.NotNull(references);
            Assert.Equal(references.Count, tpiStream.TypeRecordCount);
            for (int i = 0; i < references.Count; i++)
            {
                Assert.NotNull(tpiStream[TypeIndex.FromArrayIndex(i)]);
            }
            var kinds = references.Select(r => r.Kind).Distinct().ToArray();

            foreach (var kind in kinds)
            {
                Assert.NotEmpty(tpiStream.GetIndexes(kind));
                Assert.NotEmpty(tpiStream[kind]);
            }

            // Check type record kinds
            var allKinds = new[]
            {
                ArgumentListRecord.Kinds,
                ArrayRecord.Kinds,
                BaseClassRecord.Kinds,
                BitFieldRecord.Kinds,
                BuildInfoRecord.Kinds,
                ClassRecord.Kinds,
                DataMemberRecord.Kinds,
                EnumeratorRecord.Kinds,
                EnumRecord.Kinds,
                FieldListRecord.Kinds,
                FunctionIdRecord.Kinds,
                LabelRecord.Kinds,
                ListContinuationRecord.Kinds,
                MemberFunctionIdRecord.Kinds,
                MemberFunctionRecord.Kinds,
                MethodOverloadListRecord.Kinds,
                ModifierRecord.Kinds,
                NestedTypeRecord.Kinds,
                OneMethodRecord.Kinds,
                OverloadedMethodRecord.Kinds,
                PointerRecord.Kinds,
                StaticDataMemberRecord.Kinds,
                StringIdRecord.Kinds,
                StringListRecord.Kinds,
                UdtModuleSourceLineRecord.Kinds,
                UnionRecord.Kinds,
                VirtualBaseClassRecord.Kinds,
                VirtualFunctionPointerRecord.Kinds,
                VirtualFunctionTableShapeRecord.Kinds,
            };

            if (references.Count > 0)
            {
                Assert.NotEmpty(allKinds.SelectMany(ka => ka.SelectMany(k => tpiStream[k])));
            }
        }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFileReader"/> class.
        /// </summary>
        /// <param name="pdbFile">Opened PDB file.</param>
        private PdbFileReader(PdbFile pdbFile)
        {
            PdbFile               = pdbFile;
            typesByIndex          = new DictionaryCache <TypeIndex, PdbType>(CreateType);
            userDefinedTypesCache = SimpleCache.CreateStruct(() =>
            {
                List <PdbType> types        = new List <PdbType>();
                var references              = PdbFile.TpiStream.References;
                TypeLeafKind[] allowedKinds = ClassRecord.Kinds.Concat(UnionRecord.Kinds).Concat(EnumRecord.Kinds).ToArray();

                for (int i = 0; i < references.Count; i++)
                {
                    if (allowedKinds.Contains(references[i].Kind))
                    {
                        TypeIndex typeIndex   = TypeIndex.FromArrayIndex(i);
                        TypeRecord typeRecord = PdbFile.TpiStream[typeIndex];
                        PdbType pdbType       = typesByIndex[typeIndex];

                        if (typeRecord is TagRecord tagRecord)
                        {
                            // Check if it is forward reference and if it has been resolved.
                            PdbUserDefinedType pdbUserDefinedType = (PdbUserDefinedType)pdbType;

                            if (pdbUserDefinedType.TagRecord != tagRecord)
                            {
                                continue;
                            }
                        }
                        types.Add(pdbType);
                    }
                }
                return((IReadOnlyList <PdbType>)types);
            });
            globalVarablesCache = SimpleCache.CreateStruct(() =>
            {
                var data = PdbFile.GlobalsStream.Data;
                PdbGlobalVariable[] globalVariables = new PdbGlobalVariable[data.Count];

                for (int i = 0; i < data.Count; i++)
                {
                    globalVariables[i] = new PdbGlobalVariable(this, data[i]);
                }
                return(globalVariables);
            });
            publicSymbolsCache = SimpleCache.CreateStruct(() =>
            {
                PdbPublicSymbol[] publicSymbols = new PdbPublicSymbol[PdbFile.PublicsStream.PublicSymbols.Count];

                for (int i = 0; i < publicSymbols.Length; i++)
                {
                    publicSymbols[i] = new PdbPublicSymbol(this, PdbFile.PublicsStream.PublicSymbols[i]);
                }
                return(publicSymbols);
            });
            functionsCache = SimpleCache.CreateStruct(() =>
            {
                List <PdbFunction> functions = new List <PdbFunction>();
                var references = PdbFile.PdbSymbolStream?.References;
                var modules    = PdbFile.DbiStream?.Modules;

                if (references != null && modules != null)
                {
                    HashSet <uint>[] selectedFunctions = new HashSet <uint> [modules.Count];

                    for (int i = 0; i < references.Count; i++)
                    {
                        ProcedureSymbol procedure = null;

                        switch (references[i].Kind)
                        {
                        // ProcedureSymbol
                        case SymbolRecordKind.S_GPROC32:
                        case SymbolRecordKind.S_LPROC32:
                        case SymbolRecordKind.S_GPROC32_ID:
                        case SymbolRecordKind.S_LPROC32_ID:
                        case SymbolRecordKind.S_LPROC32_DPC:
                        case SymbolRecordKind.S_LPROC32_DPC_ID:
                            procedure = PdbFile.PdbSymbolStream[i] as ProcedureSymbol;
                            break;

                        // ProcedureReferenceSymbol
                        case SymbolRecordKind.S_PROCREF:
                        case SymbolRecordKind.S_LPROCREF:
                            {
                                ProcedureReferenceSymbol procedureReference = PdbFile.PdbSymbolStream[i] as ProcedureReferenceSymbol;
                                int moduleIndex = procedureReference.Module - 1;

                                if (moduleIndex >= 0 && moduleIndex < modules.Count)
                                {
                                    var module = modules[moduleIndex];

                                    if (selectedFunctions[moduleIndex] == null)
                                    {
                                        selectedFunctions[moduleIndex] = new HashSet <uint>();
                                    }
                                    if (!selectedFunctions[moduleIndex].Contains(procedureReference.Offset) &&
                                        module.LocalSymbolStream.TryGetSymbolRecordByOffset(procedureReference.Offset, out SymbolRecord procedureSymbol))
                                    {
                                        procedure = procedureSymbol as ProcedureSymbol;
                                        selectedFunctions[moduleIndex].Add(procedureReference.Offset);
                                    }
                                }
                            }
                            break;
                        }

                        if (procedure != null)
                        {
                            functions.Add(new PdbFunction(this, procedure));
                        }
                    }
                }
                return(functions);
            });
        }
예제 #7
0
        private static void TestUdts(IDiaSession diaSession, PdbFile pdb)
        {
            // Extract all udts from PDB
            var typeRecordReferences        = pdb.TpiStream.References;
            List <ClassRecord> classRecords = new List <ClassRecord>();
            List <UnionRecord> unionRecords = new List <UnionRecord>();

            for (int i = 0; i < typeRecordReferences.Count; i++)
            {
                if (ClassRecord.Kinds.Contains(typeRecordReferences[i].Kind))
                {
                    classRecords.Add((ClassRecord)pdb.TpiStream[TypeIndex.FromArrayIndex(i)]);
                }
                else if (UnionRecord.Kinds.Contains(typeRecordReferences[i].Kind))
                {
                    unionRecords.Add((UnionRecord)pdb.TpiStream[TypeIndex.FromArrayIndex(i)]);
                }
            }

            // Extract UDTs from DIA
            IDiaSymbol[]     udts        = diaSession.globalScope.GetChildren(SymTagEnum.UDT).ToArray();
            HashSet <string> checkedUdts = new HashSet <string>();
            List <Tuple <uint, TypeRecord> > checkedTypes = new List <Tuple <uint, TypeRecord> >();

            foreach (IDiaSymbol udt in udts)
            {
                string name = udt.name;

                if (udt.length > 0 && !checkedUdts.Contains(name))
                {
                    UdtKind   udtKind = (UdtKind)udt.udtKind;
                    TagRecord record;

                    if (udtKind == UdtKind.Union)
                    {
                        UnionRecord unionRecord = unionRecords.FirstOrDefault(cr => !cr.IsForwardReference && cr.Name.String == name);

                        if (unionRecord == null)
                        {
                            unionRecord = unionRecords.FirstOrDefault(cr => cr.Name.String == name);
                        }
                        Assert.NotNull(unionRecord);
                        record = unionRecord;
                    }
                    else
                    {
                        ClassRecord classRecord = classRecords.FirstOrDefault(cr => !cr.IsForwardReference && cr.Name.String == name);

                        if (classRecord == null)
                        {
                            classRecord = classRecords.FirstOrDefault(cr => cr.Name.String == name);
                        }
                        Assert.NotNull(classRecord);
                        record = classRecord;
                    }

                    CompareTypes(udt, pdb, record, checkedTypes);
                    checkedUdts.Add(name);
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Creates new <see cref="PdbSymbol"/> for the specified type index.
        /// </summary>
        /// <param name="index">Type index in the TPI stream.</param>
        private PdbSymbol CreateSymbol(int index)
        {
            TypeIndex typeIndex = TypeIndex.FromArrayIndex(index);

            return(new PdbSymbol(this, typeIndex.Index, PdbFile.TpiStream[typeIndex]));
        }