Skip to content

Commit 969e3c4

Browse files
committed
Another take at eliminating UB in patchedcode.S with Apple linkers
1 parent d2bb5f3 commit 969e3c4

File tree

4 files changed

+100
-46
lines changed

4 files changed

+100
-46
lines changed

src/coreclr/pal/inc/unixasmmacrosamd64.inc

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,6 @@ C_FUNC(\Name):
5252
.cfi_endproc
5353
.endm
5454

55-
// Special version of the LEAF_ENTRY macro that should be used inside
56-
// patchable code region to prevent the linker from relocating the code.
57-
// On most Unix platforms this is identical to LEAF_ENTRY. However, on
58-
// Apple platforms it produces the function entry points at .alt_entry
59-
// symbols that create external labels but keep the whole patched region
60-
// as single atom for the linker.
61-
.macro LEAF_ENTRY_PATCHABLE Name, Section
62-
#if defined(__APPLE__)
63-
.text
64-
.p2align 4
65-
.alt_entry C_FUNC(\Name)
66-
.private_extern C_FUNC(\Name)
67-
C_FUNC(\Name):
68-
.cfi_startproc
69-
#else
70-
LEAF_ENTRY \Name, \Section
71-
#endif
72-
.endm
73-
7455
.macro LEAF_END_MARKED Name, Section
7556
#if defined(__APPLE__)
7657
.alt_entry C_FUNC(\Name\()_End)

src/coreclr/pal/inc/unixasmmacrosarm64.inc

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,6 @@ C_FUNC(\Name):
6363
.cfi_endproc
6464
.endm
6565

66-
// Special version of the LEAF_ENTRY macro that should be used inside
67-
// patchable code region to prevent the linker from relocating the code.
68-
// On most Unix platforms this is identical to LEAF_ENTRY. However, on
69-
// Apple platforms it produces the function entry points at .alt_entry
70-
// symbols that create external labels but keep the whole patched region
71-
// as single atom for the linker.
72-
.macro LEAF_ENTRY_PATCHABLE Name, Section
73-
#if defined(__APPLE__)
74-
.text
75-
.p2align 2
76-
.alt_entry C_FUNC(\Name)
77-
.private_extern C_FUNC(\Name)
78-
C_FUNC(\Name):
79-
.cfi_startproc
80-
#else
81-
LEAF_ENTRY \Name, \Section
82-
#endif
83-
.endm
84-
8566
.macro LEAF_END_MARKED Name, Section
8667
#if defined(__APPLE__)
8768
.alt_entry C_FUNC(\Name\()_End)

src/coreclr/vm/amd64/patchedcode.S

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,58 @@
55
#include "unixasmmacros.inc"
66
#include "asmconstants.h"
77

8+
// On Apple platforms we emit the whole patched region as single function
9+
// with .alt_entry labels for individual write barrier helpers. This ensures
10+
// the linker doesn't relocate or split the code and treats it as single
11+
// atom. We also need to be careful to produce the correct unwinding
12+
// information.
13+
14+
//-----------------------------------------------------------------------------
15+
// The following Macros help in WRITE_BARRIER Implementations
16+
// WRITE_BARRIER_ENTRY
17+
//
18+
// Declare the start of a write barrier function. Use similarly to NESTED_ENTRY. This is the only legal way
19+
// to declare a write barrier function.
20+
//
21+
.macro WRITE_BARRIER_ENTRY name
22+
#if defined(__APPLE__)
23+
.text
24+
.p2align 4
25+
.alt_entry C_FUNC(\name)
26+
.private_extern C_FUNC(\name)
27+
C_FUNC(\name):
28+
#else
29+
LEAF_ENTRY \name, _TEXT
30+
#endif
31+
.endm
32+
33+
// WRITE_BARRIER_END
34+
//
35+
// The partner to WRITE_BARRIER_ENTRY, used like NESTED_END.
36+
//
37+
.macro WRITE_BARRIER_END name
38+
#if defined(__APPLE__)
39+
.alt_entry C_FUNC(\name\()_End)
40+
.private_extern C_FUNC(\name\()_End)
41+
C_FUNC(\name\()_End):
42+
// make sure this symbol gets its own address
43+
nop
44+
#else
45+
LEAF_END_MARKED \name, _TEXT
46+
#endif
47+
.endm
48+
849
// Mark start of the code region that we patch at runtime
50+
#if defined(__APPLE__)
51+
.global C_FUNC(JIT_PatchedCodeStart)
52+
C_FUNC(JIT_PatchedCodeStart):
53+
.cfi_startproc
54+
ret
55+
#else
956
LEAF_ENTRY JIT_PatchedCodeStart, _TEXT
1057
ret
1158
LEAF_END JIT_PatchedCodeStart, _TEXT
59+
#endif
1260

1361

1462
// There is an even more optimized version of these helpers possible which takes
@@ -24,7 +72,7 @@ LEAF_END JIT_PatchedCodeStart, _TEXT
2472
// it needs to have it's card updated
2573
//
2674
// void JIT_CheckedWriteBarrier(Object** dst, Object* src)
27-
LEAF_ENTRY_PATCHABLE JIT_CheckedWriteBarrier, _TEXT
75+
WRITE_BARRIER_ENTRY JIT_CheckedWriteBarrier
2876

