mirror of
				https://github.com/ryujinx-mirror/ryujinx.git
				synced 2025-11-04 08:18:58 -06:00 
			
		
		
		
	Allow access to code memory for exefs mods (#5518)
* Allow access to code memory for exefs mods * Add ASLR workaround for Skyline * Hardcode allowCodeMemoryForJit to true
This commit is contained in:
		@@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
        private const string OuterHeaderMagicString = "PTCohd\0\0";
 | 
			
		||||
        private const string InnerHeaderMagicString = "PTCihd\0\0";
 | 
			
		||||
 | 
			
		||||
        private const uint InternalVersion = 5502; //! To be incremented manually for each change to the ARMeilleure project.
 | 
			
		||||
        private const uint InternalVersion = 5518; //! To be incremented manually for each change to the ARMeilleure project.
 | 
			
		||||
 | 
			
		||||
        private const string ActualDir = "0";
 | 
			
		||||
        private const string BackupDir = "1";
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,26 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
            return dictionary;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
        public static Dictionary<TKey, TValue> DeserializeAndUpdateDictionary<TKey, TValue>(Stream stream, Func<Stream, TValue> valueFunc, Func<TKey, TValue, (TKey, TValue)> updateFunc) where TKey : struct
 | 
			
		||||
        {
 | 
			
		||||
            Dictionary<TKey, TValue> dictionary = new();
 | 
			
		||||
 | 
			
		||||
            int count = DeserializeStructure<int>(stream);
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                TKey key = DeserializeStructure<TKey>(stream);
 | 
			
		||||
                TValue value = valueFunc(stream);
 | 
			
		||||
 | 
			
		||||
                (key, value) = updateFunc(key, value);
 | 
			
		||||
 | 
			
		||||
                dictionary.Add(key, value);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return dictionary;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
        public static List<T> DeserializeList<T>(Stream stream) where T : struct
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,10 +9,13 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.IO.Compression;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Timers;
 | 
			
		||||
using static ARMeilleure.Translation.PTC.PtcFormatter;
 | 
			
		||||
using Timer = System.Timers.Timer;
 | 
			
		||||
 | 
			
		||||
namespace ARMeilleure.Translation.PTC
 | 
			
		||||
{
 | 
			
		||||
@@ -20,7 +23,11 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
    {
 | 
			
		||||
        private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
 | 
			
		||||
 | 
			
		||||
        private const uint InternalVersion = 1866; //! Not to be incremented manually for each change to the ARMeilleure project.
 | 
			
		||||
        private const uint InternalVersion = 5518; //! Not to be incremented manually for each change to the ARMeilleure project.
 | 
			
		||||
 | 
			
		||||
        private static readonly uint[] _migrateInternalVersions = {
 | 
			
		||||
            1866,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        private const int SaveInterval = 30; // Seconds.
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +35,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
 | 
			
		||||
        private readonly Ptc _ptc;
 | 
			
		||||
 | 
			
		||||
        private readonly System.Timers.Timer _timer;
 | 
			
		||||
        private readonly Timer _timer;
 | 
			
		||||
 | 
			
		||||
        private readonly ulong _outerHeaderMagic;
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +58,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
        {
 | 
			
		||||
            _ptc = ptc;
 | 
			
		||||
 | 
			
		||||
            _timer = new System.Timers.Timer((double)SaveInterval * 1000d);
 | 
			
		||||
            _timer = new Timer(SaveInterval * 1000d);
 | 
			
		||||
            _timer.Elapsed += PreSave;
 | 
			
		||||
 | 
			
		||||
            _outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
 | 
			
		||||
@@ -168,7 +175,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (outerHeader.InfoFileVersion != InternalVersion)
 | 
			
		||||
                if (outerHeader.InfoFileVersion != InternalVersion && !_migrateInternalVersions.Contains(outerHeader.InfoFileVersion))
 | 
			
		||||
                {
 | 
			
		||||
                    InvalidateCompressedStream(compressedStream);
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +218,19 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ProfiledFuncs = Deserialize(stream);
 | 
			
		||||
                switch (outerHeader.InfoFileVersion)
 | 
			
		||||
                {
 | 
			
		||||
                    case InternalVersion:
 | 
			
		||||
                        ProfiledFuncs = Deserialize(stream);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 1866:
 | 
			
		||||
                        ProfiledFuncs = Deserialize(stream, (address, profile) => (address + 0x500000UL, profile));
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        Logger.Error?.Print(LogClass.Ptc, $"No migration path for {nameof(outerHeader.InfoFileVersion)} '{outerHeader.InfoFileVersion}'. Discarding cache.");
 | 
			
		||||
                        InvalidateCompressedStream(compressedStream);
 | 
			
		||||
                        return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Debug.Assert(stream.Position == stream.Length);
 | 
			
		||||
 | 
			
		||||
@@ -225,9 +244,14 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Dictionary<ulong, FuncProfile> Deserialize(Stream stream)
 | 
			
		||||
        private static Dictionary<ulong, FuncProfile> Deserialize(Stream stream, Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null)
 | 
			
		||||
        {
 | 
			
		||||
            return DeserializeDictionary<ulong, FuncProfile>(stream, (stream) => DeserializeStructure<FuncProfile>(stream));
 | 
			
		||||
            if (migrateEntryFunc != null)
 | 
			
		||||
            {
 | 
			
		||||
                return DeserializeAndUpdateDictionary(stream, DeserializeStructure<FuncProfile>, migrateEntryFunc);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return DeserializeDictionary<ulong, FuncProfile>(stream, DeserializeStructure<FuncProfile>);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
 | 
			
		||||
@@ -240,7 +264,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
            compressedStream.SetLength(0L);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void PreSave(object source, System.Timers.ElapsedEventArgs e)
 | 
			
		||||
        private void PreSave(object source, ElapsedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            _waitEvent.Reset();
 | 
			
		||||
 | 
			
		||||
@@ -277,7 +301,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);
 | 
			
		||||
 | 
			
		||||
                stream.Seek((long)Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin);
 | 
			
		||||
                stream.Seek(Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin);
 | 
			
		||||
 | 
			
		||||
                lock (_lock)
 | 
			
		||||
                {
 | 
			
		||||
@@ -288,7 +312,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
 | 
			
		||||
                Debug.Assert(stream.Position == stream.Length);
 | 
			
		||||
 | 
			
		||||
                stream.Seek((long)Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin);
 | 
			
		||||
                stream.Seek(Unsafe.SizeOf<Hash128>(), SeekOrigin.Begin);
 | 
			
		||||
                Hash128 hash = XXHash128.ComputeHash(GetReadOnlySpan(stream));
 | 
			
		||||
 | 
			
		||||
                stream.Seek(0L, SeekOrigin.Begin);
 | 
			
		||||
@@ -332,7 +356,7 @@ namespace ARMeilleure.Translation.PTC
 | 
			
		||||
 | 
			
		||||
        private static void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
 | 
			
		||||
        {
 | 
			
		||||
            SerializeDictionary(stream, profiledFuncs, (stream, structure) => SerializeStructure(stream, structure));
 | 
			
		||||
            SerializeDictionary(stream, profiledFuncs, SerializeStructure);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 29*/)]
 | 
			
		||||
 
 | 
			
		||||
@@ -89,9 +89,6 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
 | 
			
		||||
                Logger.Warning?.Print(LogClass.Ptc, "Detected unsupported ExeFs modifications. PTC disabled.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // We allow it for nx-hbloader because it can be used to launch homebrew.
 | 
			
		||||
            bool allowCodeMemoryForJit = programId == 0x010000000000100DUL || isHomebrew;
 | 
			
		||||
 | 
			
		||||
            string programName = "";
 | 
			
		||||
 | 
			
		||||
            if (!isHomebrew && programId > 0x010000000000FFFF)
 | 
			
		||||
@@ -119,7 +116,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
 | 
			
		||||
                metaLoader,
 | 
			
		||||
                nacpData,
 | 
			
		||||
                enablePtc,
 | 
			
		||||
                allowCodeMemoryForJit,
 | 
			
		||||
                true,
 | 
			
		||||
                programName,
 | 
			
		||||
                metaLoader.GetProgramId(),
 | 
			
		||||
                null,
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,11 @@ namespace Ryujinx.HLE.Loaders.Processes
 | 
			
		||||
{
 | 
			
		||||
    static class ProcessLoaderHelper
 | 
			
		||||
    {
 | 
			
		||||
        // NOTE: If you want to change this value make sure to increment the InternalVersion of Ptc and PtcProfiler.
 | 
			
		||||
        //       You also need to add a new migration path and adjust the existing ones.
 | 
			
		||||
        // TODO: Remove this workaround when ASLR is implemented.
 | 
			
		||||
        private const ulong CodeStartOffset = 0x500000UL;
 | 
			
		||||
 | 
			
		||||
        public static LibHac.Result RegisterProgramMapInfo(Switch device, PartitionFileSystem partitionFileSystem)
 | 
			
		||||
        {
 | 
			
		||||
            ulong applicationId = 0;
 | 
			
		||||
@@ -242,7 +247,7 @@ namespace Ryujinx.HLE.Loaders.Processes
 | 
			
		||||
 | 
			
		||||
            ulong argsStart = 0;
 | 
			
		||||
            uint argsSize = 0;
 | 
			
		||||
            ulong codeStart = (meta.Flags & 1) != 0 ? 0x8000000UL : 0x200000UL;
 | 
			
		||||
            ulong codeStart = ((meta.Flags & 1) != 0 ? 0x8000000UL : 0x200000UL) + CodeStartOffset;
 | 
			
		||||
            uint codeSize = 0;
 | 
			
		||||
 | 
			
		||||
            var buildIds = executables.Select(e => (e switch
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user