示例#1
0
文件: Ptc.cs 项目: historria/Ryujinx
        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");
        }
示例#2
0
文件: Ptc.cs 项目: ianuub/Ryujinxxx
        internal static void LoadTranslations(ConcurrentDictionary <ulong, TranslatedFunction> funcs, IMemoryManager memory, JumpTable jumpTable)
        {
            if (AreMemoryStreamsEmpty())
            {
                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(_infosStream, EncodingCache.UTF8NoBOM, true))
                using (BinaryReader codesReader = new(_codesStream, EncodingCache.UTF8NoBOM, true))
                    using (BinaryReader relocsReader = new(_relocsStream, EncodingCache.UTF8NoBOM, true))
                        using (BinaryReader unwindInfosReader = new(_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);

                                    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;
                                    UpdateInfo(infoEntry);

                                    StubCode(infoEntry.CodeLen);
                                    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;
                                }

                                Span <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.");
                            }
                        }

            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");
        }