2977
// When WRITE_BARRIER_CHECK is defined _NotInHeap will write the reference
3078
// but if it isn't then it will just return.
@@ -45,7 +93,7 @@ LEAF_ENTRY_PATCHABLE JIT_CheckedWriteBarrier, _TEXT
4593
// See comment above about possible AV
4694
mov [rdi], rsi
4795
ret
48-
LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT
96+
WRITE_BARRIER_END JIT_CheckedWriteBarrier
4997

5098

5199
// This is used by the mechanism to hold either the JIT_WriteBarrier_PreGrow
@@ -54,7 +102,7 @@ LEAF_END_MARKED JIT_CheckedWriteBarrier, _TEXT
54102
// larger of the two functions (JIT_WriteBarrier_PostGrow) to ensure we have created
55103
// enough space to copy that code in.
56104
.balign 16
57-
LEAF_ENTRY_PATCHABLE JIT_WriteBarrier, _TEXT
105+
WRITE_BARRIER_ENTRY JIT_WriteBarrier
58106
#ifdef _DEBUG
59107
// In debug builds, this just contains jump to the debug version of the write barrier by default
60108
jmp C_FUNC(JIT_WriteBarrier_Debug)
@@ -237,9 +285,17 @@ LEAF_ENTRY_PATCHABLE JIT_WriteBarrier, _TEXT
237285
// make sure this is bigger than any of the others
238286
.balign 16
239287
nop
240-
LEAF_END_MARKED JIT_WriteBarrier, _TEXT
288+
WRITE_BARRIER_END JIT_WriteBarrier
241289

242290
// Mark start of the code region that we patch at runtime
243-
LEAF_ENTRY_PATCHABLE JIT_PatchedCodeLast, _TEXT
291+
#if defined(__APPLE__)
292+
.private_extern C_FUNC(JIT_PatchedCodeLast)
293+
.alt_entry C_FUNC(JIT_PatchedCodeLast)
294+
C_FUNC(JIT_PatchedCodeLast):
295+
.cfi_endproc
296+
ret
297+
#else
298+
LEAF_ENTRY JIT_PatchedCodeLast, _TEXT
244299
ret
245300
LEAF_END JIT_PatchedCodeLast, _TEXT
301+
#endif

src/coreclr/vm/arm64/patchedcode.S

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
#include "unixasmmacros.inc"
66
#include "patchedcodeconstants.h"
77

8+
// On Apple platforms we emit the whole patched region as single function
9+
// with .alt_entry labels for individual write barrier helpers. This ensures
10+
// the linker doesn't relocate or split the code and treats it as single
11+
// atom. We also need to be careful to produce the correct unwinding
12+
// information.
13+
814
//-----------------------------------------------------------------------------
915
// The following Macros help in WRITE_BARRIER Implementations
1016
// WRITE_BARRIER_ENTRY
@@ -13,23 +19,46 @@
1319
// to declare a write barrier function.
1420
//
1521
.macro WRITE_BARRIER_ENTRY name
16-
LEAF_ENTRY_PATCHABLE \name, _TEXT
22+
#if defined(__APPLE__)
23+
.text
24+
.p2align 2
25+
.alt_entry C_FUNC(\name)
26+
.private_extern C_FUNC(\name)
27+
C_FUNC(\name):
28+
#else
29+
LEAF_ENTRY \name, _TEXT
30+
#endif
1731
.endm
1832

1933
// WRITE_BARRIER_END
2034
//
2135
// The partner to WRITE_BARRIER_ENTRY, used like NESTED_END.
2236
//
2337
.macro WRITE_BARRIER_END name
38+
#if defined(__APPLE__)
39+
.alt_entry C_FUNC(\name\()_End)
40+
.private_extern C_FUNC(\name\()_End)
41+
C_FUNC(\name\()_End):
42+
// make sure this symbol gets its own address
43+
nop
44+
#else
2445
LEAF_END_MARKED \name, _TEXT
46+
#endif
2547
.endm
2648

2749
.balign 64 // Align to power of two at least as big as patchable literal pool so that it fits optimally in cache line
2850
//------------------------------------------
2951
// Start of the writeable code region
52+
#if defined(__APPLE__)
53+
.global C_FUNC(JIT_PatchedCodeStart)
54+
C_FUNC(JIT_PatchedCodeStart):
55+
.cfi_startproc
56+
ret lr
57+
#else
3058
LEAF_ENTRY JIT_PatchedCodeStart, _TEXT
3159
ret lr
3260
LEAF_END JIT_PatchedCodeStart, _TEXT
61+
#endif
3362

3463
//-----------------------------------------------------------------------------
3564
// void JIT_ByRefWriteBarrier
@@ -145,10 +174,17 @@ WRITE_BARRIER_END JIT_WriteBarrier_Table
145174

146175
// ------------------------------------------------------------------
147176
// End of the writeable code region
148-
LEAF_ENTRY_PATCHABLE JIT_PatchedCodeLast, _TEXT
177+
#if defined(__APPLE__)
178+
.private_extern C_FUNC(JIT_PatchedCodeLast)
179+
.alt_entry C_FUNC(JIT_PatchedCodeLast)
180+
C_FUNC(JIT_PatchedCodeLast):
181+
.cfi_endproc
182+
ret lr
183+
#else
184+
LEAF_ENTRY JIT_PatchedCodeLast, _TEXT
149185
ret lr
150186
LEAF_END JIT_PatchedCodeLast, _TEXT
151-
187+
#endif
152188

153189

154190
//-----------------------------------------------------------------------------

0 commit comments

Comments
 (0)