From e52c60c2b2b03c5eec88ef71f9f2566e2ea59744 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 1 Sep 2025 10:33:40 +0200 Subject: [PATCH 1/6] Mark labels in x64 write barrier code as local/alt_entry to prevent incorrect transformations by the ld64/ld-prime linkers --- .../vm/amd64/jithelpers_fastwritebarriers.S | 172 +++++++++--------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S b/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S index f987751bdcb358..cf9f149e374899 100644 --- a/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S +++ b/src/coreclr/vm/amd64/jithelpers_fastwritebarriers.S @@ -39,10 +39,10 @@ PATCH_LABEL JIT_WriteBarrier_PreGrow64_Patch_Label_CardTable shr rdi, 0x0B cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_PreGrow64 + // jne LOCAL_LABEL(UpdateCardTable_PreGrow64) REPRET - UpdateCardTable_PreGrow64: + LOCAL_LABEL(UpdateCardTable_PreGrow64): mov byte ptr [rdi + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -57,17 +57,17 @@ PATCH_LABEL JIT_WriteBarrier_PreGrow64_Patch_Label_CardBundleTable cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundle_PreGrow64 + // jne LOCAL_LABEL(UpdateCardBundle_PreGrow64) REPRET - UpdateCardBundle_PreGrow64: + LOCAL_LABEL(UpdateCardBundle_PreGrow64): mov byte ptr [rdi + rax], 0xFF #endif ret .balign 16 - Exit_PreGrow64: +PATCH_LABEL Exit_PreGrow64 REPRET LEAF_END_MARKED JIT_WriteBarrier_PreGrow64, _TEXT @@ -124,10 +124,10 @@ PATCH_LABEL JIT_WriteBarrier_PostGrow64_Patch_Label_CardTable shr rdi, 0x0B cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_PostGrow64 + // jne LOCAL_LABEL(UpdateCardTable_PostGrow64) REPRET - UpdateCardTable_PostGrow64: + LOCAL_LABEL(UpdateCardTable_PostGrow64): mov byte ptr [rdi + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -142,17 +142,17 @@ PATCH_LABEL JIT_WriteBarrier_PostGrow64_Patch_Label_CardBundleTable cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundle_PostGrow64 + // jne LOCAL_LABEL(UpdateCardBundle_PostGrow64) REPRET - UpdateCardBundle_PostGrow64: + LOCAL_LABEL(UpdateCardBundle_PostGrow64): mov byte ptr [rdi + rax], 0xFF #endif ret .balign 16 - Exit_PostGrow64: +PATCH_LABEL Exit_PostGrow64 REPRET LEAF_END_MARKED JIT_WriteBarrier_PostGrow64, _TEXT @@ -183,10 +183,10 @@ PATCH_LABEL JIT_WriteBarrier_SVR64_PatchLabel_CardTable cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_SVR64 + // jne LOCAL_LABEL(UpdateCardTable_SVR64) REPRET - UpdateCardTable_SVR64: + LOCAL_LABEL(UpdateCardTable_SVR64): mov byte ptr [rdi + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -200,10 +200,10 @@ PATCH_LABEL JIT_WriteBarrier_SVR64_PatchLabel_CardBundleTable cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundle_SVR64 + // jne LOCAL_LABEL(UpdateCardBundle_SVR64) REPRET - UpdateCardBundle_SVR64: + LOCAL_LABEL(UpdateCardBundle_SVR64): mov byte ptr [rdi + rax], 0xFF #endif @@ -233,46 +233,46 @@ PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_RegionShrDest // Check whether the region we're storing into is gen 0 - nothing to do in this case cmp byte ptr [rdi + rax], 0 .byte 0x75, 0x04 - //jne NotGen0_Byte_Region64 + //jne LOCAL_LABEL(NotGen0_Byte_Region64) REPRET NOP_2_BYTE // padding for alignment of constant - NotGen0_Byte_Region64: + LOCAL_LABEL(NotGen0_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_Lower movabs r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x73, 0x01 - // jae NotLow_Byte_Region64 + // jae LOCAL_LABEL(NotLow_Byte_Region64) ret - NotLow_Byte_Region64: + LOCAL_LABEL(NotLow_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_Upper movabs r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x72, 0x02 - // jb NotHigh_Byte_Region64 + // jb LOCAL_LABEL(NotHigh_Byte_Region64) REPRET - NotHigh_Byte_Region64: + LOCAL_LABEL(NotHigh_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_RegionShrSrc shr rsi, 0x16 // compute region index mov dl, [rsi + rax] cmp dl, [rdi + rax] .byte 0x72, 0x03 - // jb IsOldToYoung_Byte_Region64 + // jb LOCAL_LABEL(IsOldToYoung_Byte_Region64) REPRET nop - IsOldToYoung_Byte_Region64: + LOCAL_LABEL(IsOldToYoung_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_CardTable movabs rax, 0xF0F0F0F0F0F0F0F0 shr r8, 0xB cmp byte ptr [r8 + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_Byte_Region64 + // jne LOCAL_LABEL(UpdateCardTable_Byte_Region64) REPRET - UpdateCardTable_Byte_Region64: + LOCAL_LABEL(UpdateCardTable_Byte_Region64): mov byte ptr [r8 + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES shr r8, 0x0A @@ -280,10 +280,10 @@ PATCH_LABEL JIT_WriteBarrier_Byte_Region64_Patch_Label_CardBundleTable movabs rax, 0xF0F0F0F0F0F0F0F0 cmp byte ptr [r8 + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundleTable_Byte_Region64 + // jne LOCAL_LABEL(UpdateCardBundleTable_Byte_Region64) REPRET - UpdateCardBundleTable_Byte_Region64: + LOCAL_LABEL(UpdateCardBundleTable_Byte_Region64): mov byte ptr [r8 + rax], 0xFF #endif ret @@ -308,36 +308,36 @@ PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_RegionShrDest // Check whether the region we're storing into is gen 0 - nothing to do in this case cmp byte ptr [rdi + rax], 0 .byte 0x75, 0x04 - //jne NotGen0_Bit_Region64 + //jne LOCAL_LABEL(NotGen0_Bit_Region64) REPRET NOP_2_BYTE // padding for alignment of constant - NotGen0_Bit_Region64: + LOCAL_LABEL(NotGen0_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_Lower movabs r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x73, 0x01 - // jae NotLow_Bit_Region64 + // jae LOCAL_LABEL(NotLow_Bit_Region64) ret - NotLow_Bit_Region64: + LOCAL_LABEL(NotLow_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_Upper movabs r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x72, 0x02 - // jb NotHigh_Bit_Region64 + // jb LOCAL_LABEL(NotHigh_Bit_Region64) REPRET - NotHigh_Bit_Region64: + LOCAL_LABEL(NotHigh_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_RegionShrSrc shr rsi, 0x16 // compute region index mov dl, [rsi + rax] cmp dl, [rdi + rax] .byte 0x72, 0x03 - // jb IsOldToYoung_Bit_Region64 + // jb LOCAL_LABEL(IsOldToYoung_Bit_Region64) REPRET nop - IsOldToYoung_Bit_Region64: + LOCAL_LABEL(IsOldToYoung_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardTable movabs rax, 0xF0F0F0F0F0F0F0F0 @@ -349,10 +349,10 @@ PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardTable shl dl, cl test byte ptr [r8 + rax], dl .byte 0x74, 0x02 - // je UpdateCardTable_Bit_Region64 + // je LOCAL_LABEL(UpdateCardTable_Bit_Region64) REPRET - UpdateCardTable_Bit_Region64: + LOCAL_LABEL(UpdateCardTable_Bit_Region64): lock or byte ptr [r8 + rax], dl #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardBundleTable @@ -360,10 +360,10 @@ PATCH_LABEL JIT_WriteBarrier_Bit_Region64_Patch_Label_CardBundleTable shr r8, 0x0A cmp byte ptr [r8 + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundleTable_Bit_Region64 + // jne LOCAL_LABEL(UpdateCardBundleTable_Bit_Region64) REPRET - UpdateCardBundleTable_Bit_Region64: + LOCAL_LABEL(UpdateCardBundleTable_Bit_Region64): mov byte ptr [r8 + rax], 0xFF #endif ret @@ -397,10 +397,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PreGrow64_Patch_Label_Lower add rax, r10 cmp byte ptr [rax], 0x0 .byte 0x75, 0x03 - // jne CheckCardTable_WriteWatch_PreGrow64 + // jne LOCAL_LABEL(CheckCardTable_WriteWatch_PreGrow64) mov byte ptr [rax], 0xFF - CheckCardTable_WriteWatch_PreGrow64: + LOCAL_LABEL(CheckCardTable_WriteWatch_PreGrow64): // Check the lower ephemeral region bound. cmp rsi, r11 @@ -419,10 +419,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PreGrow64_Patch_Label_CardTable movabs rax, 0xF0F0F0F0F0F0F0F0 cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_WriteWatch_PreGrow64 + // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_PreGrow64) REPRET - UpdateCardTable_WriteWatch_PreGrow64: + LOCAL_LABEL(UpdateCardTable_WriteWatch_PreGrow64): mov byte ptr [rdi + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -434,17 +434,17 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PreGrow64_Patch_Label_CardBundleTable cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundle_WriteWatch_PreGrow64 + // jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_PreGrow64) REPRET - UpdateCardBundle_WriteWatch_PreGrow64: + LOCAL_LABEL(UpdateCardBundle_WriteWatch_PreGrow64): mov byte ptr [rdi + rax], 0xFF #endif ret .balign 16 - Exit_WriteWatch_PreGrow64: +PATCH_LABEL Exit_WriteWatch_PreGrow64 REPRET LEAF_END_MARKED JIT_WriteBarrier_WriteWatch_PreGrow64, _TEXT @@ -475,13 +475,13 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PostGrow64_Patch_Label_Lower add rax, r10 cmp byte ptr [rax], 0x0 .byte 0x75, 0x06 - // jne CheckCardTable_WriteWatch_PostGrow64 + // jne LOCAL_LABEL(CheckCardTable_WriteWatch_PostGrow64) mov byte ptr [rax], 0xFF NOP_3_BYTE // padding for alignment of constant // Check the lower and upper ephemeral region bounds - CheckCardTable_WriteWatch_PostGrow64: + LOCAL_LABEL(CheckCardTable_WriteWatch_PostGrow64): cmp rsi, r11 #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -514,10 +514,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PostGrow64_Patch_Label_CardTable shr rdi, 0x0B cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_WriteWatch_PostGrow64 + // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_PostGrow64) REPRET - UpdateCardTable_WriteWatch_PostGrow64: + LOCAL_LABEL(UpdateCardTable_WriteWatch_PostGrow64): mov byte ptr [rdi + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -529,16 +529,16 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_PostGrow64_Patch_Label_CardBundleTable cmp byte ptr [rdi + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundle_WriteWatch_PostGrow64 + // jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_PostGrow64) REPRET - UpdateCardBundle_WriteWatch_PostGrow64: + LOCAL_LABEL(UpdateCardBundle_WriteWatch_PostGrow64): mov byte ptr [rdi + rax], 0xFF #endif ret .balign 16 - Exit_WriteWatch_PostGrow64: +PATCH_LABEL Exit_WriteWatch_PostGrow64 REPRET LEAF_END_MARKED JIT_WriteBarrier_WriteWatch_PostGrow64, _TEXT @@ -578,17 +578,17 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_SVR64_PatchLabel_CardTable add rax, r10 cmp byte ptr [rax], 0x0 .byte 0x75, 0x03 - // jne CheckCardTable_WriteWatch_SVR64 + // jne LOCAL_LABEL(CheckCardTable_WriteWatch_SVR64) mov byte ptr [rax], 0xFF - CheckCardTable_WriteWatch_SVR64: + LOCAL_LABEL(CheckCardTable_WriteWatch_SVR64): shr rdi, 0x0B cmp byte ptr [rdi + r11], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_WriteWatch_SVR64 + // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_SVR64) REPRET - UpdateCardTable_WriteWatch_SVR64: + LOCAL_LABEL(UpdateCardTable_WriteWatch_SVR64): mov byte ptr [rdi + r11], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES @@ -600,10 +600,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_SVR64_PatchLabel_CardBundleTable shr rdi, 0x0A cmp byte ptr [rdi + r11], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundle_WriteWatch_SVR64 + // jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_SVR64) REPRET - UpdateCardBundle_WriteWatch_SVR64: + LOCAL_LABEL(UpdateCardBundle_WriteWatch_SVR64): mov byte ptr [rdi + r11], 0xFF #endif @@ -632,57 +632,57 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_RegionShrDest shr rdi, 0x16 // compute region index cmp byte ptr [rax], 0x0 .byte 0x75, 0x03 - // jne CheckGen0_WriteWatch_Byte_Region64 + // jne LOCAL_LABEL(CheckGen0_WriteWatch_Byte_Region64) mov byte ptr [rax], 0xFF - CheckGen0_WriteWatch_Byte_Region64: + LOCAL_LABEL(CheckGen0_WriteWatch_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_RegionToGeneration mov rax, 0xF0F0F0F0F0F0F0F0 // Check whether the region we're storing into is gen 0 - nothing to do in this case cmp byte ptr [rdi + rax], 0 .byte 0x75, 0x08 - // jne NotGen0_WriteWatch_Byte_Region64 + // jne LOCAL_LABEL(NotGen0_WriteWatch_Byte_Region64) REPRET NOP_2_BYTE // padding for alignment of constant NOP_2_BYTE // padding for alignment of constant NOP_2_BYTE // padding for alignment of constant - NotGen0_WriteWatch_Byte_Region64: + LOCAL_LABEL(NotGen0_WriteWatch_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_Lower movabs r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x73, 0x01 - // jae NotLow_WriteWatch_Byte_Region64 + // jae LOCAL_LABEL(NotLow_WriteWatch_Byte_Region64) ret - NotLow_WriteWatch_Byte_Region64: + LOCAL_LABEL(NotLow_WriteWatch_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_Upper mov r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x72, 0x02 - // jb NotHigh_WriteWatch_Byte_Region64 + // jb LOCAL_LABEL(NotHigh_WriteWatch_Byte_Region64) REPRET - NotHigh_WriteWatch_Byte_Region64: + LOCAL_LABEL(NotHigh_WriteWatch_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_RegionShrSrc shr rsi, 0x16 // compute region index mov dl, [rsi + rax] cmp dl, [rdi + rax] .byte 0x72, 0x03 - // jb IsOldToYoung_WriteWatch_Byte_Region64 + // jb LOCAL_LABEL(IsOldToYoung_WriteWatch_Byte_Region64) REPRET nop - IsOldToYoung_WriteWatch_Byte_Region64: + LOCAL_LABEL(IsOldToYoung_WriteWatch_Byte_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_CardTable mov rax, 0xF0F0F0F0F0F0F0F0 shr r8, 0xB cmp byte ptr [r8 + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardTable_WriteWatch_Byte_Region64 + // jne LOCAL_LABEL(UpdateCardTable_WriteWatch_Byte_Region64) REPRET - UpdateCardTable_WriteWatch_Byte_Region64: + LOCAL_LABEL(UpdateCardTable_WriteWatch_Byte_Region64): mov byte ptr [r8 + rax], 0xFF #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES shr r8, 0x0A @@ -690,10 +690,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Byte_Region64_Patch_Label_CardBundleTabl mov rax, 0xF0F0F0F0F0F0F0F0 cmp byte ptr [r8 + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundleTable_WriteWatch_Byte_Region64 + // jne LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Byte_Region64) REPRET - UpdateCardBundleTable_WriteWatch_Byte_Region64: + LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Byte_Region64): mov byte ptr [r8 + rax], 0xFF #endif ret @@ -718,47 +718,47 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_RegionShrDest shr rdi, 0x16 // compute region index cmp byte ptr [rax], 0x0 .byte 0x75, 0x03 - // jne CheckGen0_WriteWatch_Bit_Region64 + // jne LOCAL_LABEL(CheckGen0_WriteWatch_Bit_Region64) mov byte ptr [rax], 0xFF - CheckGen0_WriteWatch_Bit_Region64: + LOCAL_LABEL(CheckGen0_WriteWatch_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_RegionToGeneration mov rax, 0xF0F0F0F0F0F0F0F0 // Check whether the region we're storing into is gen 0 - nothing to do in this case cmp byte ptr [rdi + rax], 0 .byte 0x75, 0x08 - // jne NotGen0_WriteWatch_Bit_Region64 + // jne LOCAL_LABEL(NotGen0_WriteWatch_Bit_Region64) REPRET NOP_2_BYTE // padding for alignment of constant NOP_2_BYTE // padding for alignment of constant NOP_2_BYTE // padding for alignment of constant - NotGen0_WriteWatch_Bit_Region64: + LOCAL_LABEL(NotGen0_WriteWatch_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_Lower movabs r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x73, 0x01 - // jae NotLow_WriteWatch_Bit_Region64 + // jae LOCAL_LABEL(NotLow_WriteWatch_Bit_Region64) ret - NotLow_WriteWatch_Bit_Region64: + LOCAL_LABEL(NotLow_WriteWatch_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_Upper mov r9, 0xF0F0F0F0F0F0F0F0 cmp rsi, r9 .byte 0x72, 0x02 - // jb NotHigh_WriteWatch_Bit_Region64 + // jb LOCAL_LABEL(NotHigh_WriteWatch_Bit_Region64) REPRET - NotHigh_WriteWatch_Bit_Region64: + LOCAL_LABEL(NotHigh_WriteWatch_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_RegionShrSrc shr rsi, 0x16 // compute region index mov dl, [rsi + rax] cmp dl, [rdi + rax] .byte 0x72, 0x03 - // jb IsOldToYoung_WriteWatch_Bit_Region64 + // jb LOCAL_LABEL(IsOldToYoung_WriteWatch_Bit_Region64) REPRET nop - IsOldToYoung_WriteWatch_Bit_Region64: + LOCAL_LABEL(IsOldToYoung_WriteWatch_Bit_Region64): PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardTable mov rax, 0xF0F0F0F0F0F0F0F0 @@ -770,10 +770,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardTable shl dl, cl test byte ptr [r8 + rax], dl .byte 0x74, 0x02 - // je UpdateCardTable_WriteWatch_Bit_Region64 + // je LOCAL_LABEL(UpdateCardTable_WriteWatch_Bit_Region64) REPRET - UpdateCardTable_WriteWatch_Bit_Region64: + LOCAL_LABEL(UpdateCardTable_WriteWatch_Bit_Region64): lock or byte ptr [r8 + rax], dl #ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardBundleTable @@ -781,10 +781,10 @@ PATCH_LABEL JIT_WriteBarrier_WriteWatch_Bit_Region64_Patch_Label_CardBundleTable shr r8, 0x0A cmp byte ptr [r8 + rax], 0xFF .byte 0x75, 0x02 - // jne UpdateCardBundleTable_WriteWatch_Bit_Region64 + // jne LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Bit_Region64) REPRET - UpdateCardBundleTable_WriteWatch_Bit_Region64: + LOCAL_LABEL(UpdateCardBundleTable_WriteWatch_Bit_Region64): mov byte ptr [r8 + rax], 0xFF #endif ret From 4227c87c85e32a971597011d026c42b10bcf1351 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 1 Sep 2025 21:08:54 +0200 Subject: [PATCH 2/6] Fix the LEAF_END_MARKED macro for Apple platforms too --- src/coreclr/pal/inc/unixasmmacrosamd64.inc | 7 ++++++- src/coreclr/pal/inc/unixasmmacrosarm64.inc | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/coreclr/pal/inc/unixasmmacrosamd64.inc b/src/coreclr/pal/inc/unixasmmacrosamd64.inc index 880a282813f738..1d3d11c7d24ab0 100644 --- a/src/coreclr/pal/inc/unixasmmacrosamd64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosamd64.inc @@ -53,8 +53,13 @@ C_FUNC(\Name): .endm .macro LEAF_END_MARKED Name, Section -C_FUNC(\Name\()_End): +#if defined(__APPLE__) + .alt_entry C_FUNC(\Name\()_End) + .private_extern C_FUNC(\Name\()_End) +#else .global C_FUNC(\Name\()_End) +#endif +C_FUNC(\Name\()_End): LEAF_END \Name, \Section // make sure this symbol gets its own address nop diff --git a/src/coreclr/pal/inc/unixasmmacrosarm64.inc b/src/coreclr/pal/inc/unixasmmacrosarm64.inc index ae5854a995c947..fa4265ab3fc9d2 100644 --- a/src/coreclr/pal/inc/unixasmmacrosarm64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosarm64.inc @@ -64,8 +64,13 @@ C_FUNC(\Name): .endm .macro LEAF_END_MARKED Name, Section -C_FUNC(\Name\()_End): +#if defined(__APPLE__) + .alt_entry C_FUNC(\Name\()_End) + .private_extern C_FUNC(\Name\()_End) +#else .global C_FUNC(\Name\()_End) +#endif +C_FUNC(\Name\()_End): LEAF_END \Name, \Section // make sure this symbol gets its own address nop From 35bb12c59eb7d7074827179d0d9703d302b7338d Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 2 Sep 2025 15:24:41 +0200 Subject: [PATCH 3/6] Mark all labels inside JIT_PatchedCode region as .alt_entry on Apple platforms --- src/coreclr/pal/inc/unixasmmacrosamd64.inc | 19 +++++++++++++++++++ src/coreclr/pal/inc/unixasmmacrosarm64.inc | 19 +++++++++++++++++++ src/coreclr/vm/amd64/patchedcode.S | 6 +++--- src/coreclr/vm/arm64/patchedcode.S | 4 ++-- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/coreclr/pal/inc/unixasmmacrosamd64.inc b/src/coreclr/pal/inc/unixasmmacrosamd64.inc index 1d3d11c7d24ab0..ae5c48b8ceca6c 100644 --- a/src/coreclr/pal/inc/unixasmmacrosamd64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosamd64.inc @@ -52,6 +52,25 @@ C_FUNC(\Name): .cfi_endproc .endm +// Special version of the LEAF_ENTRY macro that should be used inside +// patchable code region to prevent the linker from relocating the code. +// On most Unix platforms this is identical to LEAF_ENTRY. However, on +// Apple platforms it produces the function entry points at .alt_entry +// symbols that create external labels but keep the whole patched region +// as single atom for the linker. +.macro LEAF_ENTRY_PATCHABLE Name, Section +#if defined(__APPLE__) + .text + .p2align 4 + .alt_entry C_FUNC(\Name) + .private_extern C_FUNC(\Name) +C_FUNC(\Name): + .cfi_startproc +#else + LEAF_ENTRY \Name, \Section +#endif +.endm + .macro LEAF_END_MARKED Name, Section #if defined(__APPLE__) .alt_entry C_FUNC(\Name\()_End) diff --git a/src/coreclr/pal/inc/unixasmmacrosarm64.inc b/src/coreclr/pal/inc/unixasmmacrosarm64.inc index fa4265ab3fc9d2..446c9540fa7a25 100644 --- a/src/coreclr/pal/inc/unixasmmacrosarm64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosarm64.inc @@ -63,6 +63,25 @@ C_FUNC(\Name): .cfi_endproc .endm +// Special version of the LEAF_ENTRY macro that should be used inside +// patchable code region to prevent the linker from relocating the code. +// On most Unix platforms this is identical to LEAF_ENTRY. However, on +// Apple platforms it produces the function entry points at .alt_entry +// symbols that create external labels but keep the whole patched region +// as single atom for the linker. +.macro LEAF_ENTRY_PATCHABLE Name, Section +#if defined(__APPLE__) + .text + .p2align 2 + .alt_entry C_FUNC(\Name) + .private_extern C_FUNC(\Name) +C_FUNC(\Name): + .cfi_startproc +#else + LEAF_ENTRY \Name, \Section +#endif +.endm + .macro LEAF_END_MARKED Name, Section #if defined(__APPLE__) .alt_entry C_FUNC(\Name\()_End) diff --git a/src/coreclr/vm/amd64/patchedcode.S b/src/coreclr/vm/amd64/patchedcode.S index 9af4e3ce855b70..21958ef54c86c0 100644 --- a/src/coreclr/vm/amd64/patchedcode.S +++ b/src/coreclr/vm/amd64/patchedcode.S @@ -24,7 +24,7 @@ LEAF_END JIT_PatchedCodeStart, _TEXT // it needs to have it's card updated // // void JIT_CheckedWriteBarrier(Object** dst, Object* src) -LEAF_ENTRY JIT_CheckedWriteBarrier, _TEXT +LEAF_ENTRY_PATCHABLE JIT_CheckedWriteBarrier, _TEXT // When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference // but if it isn't then it will just return. @@ -54,7 +54,7 @@ LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT // larger of the two functions (JIT_WriteBarrier_PostGrow) to ensure we have created // enough space to copy that code in. .balign 16 -LEAF_ENTRY JIT_WriteBarrier, _TEXT +LEAF_ENTRY_PATCHABLE JIT_WriteBarrier, _TEXT #ifdef _DEBUG // In debug builds, this just contains jump to the debug version of the write barrier by default jmp C_FUNC(JIT_WriteBarrier_Debug) @@ -240,6 +240,6 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT LEAF_END_MARKED JIT_WriteBarrier, _TEXT // Mark start of the code region that we patch at runtime -LEAF_ENTRY JIT_PatchedCodeLast, _TEXT +LEAF_ENTRY_PATCHABLE JIT_PatchedCodeLast, _TEXT ret LEAF_END JIT_PatchedCodeLast, _TEXT diff --git a/src/coreclr/vm/arm64/patchedcode.S b/src/coreclr/vm/arm64/patchedcode.S index 2bea90942e66a4..21ea17185a819f 100644 --- a/src/coreclr/vm/arm64/patchedcode.S +++ b/src/coreclr/vm/arm64/patchedcode.S @@ -13,7 +13,7 @@ // to declare a write barrier function. // .macro WRITE_BARRIER_ENTRY name - LEAF_ENTRY \name, _TEXT + LEAF_ENTRY_PATCHABLE \name, _TEXT .endm // WRITE_BARRIER_END @@ -145,7 +145,7 @@ WRITE_BARRIER_END JIT_WriteBarrier_Table // ------------------------------------------------------------------ // End of the writeable code region -LEAF_ENTRY JIT_PatchedCodeLast, _TEXT +LEAF_ENTRY_PATCHABLE JIT_PatchedCodeLast, _TEXT ret lr LEAF_END JIT_PatchedCodeLast, _TEXT From 127d98c29728e56e43b3081cca2bf5b1e3a6db6f Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 3 Sep 2025 10:38:10 +0200 Subject: [PATCH 4/6] Another take at eliminating UB in patchedcode.S with Apple linkers --- src/coreclr/pal/inc/unixasmmacrosamd64.inc | 19 ------- src/coreclr/pal/inc/unixasmmacrosarm64.inc | 19 ------- src/coreclr/vm/amd64/patchedcode.S | 66 ++++++++++++++++++++-- src/coreclr/vm/arm64/patchedcode.S | 42 +++++++++++++- 4 files changed, 100 insertions(+), 46 deletions(-) diff --git a/src/coreclr/pal/inc/unixasmmacrosamd64.inc b/src/coreclr/pal/inc/unixasmmacrosamd64.inc index ae5c48b8ceca6c..1d3d11c7d24ab0 100644 --- a/src/coreclr/pal/inc/unixasmmacrosamd64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosamd64.inc @@ -52,25 +52,6 @@ C_FUNC(\Name): .cfi_endproc .endm -// Special version of the LEAF_ENTRY macro that should be used inside -// patchable code region to prevent the linker from relocating the code. -// On most Unix platforms this is identical to LEAF_ENTRY. However, on -// Apple platforms it produces the function entry points at .alt_entry -// symbols that create external labels but keep the whole patched region -// as single atom for the linker. -.macro LEAF_ENTRY_PATCHABLE Name, Section -#if defined(__APPLE__) - .text - .p2align 4 - .alt_entry C_FUNC(\Name) - .private_extern C_FUNC(\Name) -C_FUNC(\Name): - .cfi_startproc -#else - LEAF_ENTRY \Name, \Section -#endif -.endm - .macro LEAF_END_MARKED Name, Section #if defined(__APPLE__) .alt_entry C_FUNC(\Name\()_End) diff --git a/src/coreclr/pal/inc/unixasmmacrosarm64.inc b/src/coreclr/pal/inc/unixasmmacrosarm64.inc index 446c9540fa7a25..fa4265ab3fc9d2 100644 --- a/src/coreclr/pal/inc/unixasmmacrosarm64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosarm64.inc @@ -63,25 +63,6 @@ C_FUNC(\Name): .cfi_endproc .endm -// Special version of the LEAF_ENTRY macro that should be used inside -// patchable code region to prevent the linker from relocating the code. -// On most Unix platforms this is identical to LEAF_ENTRY. However, on -// Apple platforms it produces the function entry points at .alt_entry -// symbols that create external labels but keep the whole patched region -// as single atom for the linker. -.macro LEAF_ENTRY_PATCHABLE Name, Section -#if defined(__APPLE__) - .text - .p2align 2 - .alt_entry C_FUNC(\Name) - .private_extern C_FUNC(\Name) -C_FUNC(\Name): - .cfi_startproc -#else - LEAF_ENTRY \Name, \Section -#endif -.endm - .macro LEAF_END_MARKED Name, Section #if defined(__APPLE__) .alt_entry C_FUNC(\Name\()_End) diff --git a/src/coreclr/vm/amd64/patchedcode.S b/src/coreclr/vm/amd64/patchedcode.S index 21958ef54c86c0..43cb6c54c598bc 100644 --- a/src/coreclr/vm/amd64/patchedcode.S +++ b/src/coreclr/vm/amd64/patchedcode.S @@ -5,10 +5,58 @@ #include "unixasmmacros.inc" #include "asmconstants.h" +// On Apple platforms we emit the whole patched region as single function +// with .alt_entry labels for individual write barrier helpers. This ensures +// the linker doesn't relocate or split the code and treats it as single +// atom. We also need to be careful to produce the correct unwinding +// information. + +//----------------------------------------------------------------------------- +// The following Macros help in WRITE_BARRIER Implementations +// WRITE_BARRIER_ENTRY +// +// Declare the start of a write barrier function. Use similarly to NESTED_ENTRY. This is the only legal way +// to declare a write barrier function. +// +.macro WRITE_BARRIER_ENTRY name +#if defined(__APPLE__) + .text + .p2align 4 + .alt_entry C_FUNC(\name) + .private_extern C_FUNC(\name) +C_FUNC(\name): +#else + LEAF_ENTRY \name, _TEXT +#endif +.endm + +// WRITE_BARRIER_END +// +// The partner to WRITE_BARRIER_ENTRY, used like NESTED_END. +// +.macro WRITE_BARRIER_END name +#if defined(__APPLE__) + .alt_entry C_FUNC(\name\()_End) + .private_extern C_FUNC(\name\()_End) +C_FUNC(\name\()_End): + // make sure this symbol gets its own address + nop +#else + LEAF_END_MARKED \name, _TEXT +#endif +.endm + // Mark start of the code region that we patch at runtime +#if defined(__APPLE__) + .global C_FUNC(JIT_PatchedCodeStart) +C_FUNC(JIT_PatchedCodeStart): + .cfi_startproc + ret +#else LEAF_ENTRY JIT_PatchedCodeStart, _TEXT ret LEAF_END JIT_PatchedCodeStart, _TEXT +#endif // There is an even more optimized version of these helpers possible which takes @@ -24,7 +72,7 @@ LEAF_END JIT_PatchedCodeStart, _TEXT // it needs to have it's card updated // // void JIT_CheckedWriteBarrier(Object** dst, Object* src) -LEAF_ENTRY_PATCHABLE JIT_CheckedWriteBarrier, _TEXT +WRITE_BARRIER_ENTRY JIT_CheckedWriteBarrier // When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference // but if it isn't then it will just return. @@ -45,7 +93,7 @@ LEAF_ENTRY_PATCHABLE JIT_CheckedWriteBarrier, _TEXT // See comment above about possible AV mov [rdi], rsi ret -LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT +WRITE_BARRIER_END JIT_CheckedWriteBarrier // This is used by the mechanism to hold either the JIT_WriteBarrier_PreGrow @@ -54,7 +102,7 @@ LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT // larger of the two functions (JIT_WriteBarrier_PostGrow) to ensure we have created // enough space to copy that code in. .balign 16 -LEAF_ENTRY_PATCHABLE JIT_WriteBarrier, _TEXT +WRITE_BARRIER_ENTRY JIT_WriteBarrier #ifdef _DEBUG // In debug builds, this just contains jump to the debug version of the write barrier by default jmp C_FUNC(JIT_WriteBarrier_Debug) @@ -237,9 +285,17 @@ LEAF_ENTRY_PATCHABLE JIT_WriteBarrier, _TEXT // make sure this is bigger than any of the others .balign 16 nop -LEAF_END_MARKED JIT_WriteBarrier, _TEXT +WRITE_BARRIER_END JIT_WriteBarrier // Mark start of the code region that we patch at runtime -LEAF_ENTRY_PATCHABLE JIT_PatchedCodeLast, _TEXT +#if defined(__APPLE__) + .private_extern C_FUNC(JIT_PatchedCodeLast) + .alt_entry C_FUNC(JIT_PatchedCodeLast) +C_FUNC(JIT_PatchedCodeLast): + .cfi_endproc + ret +#else +LEAF_ENTRY JIT_PatchedCodeLast, _TEXT ret LEAF_END JIT_PatchedCodeLast, _TEXT +#endif diff --git a/src/coreclr/vm/arm64/patchedcode.S b/src/coreclr/vm/arm64/patchedcode.S index 21ea17185a819f..13bce31a4cfaea 100644 --- a/src/coreclr/vm/arm64/patchedcode.S +++ b/src/coreclr/vm/arm64/patchedcode.S @@ -5,6 +5,12 @@ #include "unixasmmacros.inc" #include "patchedcodeconstants.h" +// On Apple platforms we emit the whole patched region as single function +// with .alt_entry labels for individual write barrier helpers. This ensures +// the linker doesn't relocate or split the code and treats it as single +// atom. We also need to be careful to produce the correct unwinding +// information. + //----------------------------------------------------------------------------- // The following Macros help in WRITE_BARRIER Implementations // WRITE_BARRIER_ENTRY @@ -13,7 +19,15 @@ // to declare a write barrier function. // .macro WRITE_BARRIER_ENTRY name - LEAF_ENTRY_PATCHABLE \name, _TEXT +#if defined(__APPLE__) + .text + .p2align 2 + .alt_entry C_FUNC(\name) + .private_extern C_FUNC(\name) +C_FUNC(\name): +#else + LEAF_ENTRY \name, _TEXT +#endif .endm // WRITE_BARRIER_END @@ -21,15 +35,30 @@ // The partner to WRITE_BARRIER_ENTRY, used like NESTED_END. // .macro WRITE_BARRIER_END name +#if defined(__APPLE__) + .alt_entry C_FUNC(\name\()_End) + .private_extern C_FUNC(\name\()_End) +C_FUNC(\name\()_End): + // make sure this symbol gets its own address + nop +#else LEAF_END_MARKED \name, _TEXT +#endif .endm .balign 64 // Align to power of two at least as big as patchable literal pool so that it fits optimally in cache line //------------------------------------------ // Start of the writeable code region +#if defined(__APPLE__) + .global C_FUNC(JIT_PatchedCodeStart) +C_FUNC(JIT_PatchedCodeStart): + .cfi_startproc + ret lr +#else LEAF_ENTRY JIT_PatchedCodeStart, _TEXT ret lr LEAF_END JIT_PatchedCodeStart, _TEXT +#endif //----------------------------------------------------------------------------- // void JIT_ByRefWriteBarrier @@ -145,10 +174,17 @@ WRITE_BARRIER_END JIT_WriteBarrier_Table // ------------------------------------------------------------------ // End of the writeable code region -LEAF_ENTRY_PATCHABLE JIT_PatchedCodeLast, _TEXT +#if defined(__APPLE__) + .private_extern C_FUNC(JIT_PatchedCodeLast) + .alt_entry C_FUNC(JIT_PatchedCodeLast) +C_FUNC(JIT_PatchedCodeLast): + .cfi_endproc + ret lr +#else +LEAF_ENTRY JIT_PatchedCodeLast, _TEXT ret lr LEAF_END JIT_PatchedCodeLast, _TEXT - +#endif //----------------------------------------------------------------------------- From 31b47d777ed91e9b3757211e16c98db6fe7c05bb Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 5 Sep 2025 13:30:26 +0200 Subject: [PATCH 5/6] Workaround for broken unwind info --- src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S | 2 +- src/coreclr/vm/amd64/patchedcode.S | 7 ++++++- src/coreclr/vm/arm64/patchedcode.S | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S b/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S index bc0edaccea0567..9b2345591947d6 100644 --- a/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S +++ b/src/coreclr/vm/amd64/CachedInterfaceDispatchCoreCLR.S @@ -23,7 +23,7 @@ LEAF_ENTRY RhpVTableOffsetDispatch, _TEXT // to get the address in the vtable chunk list of what we want to dereference #ifdef TARGET_APPLE // Apple's linker has issues which break unwind info if -// an ALTERNATE_ENTRY is present in the middle of a function see https://github.com/dotnet/runtime/pull/114982#discussion_r2083272768 +// an ALTERNATE_ENTRY is present in the middle of a function see https://github.com/dotnet/runtime/issues/119005 .cfi_endproc #endif ALTERNATE_ENTRY RhpVTableOffsetDispatchAVLocation diff --git a/src/coreclr/vm/amd64/patchedcode.S b/src/coreclr/vm/amd64/patchedcode.S index 43cb6c54c598bc..0c0173bf184e33 100644 --- a/src/coreclr/vm/amd64/patchedcode.S +++ b/src/coreclr/vm/amd64/patchedcode.S @@ -20,11 +20,13 @@ // .macro WRITE_BARRIER_ENTRY name #if defined(__APPLE__) - .text + // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005 + .cfi_endproc .p2align 4 .alt_entry C_FUNC(\name) .private_extern C_FUNC(\name) C_FUNC(\name): + .cfi_startproc #else LEAF_ENTRY \name, _TEXT #endif @@ -36,9 +38,12 @@ C_FUNC(\name): // .macro WRITE_BARRIER_END name #if defined(__APPLE__) + // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005 + .cfi_endproc .alt_entry C_FUNC(\name\()_End) .private_extern C_FUNC(\name\()_End) C_FUNC(\name\()_End): + .cfi_startproc // make sure this symbol gets its own address nop #else diff --git a/src/coreclr/vm/arm64/patchedcode.S b/src/coreclr/vm/arm64/patchedcode.S index 13bce31a4cfaea..248375142d2c49 100644 --- a/src/coreclr/vm/arm64/patchedcode.S +++ b/src/coreclr/vm/arm64/patchedcode.S @@ -20,11 +20,13 @@ // .macro WRITE_BARRIER_ENTRY name #if defined(__APPLE__) - .text + // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005 + .cfi_endproc .p2align 2 .alt_entry C_FUNC(\name) .private_extern C_FUNC(\name) C_FUNC(\name): + .cfi_startproc #else LEAF_ENTRY \name, _TEXT #endif @@ -36,9 +38,12 @@ C_FUNC(\name): // .macro WRITE_BARRIER_END name #if defined(__APPLE__) + // .cfi_startproc/.cfi_endproc is workaround for https://github.com/dotnet/runtime/issues/119005 + .cfi_endproc .alt_entry C_FUNC(\name\()_End) .private_extern C_FUNC(\name\()_End) C_FUNC(\name\()_End): + .cfi_startproc // make sure this symbol gets its own address nop #else From 977ca13f9506d37e0b2c304d1e92ad861362ae6d Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 8 Sep 2025 15:34:42 +0200 Subject: [PATCH 6/6] Use classic linker on Xcode 15 --- eng/native/configurecompiler.cmake | 7 +++++++ src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index d54d9b6803b9e7..f3884d0fb6c672 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -34,6 +34,13 @@ if (CLR_CMAKE_HOST_UNIX) endif() endif() +# Force usage of classic linker on Xcode 15 +if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15 AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) + add_link_options("-Wl,-ld_classic") +endif() + if (CMAKE_CONFIGURATION_TYPES) # multi-configuration generator? set(CMAKE_CONFIGURATION_TYPES "Debug;Checked;Release;RelWithDebInfo" CACHE STRING "" FORCE) endif (CMAKE_CONFIGURATION_TYPES) diff --git a/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S b/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S index 068936ef5235e2..d4da67291443ab 100644 --- a/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S +++ b/src/coreclr/vm/arm64/CachedInterfaceDispatchCoreCLR.S @@ -6,6 +6,10 @@ #ifdef FEATURE_CACHED_INTERFACE_DISPATCH + // Workaround for Xcode 15 ld-classic linker which cannot deal with + // .alt_entry labels at beginning of section. + nop + // // Stub dispatch routine for dispatch to a vtable slot //