Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow access to code memory for exefs mods #5518

Merged
merged 3 commits into from Aug 9, 2023

Conversation

TSRBerry
Copy link
Member

@TSRBerry TSRBerry commented Aug 1, 2023

This PR fixes an issue where games would crash if mods utilizing JIT (most notably exlaunch) were used.

More context can be found at the linked issue.


Fixes #5466
Fixes #4354

@TSRBerry TSRBerry added the fix Fix something label Aug 1, 2023
@github-actions github-actions bot added the horizon Related to Ryujinx.HLE label Aug 1, 2023
@TSRBerry TSRBerry requested a review from a team August 1, 2023 20:09
@gdkchan
Copy link
Member

gdkchan commented Aug 1, 2023

Does that work with ARCropolis on Super Smash Bros Ultimate? The main reason it was disabled is because there is a bug on skyline that prevents it from working with code memory. It would try to allocate memory before the executable, which doesn't work in the emulator as it maps the executable at the base of the address space. A potential fix for this is simply not loading the executable at the base of address space, but that will break PPTC since it currently assumes all guest code addresses don't change.

@TSRBerry
Copy link
Member Author

TSRBerry commented Aug 2, 2023

That just crashes with an invalid memory access:

Ryujinx crash: ARCropolis
00:00:01.093 |I| Loader Load: Loading rtld...
00:00:01.101 |I| Loader PrintRoSectionInfo: rtld:
    Module: nnrtld
00:00:01.101 |I| Loader Load: Loading main...
00:00:01.811 |I| Loader PrintRoSectionInfo: main:
    Module: C:\c2\p4\patch-13.0.0\work\build\vs2015.built\cross2app+standalone\NX64\Release\cross2_Release.nss
    SDK Libraries: SDK MW+Nintendo+NintendoSDK_libcurl-8_2_1-Release
                   SDK MW+Nintendo+NintendoSDK_libz-8_2_1-Release
                   SDK MW+Nintendo+NintendoSDK_gfx-8_2_1-Release
                   SDK MW+Nintendo+NintendoWare_Ui2d-8_2_1-Release
                   SDK MW+Nintendo+NintendoWare_Font-8_2_1-Release
                   SDK MW+Nintendo+NintendoWare_Vfx-8_2_1-Release
                   SDK MW+Nintendo+NintendoWare_G3d-8_2_1-Release
                   SDK MW+Nintendo+PiaCommon-5_19_1
                   SDK MW+Nintendo+Pia-5_19_1
                   SDK MW+Nintendo+PiaNex-5_19_1-forNEX-4_6_3
                   SDK MW+Nintendo+PiaLan-5_19_1
                   SDK MW+Nintendo+PiaSession-5_19_1
                   SDK MW+Nintendo+PiaTransport-5_19_1
                   SDK MW+Nintendo+PiaLocal-5_19_1
                   SDK MW+Nintendo+NEX-4_6_13-appc2
                   SDK MW+Nintendo+NEX_MM-4_6_13
                   SDK MW+Nintendo+NEX_UT-4_6_13
                   SDK MW+Nintendo+NEX_DS-4_6_13
                   SDK MW+Nintendo+NEX_CO-4_6_13
                   SDK MW+Nintendo+NEX_SC-4_6_13
00:00:01.812 |I| Loader Load: Loading subsdk0...
00:00:01.885 |I| Loader PrintRoSectionInfo: subsdk0:
    Module: multimedia
    SDK Libraries: SDK MW+Nintendo+NintendoSDK_movie-8_2_1-Release
00:00:01.885 |I| Loader Load: Loading sdk...
00:00:01.975 |I| Loader PrintRoSectionInfo: sdk:
    Module: nnSdk
    FS SDK Version: 8.2.1
    SDK Libraries: SDK MW+Nintendo+NintendoSDK_libz-8_2_1-Release
                   SDK MW+Nintendo+NintendoSdk_nnSdk-8_2_1-Release
                   SDK MW+Nintendo+NintendoSDK_NVN-8_2_1-Release
00:00:01.977 |I| Loader PrintRoSectionInfo: subsdk9:
    Module: Skyline
00:00:01.977 |I| ModLoader ApplyExefsMods: NSO 'subsdk9' replaced
00:00:01.978 |I| ModLoader ApplyExefsMods: main.npdm replaced
00:00:01.987 |W| Ptc Load: Detected unsupported ExeFs modifications. PTC disabled.
00:00:02.171 |I| Ptc Initialize: Initializing Profiled Persistent Translation Cache (enabled: False).
00:00:02.179 |I| Loader LoadNsos: Loading image 0 at 0x0000000008000000...
00:00:02.181 |I| Loader LoadNsos: Loading image 1 at 0x0000000008004000...
00:00:02.248 |I| Loader LoadNsos: Loading image 2 at 0x000000000f44a000...
00:00:02.252 |I| Loader LoadNsos: Loading image 3 at 0x000000000fb5f000...
00:00:02.252 |I| Loader LoadNsos: Loading image 4 at 0x000000000fb7c000...
00:00:02.261 |I| ModLoader LoadCheats: Build ids found for title 01006A800016E000:
    285183CAC95179371CC22CEC3723F882E1589659000000000000000000000000
    77104350C9768709FD91636A8822EB2B16D9CAE1000000000000000000000000
    60C6EDBBFCEBD4176CC301D5D9CB5A6F094F9360000000000000000000000000
    04230E58D6A644C473F80DF48EFE4B374FF65CC7000000000000000000000000
    5FD4F531C1195E9E5510C9E73F22CD39612839F8000000000000000000000000
00:00:02.265 |I| ModLoader ApplyRomFsMods: Applying RomFS mods for Title 01006A800016E000
00:00:02.272 |I| ModLoader ApplyRomFsMods: Replaced 1 file(s) over 1 mod(s). Processing base storage...
00:00:02.345 |I| ModLoader ApplyRomFsMods: Building new RomFS...
00:00:02.352 |I| ModLoader ApplyRomFsMods: Using modded RomFS
00:00:02.355 |I| Application EnsureSaveData: Ensuring required savedata exists.
00:00:02.420 |I| Loader Start: Application Loaded: Super Smash Bros. Ultimate v13.0.0 [01006a800016e000] [64-bit]
00:00:02.499 |I| GUI.WindowThread Hid Configure: Configured Controller ProController to Player1
00:00:02.518 |I| GUI.WindowThread Hid SetupNpad: Connected Controller ProController to Player1
XError: 0 result is 8
00:00:02.930 |N| GUI.RenderThread Gpu PrintGpuInformation: NVIDIA NVIDIA GeForce RTX 2060 (Vulkan v1.3.242, Driver v535.86.5.0)
00:00:02.943 |I| GPU.MainThread Gpu LoadShaders: Loading 15 shaders from the cache...
00:00:03.056 |W| GPU.AsyncTranslationThread.6 Gpu Log: Shader translator: Shader instruction Votevtg is not implemented.
00:00:03.059 |W| GPU.AsyncTranslationThread.1 Gpu Log: Shader translator: Shader instruction Votevtg is not implemented.
00:00:03.450 |I| GPU.MainThread Gpu LoadShaders: Rebuilding 15 shaders...
00:00:03.553 |I| GPU.MainThread Gpu LoadShaders: Rebuilt 15 shaders successfully.
00:00:03.553 |I| GPU.MainThread Gpu LoadShaders: Shader cache loaded.
00:00:05.592 |W| HLE.GuestThread.21 KernelSvc : GetInfo(value: 0x0000000000000000) = InvalidHandle
00:00:05.592 |W| HLE.GuestThread.21 KernelSvc : GetInfo(value: 0x0000000000000000) = InvalidHandle
00:00:05.592 |W| HLE.GuestThread.21 KernelSvc : GetInfo(value: 0x0000000000000000) = InvalidEnumValue
00:00:05.593 |W| HLE.GuestThread.21 KernelSvc : GetInfo(value: 0x0000000000000000) = InvalidHandle
00:00:05.593 |W| HLE.GuestThread.21 KernelSvc : GetInfo(value: 0x0000000000000000) = InvalidHandle
00:00:05.601 |W| HLE.GuestThread.21 KernelSvc : ControlCodeMemory() = InvalidEnumValue
00:00:05.625 |W| HLE.GuestThread.21 KernelSvc : ControlCodeMemory() = InvalidMemoryRegion
00:00:06.390 |I| HLE.GuestThread.21 Cpu PrintGuestStackTrace: Guest stack trace:
Process: Super Smash Bros. Ultimate, PID: 98
   0x00000000080007e4   rtld:0x07e4     
   0x000000000fe19a28   sdk:0x29da28    nn::init::Start(unsigned long, unsigned long, void (*)(), void (*)()):0x0048
   0x00000000080000c0   rtld:0x00c0     


