Skip to content

Commit 0e4850e

Browse files
committed
Fix JIT branch patching bugs on Apple Silicon
This resolves critical bugs in update_branch_imm causing intermittent test failures (~13-20% failure rate) on macOS/Arm64: 1. MAP_JIT memory corruption: Reading MAP_JIT memory while in write mode returns corrupted data on Apple Silicon. Fixed by moving pthread_jit_write_protect_np(false) to after the read operation. 2. Branch offset bit accumulation: When branches are patched multiple times, old offset bits were not cleared before OR-ing new values. Added bit masking to clear old offsets before setting new ones.
1 parent a5863f1 commit 0e4850e

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

src/jit.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,24 +595,27 @@ static void update_branch_imm(struct jit_state *state,
595595
uint32_t insn;
596596
imm >>= 2;
597597
rv_log_debug("JIT: Patching branch at offset=%u, imm=%d", offset, imm * 4);
598-
#if defined(__APPLE__) && defined(__aarch64__)
599-
/* Must be in write mode to read/write MAP_JIT memory on Apple ARM64 */
600-
pthread_jit_write_protect_np(false);
601-
#endif
598+
/* Read instruction while in execute mode (MAP_JIT requirement) */
602599
memcpy(&insn, state->buf + offset, sizeof(uint32_t));
603600
if ((insn & 0xfe000000U) == 0x54000000U /* Conditional branch immediate. */
604601
|| (insn & 0x7e000000U) ==
605602
0x34000000U) { /* Compare and branch immediate. */
606603
assert((imm >> 19) == INT64_C(-1) || (imm >> 19) == 0);
604+
insn &= ~(0x7ffffU << 5); /* Clear old offset bits */
607605
insn |= (imm & 0x7ffff) << 5;
608606
} else if ((insn & 0x7c000000U) == 0x14000000U) {
609607
/* Unconditional branch immediate. */
610608
assert((imm >> 26) == INT64_C(-1) || (imm >> 26) == 0);
609+
insn &= ~0x03ffffffU; /* Clear old offset bits */
611610
insn |= (imm & 0x03ffffffU) << 0;
612611
} else {
613612
assert(false);
614613
insn = BAD_OPCODE;
615614
}
615+
#if defined(__APPLE__) && defined(__aarch64__)
616+
/* Switch to write mode only for writing */
617+
pthread_jit_write_protect_np(false);
618+
#endif
616619
memcpy(state->buf + offset, &insn, sizeof(uint32_t));
617620
sys_icache_invalidate(state->buf + offset, sizeof(uint32_t));
618621
#if defined(__APPLE__) && defined(__aarch64__)

0 commit comments

Comments
 (0)