Skip to content

Commit 60822a2

Browse files
committed
qemu: new JIT workaround for iOS 26
We map the JIT region originally as RX and also mirror map it as RX. Then we use attached debugger to flag the mirror mapping as debugger owned. Finally, we change the original map to RW which should not invalidate code-signing as the mirror is debugger owned. Thanks to @JJTech0130 for this workaround.
1 parent 5423e6d commit 60822a2

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

patches/qemu-10.0.2-utm.patch

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,115 @@ index 6c91e2d292..86978f4671 100644
427427
--
428428
2.41.0
429429

430+
From dccccf8b3910e69aa236ac1f47e7f16ad34a003d Mon Sep 17 00:00:00 2001
431+
From: osy <[email protected]>
432+
Date: Sun, 14 Sep 2025 00:55:51 -0700
433+
Subject: [PATCH] tcg: new JIT workaround for iOS 26
434+
435+
We map the JIT region originally as RX and also mirror map it
436+
as RX. Then we use attached debugger to flag the mirror
437+
mapping as debugger owned. Finally, we change the original map
438+
to RW which should not invalidate code-signing as the mirror
439+
is debugger owned.
440+
441+
Thanks to @JJTech0130 for this workaround.
442+
---
443+
tcg/region.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++--
444+
1 file changed, 67 insertions(+), 2 deletions(-)
445+
446+
diff --git a/tcg/region.c b/tcg/region.c
447+
index 70996b5ab1..48def8311f 100644
448+
--- a/tcg/region.c
449+
+++ b/tcg/region.c
450+
@@ -623,14 +623,57 @@ extern kern_return_t mach_vm_remap(vm_map_t target_task,
451+
vm_prot_t *max_protection,
452+
vm_inherit_t inheritance);
453+
454+
+#include <TargetConditionals.h>
455+
+#if defined(TARGET_OS_IPHONE) && !defined(TARGET_OS_SIMULATOR)
456+
+#include <sys/types.h>
457+
+#include <sys/sysctl.h>
458+
+static int is_debugger_attached(void)
459+
+{
460+
+ int mib[4];
461+
+ struct kinfo_proc info;
462+
+ size_t size;
463+
+
464+
+ info.kp_proc.p_flag = 0;
465+
+
466+
+ /* Initialize MIB for sysctl call */
467+
+ mib[0] = CTL_KERN;
468+
+ mib[1] = KERN_PROC;
469+
+ mib[2] = KERN_PROC_PID;
470+
+ mib[3] = getpid();
471+
+
472+
+ size = sizeof(info);
473+
+
474+
+ if (sysctl(mib, 4, &info, &size, NULL, 0) == -1) {
475+
+ return 0; // sysctl failed, be conservative
476+
+ }
477+
+
478+
+ /* P_TRACED means the process is being debugged */
479+
+ return (info.kp_proc.p_flag & P_TRACED) != 0;
480+
+}
481+
+
482+
+static void break_prepare_jit_region(mach_vm_address_t addr, size_t len)
483+
+{
484+
+ asm ("mov x0, %0\n"
485+
+ "mov x1, %1\n"
486+
+ "brk #0x69" :: "r" (addr), "r" (len) : "x0", "x1");
487+
+}
488+
+#endif
489+
+
490+
static int alloc_code_gen_buffer_splitwx_vmremap(size_t size, Error **errp)
491+
{
492+
kern_return_t ret;
493+
mach_vm_address_t buf_rw, buf_rx;
494+
vm_prot_t cur_prot, max_prot;
495+
+ int orig_prot = PROT_READ | PROT_WRITE;
496+
497+
- /* Map the read-write portion via normal anon memory. */
498+
- if (!alloc_code_gen_buffer_anon(size, PROT_READ | PROT_WRITE,
499+
+#if defined(TARGET_OS_IPHONE) && !defined(TARGET_OS_SIMULATOR)
500+
+ /* iOS 26 with TXM requires new workaround*/
501+
+ if (__builtin_available(iOS 26, visionOS 26, watchOS 26, tvOS 26, *)) {
502+
+ orig_prot = PROT_READ | PROT_EXEC;
503+
+ }
504+
+#endif
505+
+
506+
+ if (!alloc_code_gen_buffer_anon(size, orig_prot,
507+
MAP_PRIVATE | MAP_ANONYMOUS, errp)) {
508+
return -1;
509+
}
510+
@@ -662,6 +705,28 @@ static int alloc_code_gen_buffer_splitwx_vmremap(size_t size, Error **errp)
511+
return -1;
512+
}
513+
514+
+#if defined(TARGET_OS_IPHONE) && !defined(TARGET_OS_SIMULATOR)
515+
+ if (__builtin_available(iOS 26, visionOS 26, watchOS 26, tvOS 26, *)) {
516+
+ if (!is_debugger_attached()) {
517+
+ error_setg(errp, "debugger must be attached for jit workaround");
518+
+ munmap((void *)buf_rx, size);
519+
+ munmap((void *)buf_rw, size);
520+
+ return -1;
521+
+ }
522+
+
523+
+ /* give let debugger modify the page permission */
524+
+ break_prepare_jit_region(buf_rx, size);
525+
+
526+
+ /* finally mark the read-write portion as RW */
527+
+ if (mprotect((void *)buf_rw, size, PROT_READ | PROT_WRITE) != 0) {
528+
+ error_setg_errno(errp, errno, "mprotect for jit splitwx (rw)");
529+
+ munmap((void *)buf_rx, size);
530+
+ munmap((void *)buf_rw, size);
531+
+ return -1;
532+
+ }
533+
+ }
534+
+#endif
535+
+
536+
tcg_splitwx_diff = buf_rx - buf_rw;
537+
return PROT_READ | PROT_WRITE;
538+
}
539+
--
540+
2.41.0
541+

0 commit comments

Comments
 (0)