internal static void LoadTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IntPtr pageTablePointer, JumpTable jumpTable) { if ((int)_infosStream.Length == 0 || (int)_codesStream.Length == 0 || (int)_relocsStream.Length == 0 || (int)_unwindInfosStream.Length == 0) { return; } Debug.Assert(funcs.Count == 0); _infosStream.Seek(0L, SeekOrigin.Begin); _codesStream.Seek(0L, SeekOrigin.Begin); _relocsStream.Seek(0L, SeekOrigin.Begin); _unwindInfosStream.Seek(0L, SeekOrigin.Begin); using (BinaryReader infosReader = new BinaryReader(_infosStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader codesReader = new BinaryReader(_codesStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader relocsReader = new BinaryReader(_relocsStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader unwindInfosReader = new BinaryReader(_unwindInfosStream, EncodingCache.UTF8NoBOM, true)) { int infosEntriesCount = (int)_infosStream.Length / InfoEntry.Stride; for (int i = 0; i < infosEntriesCount; i++) { InfoEntry infoEntry = ReadInfo(infosReader); byte[] code = ReadCode(codesReader, infoEntry.CodeLen); if (infoEntry.RelocEntriesCount != 0) { RelocEntry[] relocEntries = GetRelocEntries(relocsReader, infoEntry.RelocEntriesCount); PatchCode(code, relocEntries, pageTablePointer, jumpTable); } UnwindInfo unwindInfo = ReadUnwindInfo(unwindInfosReader); TranslatedFunction func = FastTranslate(code, unwindInfo, infoEntry.HighCq); funcs.AddOrUpdate((ulong)infoEntry.Address, func, (key, oldFunc) => func.HighCq && !oldFunc.HighCq ? func : oldFunc); } } if (_infosStream.Position < _infosStream.Length || _codesStream.Position < _codesStream.Length || _relocsStream.Position < _relocsStream.Length || _unwindInfosStream.Position < _unwindInfosStream.Length) { throw new Exception("Could not reach the end of one or more memory streams."); } jumpTable.Initialize(PtcJumpTable, funcs); PtcJumpTable.WriteJumpTable(jumpTable, funcs); PtcJumpTable.WriteDynamicTable(jumpTable); }
public void WriteUnwindInfo(UnwindInfo unwindInfo) { SerializeStructure(UnwindInfoStream, (int)unwindInfo.PushEntries.Length); foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries) { SerializeStructure(UnwindInfoStream, unwindPushEntry); } SerializeStructure(UnwindInfoStream, (int)unwindInfo.PrologSize); }
private static TranslatedFunction FastTranslate(byte[] code, UnwindInfo unwindInfo, bool highCq) { CompiledFunction cFunc = new CompiledFunction(code, unwindInfo); IntPtr codePtr = JitCache.Map(cFunc); GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer <GuestFunction>(codePtr); TranslatedFunction tFunc = new TranslatedFunction(gFunc, highCq); return(tFunc); }
private static void Add(int offset, int size, UnwindInfo unwindInfo) { CacheEntry entry = new CacheEntry(offset, size, unwindInfo); int index = _cacheEntries.BinarySearch(entry); if (index < 0) { index = ~index; } _cacheEntries.Insert(index, entry); }
public void WriteUnwindInfo(UnwindInfo unwindInfo) { _unwindInfoWriter.Write((int)unwindInfo.PushEntries.Length); foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries) { _unwindInfoWriter.Write((int)unwindPushEntry.PseudoOp); _unwindInfoWriter.Write((int)unwindPushEntry.PrologOffset); _unwindInfoWriter.Write((int)unwindPushEntry.RegIndex); _unwindInfoWriter.Write((int)unwindPushEntry.StackOffsetOrAllocSize); } _unwindInfoWriter.Write((int)unwindInfo.PrologSize); }
public void UnwindInfoConstructorWorks_Test() { var unwindInfo = new UnwindInfo(new BufferFile(RawStructures.RawUnwindInfo), 2); Assert.Equal((byte)0x1, unwindInfo.Version); Assert.Equal((byte)0x12, unwindInfo.Flags); Assert.Equal((byte)0x33, unwindInfo.SizeOfProlog); Assert.Equal((byte)0x5, unwindInfo.FrameRegister); Assert.Equal((byte)0x6, unwindInfo.FrameOffset); Assert.Single(unwindInfo.UnwindCode); Assert.Equal((byte)0x77, unwindInfo.UnwindCode[0].CodeOffset); Assert.Equal(UnwindOpType.SaveXmm128, unwindInfo.UnwindCode[0].UnwindOp); Assert.Equal((byte)0x9, unwindInfo.UnwindCode[0].Opinfo); Assert.Equal(0xffeeddcc, unwindInfo.ExceptionHandler); }
internal static void LoadTranslations( ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable, EntryTable <uint> countTable) { if (AreCarriersEmpty()) { return; } long infosStreamLength = _infosStream.Length; long relocsStreamLength = _relocsStream.Length; long unwindInfosStreamLength = _unwindInfosStream.Length; _infosStream.Seek(0L, SeekOrigin.Begin); _relocsStream.Seek(0L, SeekOrigin.Begin); _unwindInfosStream.Seek(0L, SeekOrigin.Begin); using (BinaryReader relocsReader = new(_relocsStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader unwindInfosReader = new(_unwindInfosStream, EncodingCache.UTF8NoBOM, true)) { for (int index = 0; index < GetEntriesCount(); index++) { InfoEntry infoEntry = DeserializeStructure <InfoEntry>(_infosStream); if (infoEntry.Stubbed) { SkipCode(index, infoEntry.CodeLength); SkipReloc(infoEntry.RelocEntriesCount); SkipUnwindInfo(unwindInfosReader); continue; } bool isEntryChanged = infoEntry.Hash != ComputeHash(memory, infoEntry.Address, infoEntry.GuestSize); if (isEntryChanged || (!infoEntry.HighCq && PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) && value.HighCq)) { infoEntry.Stubbed = true; infoEntry.CodeLength = 0; UpdateInfo(infoEntry); StubCode(index); StubReloc(infoEntry.RelocEntriesCount); StubUnwindInfo(unwindInfosReader); if (isEntryChanged) { PtcJumpTable.Clean(infoEntry.Address); Logger.Info?.Print(LogClass.Ptc, $"Invalidated translated function (address: 0x{infoEntry.Address:X16})"); } continue; } byte[] code = ReadCode(index, infoEntry.CodeLength); Counter <uint> callCounter = null; if (infoEntry.RelocEntriesCount != 0) { RelocEntry[] relocEntries = GetRelocEntries(relocsReader, infoEntry.RelocEntriesCount); PatchCode(code, relocEntries, memory.PageTablePointer, jumpTable, countTable, out callCounter); } UnwindInfo unwindInfo = ReadUnwindInfo(unwindInfosReader); TranslatedFunction func = FastTranslate(code, callCounter, infoEntry.GuestSize, unwindInfo, infoEntry.HighCq); bool isAddressUnique = funcs.TryAdd(infoEntry.Address, func); Debug.Assert(isAddressUnique, $"The address 0x{infoEntry.Address:X16} is not unique."); } } if (_infosStream.Length != infosStreamLength || _infosStream.Position != infosStreamLength || _relocsStream.Length != relocsStreamLength || _relocsStream.Position != relocsStreamLength || _unwindInfosStream.Length != unwindInfosStreamLength || _unwindInfosStream.Position != unwindInfosStreamLength) { throw new Exception("The length of a memory stream has changed, or its position has not reached or has exceeded its end."); } jumpTable.Initialize(PtcJumpTable, funcs); PtcJumpTable.WriteJumpTable(jumpTable, funcs); PtcJumpTable.WriteDynamicTable(jumpTable); Logger.Info?.Print(LogClass.Ptc, $"{funcs.Count} translated functions loaded"); }
public JitCacheEntry(int offset, int size, UnwindInfo unwindInfo) { Offset = offset; Size = size; UnwindInfo = unwindInfo; }
internal static void LoadTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable) { if ((int)_infosStream.Length == 0 || (int)_codesStream.Length == 0 || (int)_relocsStream.Length == 0 || (int)_unwindInfosStream.Length == 0) { return; } Debug.Assert(funcs.Count == 0); _infosStream.Seek(0L, SeekOrigin.Begin); _codesStream.Seek(0L, SeekOrigin.Begin); _relocsStream.Seek(0L, SeekOrigin.Begin); _unwindInfosStream.Seek(0L, SeekOrigin.Begin); using (BinaryReader infosReader = new BinaryReader(_infosStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader codesReader = new BinaryReader(_codesStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader relocsReader = new BinaryReader(_relocsStream, EncodingCache.UTF8NoBOM, true)) using (BinaryReader unwindInfosReader = new BinaryReader(_unwindInfosStream, EncodingCache.UTF8NoBOM, true)) { for (int i = 0; i < GetInfosEntriesCount(); i++) { InfoEntry infoEntry = ReadInfo(infosReader); if (infoEntry.Stubbed) { SkipCode(infoEntry.CodeLen); SkipReloc(infoEntry.RelocEntriesCount); SkipUnwindInfo(unwindInfosReader); } else if (infoEntry.HighCq || !PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) || !value.highCq) { byte[] code = ReadCode(codesReader, infoEntry.CodeLen); if (infoEntry.RelocEntriesCount != 0) { RelocEntry[] relocEntries = GetRelocEntries(relocsReader, infoEntry.RelocEntriesCount); PatchCode(code, relocEntries, memory.PageTablePointer, jumpTable); } UnwindInfo unwindInfo = ReadUnwindInfo(unwindInfosReader); TranslatedFunction func = FastTranslate(code, infoEntry.GuestSize, unwindInfo, infoEntry.HighCq); bool isAddressUnique = funcs.TryAdd(infoEntry.Address, func); Debug.Assert(isAddressUnique, $"The address 0x{infoEntry.Address:X16} is not unique."); } else { infoEntry.Stubbed = true; UpdateInfo(infoEntry); StubCode(infoEntry.CodeLen); StubReloc(infoEntry.RelocEntriesCount); StubUnwindInfo(unwindInfosReader); } } } if (_infosStream.Position < _infosStream.Length || _codesStream.Position < _codesStream.Length || _relocsStream.Position < _relocsStream.Length || _unwindInfosStream.Position < _unwindInfosStream.Length) { throw new Exception("Could not reach the end of one or more memory streams."); } jumpTable.Initialize(PtcJumpTable, funcs); PtcJumpTable.WriteJumpTable(jumpTable, funcs); PtcJumpTable.WriteDynamicTable(jumpTable); Logger.Info?.Print(LogClass.Ptc, $"{funcs.Count} translated functions loaded"); }
public CompiledFunction(byte[] code, UnwindInfo unwindInfo) { Code = code; UnwindInfo = unwindInfo; }
/// <summary> /// Initializes a new instance of the <see cref="CompiledFunction"/> struct with the specified machine code, /// unwind info and relocation info. /// </summary> /// <param name="code">Machine code</param> /// <param name="unwindInfo">Unwind info</param> /// <param name="relocInfo">Relocation info</param> internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo) { Code = code; UnwindInfo = unwindInfo; RelocInfo = relocInfo; }
private static TranslatedFunction FastTranslate(ReadOnlySpan <byte> code, ulong guestSize, UnwindInfo unwindInfo, bool highCq) { CompiledFunction cFunc = new CompiledFunction(code.ToArray(), unwindInfo); IntPtr codePtr = JitCache.Map(cFunc); GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer <GuestFunction>(codePtr); TranslatedFunction tFunc = new TranslatedFunction(gFunc, guestSize, highCq); return(tFunc); }
public CacheEntry(uint offset, uint size, UnwindInfo unwindInfo) { Offset = offset; Size = size; UnwindInfo = unwindInfo; }