Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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");
        }
Beispiel #8
0
 public JitCacheEntry(int offset, int size, UnwindInfo unwindInfo)
 {
     Offset     = offset;
     Size       = size;
     UnwindInfo = unwindInfo;
 }
Beispiel #9
0
        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");
        }
Beispiel #10
0
 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;
 }
Beispiel #12
0
        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);
        }
Beispiel #13
0
 public CacheEntry(uint offset, uint size, UnwindInfo unwindInfo)
 {
     Offset     = offset;
     Size       = size;
     UnwindInfo = unwindInfo;
 }