private static unsafe bool Load(string fileName, bool isBackup) { using (FileStream compressedStream = new(fileName, FileMode.Open)) using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true)) { OuterHeader outerHeader = DeserializeStructure <OuterHeader>(compressedStream); if (!outerHeader.IsHeaderValid()) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.Magic != _outerHeaderMagic) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.CacheFileVersion != InternalVersion) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.Endianness != GetEndianness()) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.FeatureInfo != GetFeatureInfo()) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.MemoryManagerMode != GetMemoryManagerMode()) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.OSPlatform != GetOSPlatform()) { InvalidateCompressedStream(compressedStream); return(false); } IntPtr intPtr = IntPtr.Zero; try { intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize)); using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite)) { try { deflateStream.CopyTo(stream); } catch { InvalidateCompressedStream(compressedStream); return(false); } Debug.Assert(stream.Position == stream.Length); stream.Seek(0L, SeekOrigin.Begin); InnerHeader innerHeader = DeserializeStructure <InnerHeader>(stream); if (!innerHeader.IsHeaderValid()) { InvalidateCompressedStream(compressedStream); return(false); } if (innerHeader.Magic != _innerHeaderMagic) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength); stream.Seek(innerHeader.InfosLength, SeekOrigin.Current); Hash128 infosHash = XXHash128.ComputeHash(infosBytes); if (innerHeader.InfosHash != infosHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan <byte> .Empty; stream.Seek(innerHeader.CodesLength, SeekOrigin.Current); Hash128 codesHash = XXHash128.ComputeHash(codesBytes); if (innerHeader.CodesHash != codesHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength); stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current); Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes); if (innerHeader.RelocsHash != relocsHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength); stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current); Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes); if (innerHeader.UnwindInfosHash != unwindInfosHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, innerHeader.PtcJumpTableLength); stream.Seek(innerHeader.PtcJumpTableLength, SeekOrigin.Current); Debug.Assert(stream.Position == stream.Length); Hash128 ptcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes); if (innerHeader.PtcJumpTableHash != ptcJumpTableHash) { InvalidateCompressedStream(compressedStream); return(false); } stream.Seek((long)Unsafe.SizeOf <InnerHeader>(), SeekOrigin.Begin); _infosStream.Write(infosBytes); stream.Seek(innerHeader.InfosLength, SeekOrigin.Current); _codesList.ReadFrom(stream); _relocsStream.Write(relocsBytes); stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current); _unwindInfosStream.Write(unwindInfosBytes); stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current); PtcJumpTable = PtcJumpTable.Deserialize(stream); Debug.Assert(stream.Position == stream.Length); } } finally { if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } } long fileSize = new FileInfo(fileName).Length; Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()})."); return(true); }
private static bool Load(string fileName, bool isBackup) { using (FileStream compressedStream = new(fileName, FileMode.Open)) using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true)) { OuterHeader outerHeader = DeserializeStructure <OuterHeader>(compressedStream); if (!outerHeader.IsHeaderValid()) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.Magic != _outerHeaderMagic) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.InfoFileVersion != InternalVersion) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.Endianness != Ptc.GetEndianness()) { InvalidateCompressedStream(compressedStream); return(false); } using (MemoryStream stream = new MemoryStream()) { Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); try { deflateStream.CopyTo(stream); } catch { InvalidateCompressedStream(compressedStream); return(false); } Debug.Assert(stream.Position == stream.Length); stream.Seek(0L, SeekOrigin.Begin); Hash128 expectedHash = DeserializeStructure <Hash128>(stream); Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream)); if (actualHash != expectedHash) { InvalidateCompressedStream(compressedStream); return(false); } ProfiledFuncs = Deserialize(stream); Debug.Assert(stream.Position == stream.Length); _lastHash = actualHash; } } long fileSize = new FileInfo(fileName).Length; Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count})."); return(true); }