[mono] Work around arm64 MacCatalyst unavailable JITing API (#51669)
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Fri, 23 Apr 2021 13:08:50 +0000 (09:08 -0400)
committerGitHub <noreply@github.com>
Fri, 23 Apr 2021 13:08:50 +0000 (09:08 -0400)
commita9f1207d9f14d6bdf6e4be0f206d11df8e032382
tree2461a29d6f2f04c7c995bf91368e49e34b3929a2
parentdf61348e8f005e95f848de7d37a9622f0282c4d1
[mono] Work around arm64 MacCatalyst unavailable JITing API (#51669)

* To [JIT on Apple Silicon](https://developer.apple.com/documentation/apple-silicon/porting-just-in-time-compilers-to-apple-silicon) the application must call `pthread_jit_write_protect_np (0)` before writing to a code page and then `pthread_jit_write_protect_np (1)` before executing JITed code.

* Catalyst apps are Mac apps that get to use iOS frameworks (as well as some mac frameworks).  The API access is guarded by `__API_AVAILABLE` and `__API_UNAVAILABLE` macros in Apple framework headers.  If an API is not explicitly marked for catalyst, clang will follow the `ios` availability.

Unfortunately, `pthread_jit_write_protect_np` is marked like this:

```c
__API_AVAILABLE(macos(11.0))
__API_UNAVAILABLE(ios, tvos, watchos)
void pthread_jit_write_protect_np(int enabled);
```

So a Catalyst app running on arm64 cannot call it.  It will get a compile-time error.
```
src/mono/mono/utils/mono-codeman.c:669:3: error: 'pthread_jit_write_protect_np' is unavailable: not available on macCatalyst
                  pthread_jit_write_protect_np (0);
                  ^
  /Applications/Xcode_12.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/include/pthread.h:561:6: note: 'pthread_jit_write_protect_np' has been explicitly marked unavailable here
  void pthread_jit_write_protect_np(int enabled);
       ^
```

---

Turns out the symbol `pthread_jit_write_protect_np` is actually present in the Catalyst framework libraries, and it does the right thing.

This PR works around the unfortunate `pthread.h` declaration by not using it.

We create a new .c file that included our own declaration
```c
void pthread_jit_write_protect_np(int enabled);
```

And then a new `mono_jit_write_protect` function that calls the pthread function.

---

Another option would be to use something like
```
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
...
#pragma clang diagnostic pop
```
around the offending callsites.  But neither ignoring `-Wpartial-availability` nor `-Wunguarded-availability-new` seem to have any effect on the compilation error.

---

Caveat: It's not yet clear whether this is ok to do in a retail (App Store) app.

---

* [mono] define HOST_MACCAT not HOST_MACCATALYST for Mac Catalyst

The C code already has HOST_MACCAT ifdefs.  HOST_MACCATALYST isn't used.
src/mono/CMakeLists.txt
src/mono/cmake/config.h.in
src/mono/cmake/configure.cmake
src/mono/mono/utils/CMakeLists.txt
src/mono/mono/utils/mono-codeman.c
src/mono/mono/utils/write-protect.c [new file with mode: 0644]
src/mono/mono/utils/write-protect.h [new file with mode: 0644]