00:00:06.392 |I| HLE.GuestThread.21 Cpu PrintGuestRegisterPrintout: Guest CPU registers:
        X[00]:  0x000000000000dc01
        X[01]:  0x00000011002801c8
        X[02]:  0x0000001100590000
        X[03]:  0x0000000000000031
        X[04]:  0x0000000000000000
        X[05]:  0x0000000000000000
        X[06]:  0x0000000000000000
        X[07]:  0x0000000000000000
        X[08]:  0x0000000000000097
        X[09]:  0x00000011002801d0
        X[10]:  0x0000000000000098
        X[11]:  0x00000000fffffffd
        X[12]:  0x0000000000000000
        X[13]:  0x000000000d93f3c0
        X[14]:  0x000000207f200028
        X[15]:  0x000000207f200028
        X[16]:  0x000000000d2a1400
        X[17]:  0x000000000feadf40 (sdk:0x331f40)       => nn::os::GetTlsValue(nn::os::TlsSlot)
        X[18]:  0x000000207f200090
        X[19]:  0x0000000008003000
        X[20]:  0x00000000107b8000
        X[21]:  0x0000000008004000 (main:0x0000)        => 
        X[22]:  0x0000000000008000
        X[23]:  0x0000000000000000
        X[24]:  0x0000000000000000
        X[25]:  0x0000000000000000
        X[26]:  0x0000000000000000
        X[27]:  0x0000000000000000
        X[28]:  0x0000000000000000
        FP:     0x0000001010b03f90 (SP:-0x0070)
        LR:     0x000000000fb6225c (subsdk1:0x325c)     => 
        SP:     0x0000001010b03f20 (SP)
        PC:     0x000000000b92cf90 (main:0x3928f90)     => 


00:00:06.392 |E| HLE.GuestThread.21 Cpu InvalidAccessHandler: Invalid memory access at virtual address 0x0000000000000000.
00:00:06.403 |E| HLE.GuestThread.21 Application : Unhandled exception caught: Ryujinx.Memory.InvalidMemoryRegionException: Attempted to access an invalid memory region.

I'm not a fan of having workarounds to make something work on Ryujinx that works on hardware without that workaround. Could we consider this a bug instead and solve this issue correctly?

@gdkchan
Copy link
Member

gdkchan commented Aug 2, 2023

I'm not a fan of having workarounds to make something work on Ryujinx that works on hardware without that workaround. Could we consider this a bug instead and solve this issue correctly?

The behaviour that makes those mods crash is the official kernel behaviour. The official kernel does not allow code memory to be mapped to the same process it was created. This is a CFW modification that was made for homebrew, to allow them to create and map code memory in the same process, to allow generating and modifying its own code. For this reason I don't see it as much as a "workaround" to make ARCropolis work.

In any case, I think the amount of people using SSBU mods is considerably higher than users of exlaunch based mods, it doesn't seems worth it for me to break one to fix the other. I think it would be better to make PPTC guest code relocation work, and then enable code memory for everything (maybe behind a Switch since it's not standard kernel behaviour).

@TSRBerry
Copy link
Member Author

TSRBerry commented Aug 2, 2023

For this reason I don't see it as much as a "workaround" to make ARCropolis work.

My word choice was bad. What I meant was that if this check was only implemented like that to make ARCropolis work, I don't think it's the right way to do this. I'd be more in favor of having the same behavior as AMS.
I like the idea of having a switch to turn off CFW modifications to reflect official (kernel) behavior!

If I understand the ARCropolis issue correctly we currently don't match the behavior of pm (or was that am?) for loading processes into memory. Shouldn't we address that instead?

@gdkchan
Copy link
Member

gdkchan commented Aug 2, 2023

My word choice was bad. What I meant was that if this check was only implemented like that to make ARCropolis work, I don't think it's the right way to do this. I'd be more in favor of having the same behavior as AMS.
I like the idea of having a switch to turn off CFW modifications to reflect official (kernel) behavior!

Yes, I think we should delete this allowCodeMemoryForJit logic eventually and replace it with the "Enable CFW modifications" toggle. It would be enabled by default to make JIT homebrew and code modifying mods work.

If I understand the ARCropolis issue correctly we currently don't match the behavior of pm (or was that am?) for loading processes into memory. Shouldn't we address that instead?

