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
Supporting Apple Silicon #90
Comments
I find it hard to believe that the only way to adjust protections is to adjust the protections for every JIT-mapped page. Does
Where is the JIT loaded then? As far as I'm aware, CoreCLR always loads the JIT as a separate binary.
|
The
I'm.. not really quite familiar enough with what's going on. But this was always ProcessModule clrjitModule = currentProc.Modules.Cast<ProcessModule>()
.FirstOrDefault(m => Path.GetFileNameWithoutExtension(m.FileName).EndsWith("clrjit", StringComparison.Ordinal));
Yeah that makes sense. So really the problem is that we didn't fill out any precode walkers here, and the ngen comment is unrelated: if (PlatformHelper.Is(Platform.ARM)) {
// TODO: Debug detouring NGEN'd methods on ARM.
} Shouldn't this have been noticed earlier though?? |
Until fairly recently, there simply wasn't a (non-Mono) runtime which targeted ARM and was widely used. As such, ARM walking was never implemented. Now would likely be the time to do it, though I would not blame you at all for not wanting to given the amount of pain that has gone into the x86 walking.
Could you enumerate the modules loaded in a CoreCLR process from outside? On Windows this would be done with something like Process Hacker, but I'm not sure what the equivalents would be for MacOS. It would likely be the same as on Linux.
Sigh. Personally, I'd like to avoid pulling in more shellcode, for hopefully obvious reasons. Is there any way to change a mapping away from |
Thank you for compiling all that information. I'll copy paste what I've sent someone else on the MonoMod Discord server when they asked about Apple Silicon support earlier this month:
Having said that, I'll happily review your (and anyone else's) efforts whenever I can, and highly appreciate that you've put your time into this to begin with.
... and after checking the dotnet runtime repo, that seems to be an intended workaround, given BSD limitations / lack of standardization..? Compare the following: I am only familiar with Linux, where
I can't even imagine how we'd embed shellcode like we already do for icache flushing (which was only tested on Android and would also require updating, see LLVM's
The only way of achieving this that I was made aware of by Hello71 on Discord is to copy it out, unmap it, remap it as MAP_JIT and copy it back. I'd love to get my hands on Apple Silicon to check if that really is necessary - I hope it isn't. As much as I hate to say it, at this point I'd be willing to let Azure Pipelines / GitHub Actions compile a helper native library, embed it, unpack it onto the disk and load it at runtime, as long as size and per-platform code can be kept to an absolute minimum, and only if absolutely necessary. Getting back to the point of actually iterating through loaded modules, the docs for
For some context: I began adding precode walkers when someone reported problems related to ngen'd assemblies, and it's all gotten much complex over time, to the point where RuntimeDetour now needs to works around Wine behavior and I've given up and added a generic catch-all. I should go back and fix those misnomers at some point though.
I remember having tested dotnet 2.x on one of my older rooted phones a few years ago, everything seemed fine enough to meet my personal needs, interest was lost eventually, thus yea. RuntimeDetour is heavily underutilized on ARM, both inside and outside mono, and as mentioned previously (icache), I wouldn't be surprised if other parts required updating as well. |
Hi @0x0ade! Nice to meet you. I was actually made aware of this discussion thanks to input from @SignatureBeef. In a conversation with them, I reached the conclusion that providing money or hardware for Apple Silicon is definitely something we could consider. My biggest problem with doing this is that it might create psychological obligations for you, and if you don't have the time/energy to do it, it isn't worth it anyways. It's an option that I should probably put on the table though -- I don't know how much time/energy/etc outside of just the raw issue of getting access to the hardware you want to spend on it. It sounds like you want AS to test on, but it also sounds like you don't realistically have the time. Consider it food for thought: we would love to get arm working and Apple Silicon working, and if having the hardware will unblock you, that's something we should consider. But if it's just going to sit in a closet or create stress for you, I don't want you to shoulder that burden necessarily. |
If this had happened half a year ago, time wouldn't have been a concern 😅 My first day at my new job is tomorrow. I'll let you know when I'll know if I'll even have the time and energy to work on this in my time off, as I have yet to see what stress awaits me. Thank you for the offer though! |
I think I can send in a PR to implement some of the precode walking for arm64 some time this week, which should unblock @hakusaro and @SignatureBeef's issues with general arm64 support.
Embedding the native library seems like the right choice, because I can't see any ways to not use
Also, by embedding a native library, we'll at least be able to use
No idea how stable this, so I would prefer
Good luck! Hope everything goes smoothly :) |
Initial work on ARM64 precode walking by @kevzhao2 merged with 69a2aa1. I'll keep this issue open for further progress tracking. I've already mentioned this on the Discord server in more detail, but will recap here. I'm currently unable to use "Mac M1 as a service" services because:
My current plan is: Given that I'll need a laptop when I'll relocate closer to my new workplace sooner or later anyway, I'll probably save up until I can afford a M1 MacBook, hitting two birds with one stone. This is to be seen as completely independent from MonoMod - getting it won't mean that I'll immediately work on M1 support for MonoMod, and I want to pay it from my own income, not from community donations which could introduce pressure. By the time I'll get it, I'll hopefully have settled a bit more at my new job and will be able to work on this in my spare time at my own pace. If the community ends up creating solid M1 support for MonoMod before that happens, I'll finally be able to review it by then, and continue maintaining it. And if something happens to my new employment (I'm only one week in, and it's going well so far), I'll see how to move forward from there. |
@0x0ade hey! how's the new job? I joined your patreon a while back, but I'd be more than happy to throw some gas on the fire and send you an M1 MacBook to an address you send me if you need one. |
Saw this pop up in my email inbox again, sorry for the lack of updates, sadly lacking time right now thus keeping it short: I'm relocating next month. All my previous plans were shot down by stuff going on in the household I'm living in right now that I won't dwell much on, which I can't wait to finally get out of. But I was already very close to buying a M1 MacBook multiple times now. If everything goes well, I might finally press the buy button this or next month. At this point I can't promise that I'll have the free time to look into M1 support though. |
No problemo, don't let not having the product stop you though. Once you're settled, hit me up! |
Hey! Just wanted to know how is your progress on getting Silicon Mac and the issue itself? :) |
I have finally started working on x64 Mac support on |
Please ignore this comment, I just want to remember in the future that I'm following this issue as it looks like it's a requirement to get Harmony working on Silicon, which is also the requirement to get FastScriptReload working on Silicon. 🙏 |
Any ETA when can we expect this to be released? |
There is currently no ETA. I simply don't have the hardware to be able to work on this. |
@nike4613 you can hit me up in the MonoMod discord (i’m antiparticles) for hardware if you’re seriously only limited by hardware for this issue |
I could contribute something too if necessary. Especially if I'm not the only one. |
I've run into an instance where I need Harmony on an ARM platform as well, though I'd be happy with any sort of ARM support, not just M1. I'm happy to offer any sort of support I can. Edit: reading back... MonoMod should have some level of support on ARM already, right? Am I not understanding that correctly? If so, I should perhaps open up a separate issue for the platform I'm currently having trouble with. |
It currently does not have any support for ARM. |
@nike4613 Gotcha. How does https://github.com/MonoMod/MonoMod.Common/blob/master/RuntimeDetour/Platforms/Native/DetourNativeARMPlatform.cs relate to this? |
That (and all of MMC) are part of legacy MonoMod. Current development (and broadest support) is on the Legacy's ARM support was all "it works on my machine" as-is, so it got dropped along with the rest of legacy, pending a return when I or someone else has the time/resources to work on it. |
Okay, I see - thanks for the explanation :) Is there some way I can support or aid the ARM implementation? I'm not familiar enough with MonoMod's architecture or the ABI of ARM processors to take a crack at it all on my lonesome, but I'm more than willing to help out any way I can. |
I would also like to aid in making ARM implementation. I have a hardware to test on, but don't have any experience with MonoMod |
Vintage Story dev here. ARM support would enable us to port our game to Mac. I've doubled my patreon pledge. If additional hardware is needed to accelerate development of this, do let me know. |
Forgive me for asking about this here, but has there been any progress made in this regard? VRChat just released their Unity 2022 SDK in beta, and their scripting tool, Udon Sharp, uses Harmony Lib as a key component. Unity 2022 itself brings with it native Apple Silicon support, which greatly improves performance and stability over running Intel builds in Rosetta. However, this issue in particular seems to effect Harmony, which in turn effects Udon Sharp, which in turn effects the VRChat SDK. Issues regarding Apple Silicon support for Harmony point here. With a major platform having a shift towards newer software, which provide Apple Silicon support, and said platform having plans for Apple Silicon support themselves in the extended pipeline (iOS/macOS), I fear this issue might become more pressing as time goes on. |
I'm still happy to sponsor hardware for people who want to work on getting this (now, |
Likewise |
+1 |
Me neither, I am interested in running tMod on the Arm64 CPU, so, I can help testing, since I don't know how MonoMod works too |
I've experimented with this issue to try to figure out what all needs to be done for arm64 support. Some of what I've discovered has already been mentioned here, but there are also some things that I have not seen mentioned that may be helpful for creating a proper port. I've mostly been trying to get my changes to work on .NET core 6, so I don't know how well my changes work for other versions of .NET or other runtimes. Here's a list of my major observations:
The code for my attempt at adding arm64 support can be found here, if anyone's interested. |
Nice work.
I'm glad the new PatchData method interface is proving useful. :)
This is slightly concerning. I wonder what causes this? We already use (if available) a native exception helper stub between native and managed code everywhere we inject ourselves into the JIT/EE boundary. Could we use those stubs to make sure
This sounds to me like we should inject another type in between For an actual release, I'd like to avoid having C++-compiled binaries if possible, to avoid needing platform-specific toolsets to build those binaries. Currently, we're able to avoid it by using NASM and LLD-Link; I suspect a similar approach with a portable assembler + linker would probably be the approach here, though the amount of code necessary here is rather unfortunate. |
I'm pretty sure that is an option. The main issue is that currently
From what I can find there isn't a way. (although Apple's documentation is very sparse on the subject) This is especially problematic, as sometimes |
Can we not allocate those in a page marked RW, then remap them as RX? We need few enough of them that wasting most of a page is probably not a huge issue. |
Yeah, that's potentially an option as well. I wasn't sure if Apple Silicon allows remapping a page to be exec, but if it does then that would be a much better option than using global state. |
I spent some time debugging over the weekend and figured out the necessary changes for supporting Apple Silicon. I can try to restructure the code a bit and send in a pull request, but I just wanted to write down the things that I encountered.
W^X
Apple requires all pages to be W^X, and requires pages to be mapped in with the
MAP_JIT
flag.MAP_JIT
flag. We just need to do the following:pthread_jit_write_protect_np(false)
(to enable write and disable execute)pthread_jit_write_protect_np(true)
(to disable write and enable execute)mmap
in memory with theMAP_JIT
flag instead of calling the equivalent ofmalloc
.The first item has to be done entirely in native code because calling
pthread_jit_write_protect_np(false)
from managed code causes a bus error -- this is becausepthread_jit_write_protect_np
controls every page!libclrjit.dylib
libclrjit.dylib
doesn't seem to be one of the modules loaded into the process, which means that the JIT hooks don't work. This is, however, a pretty easy change to make.Virtual Method Function Pointers
Hooking virtual methods seems to be a bit fraught (with arm64, at least?) because the function pointers that we get with
DetourRuntimeNETPlatform.GetFunctionPointer
don't seem to related to the entries found in the vtable, and I'm not exactly sure why this isn't the case for amd64...My quick and dirty solution was to just read the vtable to get the function pointer:
Additionally, because the devirtualization code expects the entries to point to things that look like precode, I had to change the detour code a bit to match.
The text was updated successfully, but these errors were encountered: