/// <summary> /// Initializes a new instance of the <see cref="GlobalsStream"/> class. /// </summary> /// <param name="file">PDB file containing this stream.</param> /// <param name="reader">Binary stream reader.</param> public GlobalsStream(PdbFile file, IBinaryReader reader) { File = file; // Read header Header = GlobalsStreamHeader.Read(reader); if (Header.Signature != GlobalsStreamHeader.ExpectedSignature) { throw new Exception($"GSIHashHeader signature (0x{GlobalsStreamHeader.ExpectedSignature:X}) not found."); } if (Header.Version != GlobalsStreamHeader.ExpectedVersion) { throw new Exception("Encountered unsupported globals stream version."); } // Read hash records if (Header.HashRecordsSubstreamSize % GlobalsStreamHashRecord.Size != 0) { throw new Exception("Invalid hash record array size."); } if (reader.BytesRemaining < Header.HashRecordsSubstreamSize) { throw new Exception("Error reading hash records."); } GlobalsStreamHashRecord[] hashRecords = new GlobalsStreamHashRecord[Header.HashRecordsSubstreamSize / GlobalsStreamHashRecord.Size]; for (int i = 0; i < hashRecords.Length; i++) { hashRecords[i] = GlobalsStreamHashRecord.Read(reader); } HashRecords = hashRecords; // Read hash buckets if (Header.HashBucketsSubstreamSize > 0) { const uint IPHR_HASH = 4096; const uint SizeOfHROffsetCalc = 12; ulong bitmapSizeInBits = (IPHR_HASH / 32 + 1) * 32; int bitmapEntriesCount = (int)(bitmapSizeInBits / 8); if (reader.BytesRemaining < bitmapEntriesCount) { throw new Exception("Could not read a bitmap."); } byte[] hashBitmap = reader.ReadByteArray(bitmapEntriesCount); int nonEmptyBucketsCount = 0; for (int i = 0; i < hashBitmap.Length; i++) { nonEmptyBucketsCount += bitCount[hashBitmap[i]]; } if (reader.BytesRemaining < nonEmptyBucketsCount * 4) // 4 = sizeof(uint) { throw new Exception("Could not read a bitmap."); } uint[] nonEmptyBucketOffsets = reader.ReadUintArray(nonEmptyBucketsCount); GlobalsStreamHashBucket[] hashBuckets = new GlobalsStreamHashBucket[IPHR_HASH]; for (int i = 0, j = 0; i < IPHR_HASH; i++) { int byteIndex = i / 8; int bitIndex = i % 8; if ((hashBitmap[byteIndex] & (1 << bitIndex)) != 0) { uint start = nonEmptyBucketOffsets[j++] / SizeOfHROffsetCalc; uint end = j < nonEmptyBucketOffsets.Length ? nonEmptyBucketOffsets[j] / SizeOfHROffsetCalc : (uint)HashRecords.Length; hashBuckets[i] = new GlobalsStreamHashBucket { Start = (int)start, End = (int)end, }; } else { hashBuckets[i] = new GlobalsStreamHashBucket { Start = -1, End = -1, } }; } HashBuckets = hashBuckets; } Symbols = new ArrayCache <SymbolRecord>(HashRecords.Length, index => File.PdbSymbolStream.GetSymbolRecordByOffset(HashRecords[index].Offset - 1)); constantsCache = SimpleCache.CreateStruct(() => { List <ConstantSymbol> constants = new List <ConstantSymbol>(); for (int i = 0; i < Symbols.Count; i++) { ConstantSymbol constant = Symbols[i] as ConstantSymbol; if (constant != null) { constants.Add(constant); } } return(constants); }); threadLocalDataCache = SimpleCache.CreateStruct(() => { List <ThreadLocalDataSymbol> threadLocalData = new List <ThreadLocalDataSymbol>(); for (int i = 0; i < Symbols.Count; i++) { ThreadLocalDataSymbol tls = Symbols[i] as ThreadLocalDataSymbol; if (tls != null) { threadLocalData.Add(tls); } } return(threadLocalData); }); dataCache = SimpleCache.CreateStruct(() => { List <DataSymbol> data = new List <DataSymbol>(); for (int i = 0; i < Symbols.Count; i++) { DataSymbol d = Symbols[i] as DataSymbol; if (d != null) { data.Add(d); } } return(data); }); }
/// <summary> /// Initializes a new instance of the <see cref="PdbTypeThreadLocalStorage"/> class. /// </summary> /// <param name="containerType">Type that contains this field.</param> /// <param name="staticDataMemberRecord">The static data member record.</param> /// <param name="threadLocalData">The thread local data.</param> internal PdbTypeThreadLocalStorage(PdbUserDefinedType containerType, StaticDataMemberRecord staticDataMemberRecord, ThreadLocalDataSymbol threadLocalData) : base(containerType, staticDataMemberRecord) { ThreadLocalData = threadLocalData; }
/// <summary> /// Reads symbol record from symbol references for the specified index. /// </summary> /// <param name="index">Index of the symbol record.</param> private SymbolRecord GetSymbol(int index) { // Since DictionaryCache is allowing only single thread to call this function, we don't need to lock reader here. SymbolRecordReference reference = references[index]; Reader.Position = reference.DataOffset; switch (reference.Kind) { 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: return(ProcedureSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_PUB32: return(Public32Symbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_CONSTANT: case SymbolRecordKind.S_MANCONSTANT: return(ConstantSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_LDATA32: case SymbolRecordKind.S_GDATA32: case SymbolRecordKind.S_LMANDATA: case SymbolRecordKind.S_GMANDATA: return(DataSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_PROCREF: case SymbolRecordKind.S_LPROCREF: return(ProcedureReferenceSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_TOKENREF: return(TokenReferenceSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_UDT: case SymbolRecordKind.S_COBOLUDT: return(UdtSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_LTHREAD32: case SymbolRecordKind.S_GTHREAD32: return(ThreadLocalDataSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_GMANPROC: case SymbolRecordKind.S_LMANPROC: return(ManagedProcedureSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_BLOCK32: return(BlockSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_OEM: return(OemSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_UNAMESPACE: return(NamespaceSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_MANSLOT: return(AttributeSlotSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_END: case SymbolRecordKind.S_INLINESITE_END: return(EndSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_ANNOTATION: return(AnnotationSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_ANNOTATIONREF: return(AnnotationReferenceSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_REGREL32: return(RegisterRelativeSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_OBJNAME: return(ObjectNameSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_COMPILE2: return(Compile2Symbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_COMPILE3: return(Compile3Symbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_ENVBLOCK: return(EnvironmentBlockSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_BUILDINFO: return(BuildInfoSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_FRAMEPROC: return(FrameProcedureSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_LABEL32: return(LabelSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_HEAPALLOCSITE: return(HeapAllocationSiteSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_CALLSITEINFO: return(CallSiteInfoSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_FRAMECOOKIE: return(FrameCookieSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_THUNK32: return(Thunk32Symbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_LOCAL: return(LocalSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_DEFRANGE_REGISTER: return(DefRangeRegisterSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_DEFRANGE_REGISTER_REL: return(DefRangeRegisterRelativeSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_DEFRANGE_SUBFIELD_REGISTER: return(DefRangeSubfieldRegisterSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_DEFRANGE_FRAMEPOINTER_REL: return(DefRangeFramePointerRelativeSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: return(DefRangeFramePointerRelativeFullScopeSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_CALLEES: case SymbolRecordKind.S_CALLERS: return(FunctionListSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); case SymbolRecordKind.S_FILESTATIC: return(FileStaticSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_TRAMPOLINE: return(TrampolineSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_SECTION: return(SectionSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_COFFGROUP: return(CoffGroupSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_EXPORT: return(ExportSymbol.Read(Reader, this, index, reference.Kind)); case SymbolRecordKind.S_INLINESITE: return(InlineSiteSymbol.Read(Reader, this, index, reference.Kind, reference.DataLen)); default: #if DEBUG throw new NotImplementedException($"Unknown reference kind: {reference.Kind}"); #else return(null); #endif } }