Exemple #1
0
        internal static void MakeAndSaveTranslations(
            ConcurrentDictionary <ulong, TranslatedFunction> funcs,
            IMemoryManager memory,
            JumpTable jumpTable,
            EntryTable <uint> countTable)
        {
            var profiledFuncsToTranslate = PtcProfiler.GetProfiledFuncsToTranslate(funcs);

            _translateCount      = 0;
            _translateTotalCount = profiledFuncsToTranslate.Count;

            int degreeOfParallelism = new DegreeOfParallelism(4d, 75d, 12.5d).GetDegreeOfParallelism(0, 32);

            if (_translateTotalCount == 0 || degreeOfParallelism == 0)
            {
                ResetCarriersIfNeeded();
                PtcJumpTable.ClearIfNeeded();

                GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;

                return;
            }

            Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism}");

            PtcStateChanged?.Invoke(PtcLoadingState.Start, _translateCount, _translateTotalCount);

            using AutoResetEvent progressReportEvent = new AutoResetEvent(false);

            Thread progressReportThread = new Thread(ReportProgress)
            {
                Name         = "Ptc.ProgressReporter",
                Priority     = ThreadPriority.Lowest,
                IsBackground = true
            };

            progressReportThread.Start(progressReportEvent);

            void TranslateFuncs()
            {
                while (profiledFuncsToTranslate.TryDequeue(out var item))
                {
                    ulong address = item.address;

                    Debug.Assert(PtcProfiler.IsAddressInStaticCodeRange(address));

                    TranslatedFunction func = Translator.Translate(memory, jumpTable, countTable, address, item.mode, item.highCq);

                    bool isAddressUnique = funcs.TryAdd(address, func);

                    Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");

                    if (func.HighCq)
                    {
                        jumpTable.RegisterFunction(address, func);
                    }

                    Interlocked.Increment(ref _translateCount);

                    if (State != PtcState.Enabled)
                    {
                        break;
                    }
                }

                Translator.DisposePools();
            }

            List <Thread> threads = new List <Thread>();

            for (int i = 0; i < degreeOfParallelism; i++)
            {
                Thread thread = new Thread(TranslateFuncs);
                thread.IsBackground = true;

                threads.Add(thread);
            }

            threads.ForEach((thread) => thread.Start());
            threads.ForEach((thread) => thread.Join());

            threads.Clear();

            progressReportEvent.Set();
            progressReportThread.Join();

            PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount);

            Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism}");

            PtcJumpTable.Initialize(jumpTable);

            PtcJumpTable.ReadJumpTable(jumpTable);
            PtcJumpTable.ReadDynamicTable(jumpTable);

            Thread preSaveThread = new Thread(PreSave);

            preSaveThread.IsBackground = true;
            preSaveThread.Start();
        }
Exemple #2
0
        internal static void LoadTranslations(
            ConcurrentDictionary <ulong, TranslatedFunction> funcs,
            IMemoryManager memory,
            JumpTable jumpTable,
            EntryTable <uint> countTable)
        {
            if (AreCarriersEmpty())
            {
                return;
            }

            _infosStream.Seek(0L, SeekOrigin.Begin);
            _relocsStream.Seek(0L, SeekOrigin.Begin);
            _unwindInfosStream.Seek(0L, SeekOrigin.Begin);

            using (BinaryReader infosReader = new(_infosStream, EncodingCache.UTF8NoBOM, true))
                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 = ReadInfo(infosReader);

                            if (infoEntry.Stubbed)
                            {
                                SkipCode(index, infoEntry.CodeLength);
                                SkipReloc(infoEntry.RelocEntriesCount);
                                SkipUnwindInfo(unwindInfosReader);
                            }
                            else if (infoEntry.HighCq || !PtcProfiler.ProfiledFuncs.TryGetValue(infoEntry.Address, out var value) || !value.HighCq)
                            {
                                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.");
                            }
                            else
                            {
                                infoEntry.Stubbed    = true;
                                infoEntry.CodeLength = 0;
                                UpdateInfo(infoEntry);

                                StubCode(index);
                                StubReloc(infoEntry.RelocEntriesCount);
                                StubUnwindInfo(unwindInfosReader);
                            }
                        }
                    }

            if (_infosStream.Position < _infosStream.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 void ThenTheAccountWithNumberShouldContainTheseEntries(string accountNumber, EntryTable expectedEntries)
    {
      EntryRow[] expectedRows = expectedEntries.Entries.ToArray();
      Entry[] actualEntries = CurrentScenarioContext.EasyBankContext[accountNumber].Entries.ToArray();

      Assert.AreEqual(expectedRows.Length, actualEntries.Length);

      for (int i = 0; i < expectedRows.Length; i++)
      {
        AssertEntry(expectedRows[i], actualEntries[i], i);
      }
    }
Exemple #4
0
        private static bool PatchCode(Span <byte> code, RelocEntry[] relocEntries, IntPtr pageTablePointer, JumpTable jumpTable, EntryTable <byte> countTable, out Counter callCounter)
        {
            callCounter = null;

            foreach (RelocEntry relocEntry in relocEntries)
            {
                ulong imm;

                if (relocEntry.Index == PageTablePointerIndex)
                {
                    imm = (ulong)pageTablePointer.ToInt64();
                }
                else if (relocEntry.Index == JumpPointerIndex)
                {
                    imm = (ulong)jumpTable.JumpPointer.ToInt64();
                }
                else if (relocEntry.Index == DynamicPointerIndex)
                {
                    imm = (ulong)jumpTable.DynamicPointer.ToInt64();
                }
                else if (relocEntry.Index == CountTableIndex)
                {
                    // If we could not allocate an entry on the count table we dip.
                    if (!Counter.TryCreate(countTable, out Counter counter))
                    {
                        return(false);
                    }

                    unsafe { imm = (ulong)Unsafe.AsPointer(ref counter.Value); }
                }
                else if (Delegates.TryGetDelegateFuncPtrByIndex(relocEntry.Index, out IntPtr funcPtr))
                {
                    imm = (ulong)funcPtr.ToInt64();
                }
                else
                {
                    throw new Exception($"Unexpected reloc entry {relocEntry}.");
                }

                BinaryPrimitives.WriteUInt64LittleEndian(code.Slice(relocEntry.Position, 8), imm);
            }

            return(true);
        }
Exemple #5
0
 void Awake()
 {
     self = this;
 }
Exemple #6
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");
        }