Yes, the Switch has ASLR and will load the executable at a random memory location. We always load it at a fixed location. Unfortunately PPTC currently has a dependency on that, it stores guest addresses directly, which means if it changes, the cached PPTC code will stop working. To make skyline work with code memory, we can simply load the executable at a higher fixed address (instead of random address) which would work with PPTC as the address would be still the same between runs, but it would still require a full PPTC invalidation as the address would be different from the existing caches. The ideal solution would be rewriting PPTC and solving that and the other issues it has (like #5130, fix the "NRO stutters", etc).

@gdkchan
Copy link
Member

gdkchan commented Aug 2, 2023

BTW there is another bug on skyline that makes it crash when using the path that does not require code memory. It uses an invalid address with a cache invalidation instruction. The only reason it works is because we ignore cache maintenance instructions on the JIT right now, as we don't emulate CPU caches. But it does not work on Apple Hypervisor for this reason, and presumably wouldn't work on hardware either (without code memory). So that is something that should eventually be fixed on the JIT, we should at least throw for cache operations with invalid memory addresses.

@TSRBerry
Copy link
Member Author

TSRBerry commented Aug 6, 2023

@gdkchan do you think the workaround that I added with my latest commit here is a good solution for now?

@gdkchan
Copy link
Member

gdkchan commented Aug 6, 2023

@gdkchan do you think the workaround that I added with my latest commit here is a good solution for now?

I'm not a fan of adding even more special cases to make this work, but maybe that is fine for now, until PPTC is eventually improved. If you are going to do this, the existing allowCodeMemoryForJit logic should be deleted. The reason it was added is that this mod doesn't work, if you are adding another work around for the issue, then it can be removed and code memory can be "always allowed". Ideally we would have the setting that I mentioned before, "Enable CFW modifications" or whatever it ends being called, and when it is enabled, code memory would be allowed. I would replace the allowCodeMemoryForJit check on the syscall with this setting, and it would be enabled by default. It should allow the code to be simplified a bit too as we don't need to pass allowCodeMemoryForJit around.

About PPTC, instead of the migration path, maybe it's fine to just implement a way to do full PPTC invalidation. It doesn't take long to build so a full invalidation wouldn't be a big deal IMO.

BTW this should also fix ARCropolis not working on mac with hypervisor, but I didn't test myself.

@TSRBerry
Copy link
Member Author

TSRBerry commented Aug 6, 2023

About PPTC, instead of the migration path, maybe it's fine to just implement a way to do full PPTC invalidation. It doesn't take long to build so a full invalidation wouldn't be a big deal IMO.

For that we just need to change the InternalVersion for both Ptc.cs and PtcProfiler.cs. But preserving what was already saved sounds better to me than deleting everything even if it can be rebuilt quickly.

If you are going to do this, the existing allowCodeMemoryForJit logic should be deleted.

I'd prefer to replace it with the setting we discussed before, but don't think I should do that in this PR as well.

Ideally we would have the setting that I mentioned before, "Enable CFW modifications" or whatever it ends being called, and when it is enabled, code memory would be allowed. I would replace the allowCodeMemoryForJit check on the syscall with this setting, and it would be enabled by default. It should allow the code to be simplified a bit too as we don't need to pass allowCodeMemoryForJit around.

Sounds good to me! I'd like to do that, but since that requires a few more changes I'd like to do it in a separate PR.

Is that fine?

@gdkchan
Copy link
Member

gdkchan commented Aug 6, 2023

Sounds good to me! I'd like to do that, but since that requires a few more changes I'd like to do it in a separate PR.

Is that fine?

You can just keep the setting hardcoded to true without exposing it on the UI or adding to the config file. It can be exposed in the UI on a separate PR. That way the amount of changes should be small.

Copy link
Member

@gdkchan gdkchan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks!

@gdkchan gdkchan merged commit 5e9678c into Ryujinx:master Aug 9, 2023
9 checks passed
@TSRBerry TSRBerry deleted the fix/code-memory-access branch August 10, 2023 00:14
jcm93 pushed a commit to jcm93/Ryujinx that referenced this pull request Aug 15, 2023
* Allow access to code memory for exefs mods

* Add ASLR workaround for Skyline

* Hardcode allowCodeMemoryForJit to true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fix Fix something horizon Related to Ryujinx.HLE
Projects
None yet
4 participants