Skip to content

Commit f177ebd

Browse files
committed
Fix JIT_ByRefWriteBarrier unwinding on macOS x64
Local labels in the JIT_ByRefWriteBarrier were not wrapped in the LOCAL_LABEL macro. That causes incorrect unwinding in case an access violation occurs inside of this function. The closest label before the failure point is considered to be the actual function, but it obviously doesn't have the right unwind info. Close #89585
1 parent 7cffd46 commit f177ebd

File tree

2 files changed

+51
-51
lines changed

2 files changed

+51
-51
lines changed

src/coreclr/vm/amd64/jithelpers_fast.S

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ LEAF_ENTRY JIT_CheckedWriteBarrier, _TEXT
3232
// See if this is in GCHeap
3333
PREPARE_EXTERNAL_VAR g_lowest_address, rax
3434
cmp rdi, [rax]
35-
// jb NotInHeap
35+
// jb LOCAL_LABEL(NotInHeap)
3636
.byte 0x72, 0x12
3737
PREPARE_EXTERNAL_VAR g_highest_address, rax
3838
cmp rdi, [rax]
3939

40-
// jnb NotInHeap
40+
// jnb LOCAL_LABEL(NotInHeap)
4141
.byte 0x73, 0x06
4242
jmp [rip + C_FUNC(JIT_WriteBarrier_Loc)]
4343

44-
NotInHeap:
44+
LOCAL_LABEL(NotInHeap):
4545
// See comment above about possible AV
4646
mov [rdi], rsi
4747
ret
@@ -85,24 +85,24 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
8585
add rax, r10
8686
cmp byte ptr [rax], 0x0
8787
.byte 0x75, 0x06
88-
// jne CheckCardTable
88+
// jne LOCAL_LABEL(CheckCardTable)
8989
mov byte ptr [rax], 0xFF
9090

9191
NOP_3_BYTE // padding for alignment of constant
9292

9393
// Check the lower and upper ephemeral region bounds
94-
CheckCardTable:
94+
LOCAL_LABEL(CheckCardTable):
9595
cmp rsi, r11
9696
.byte 0x72,0x3D
97-
// jb Exit
97+
// jb LOCAL_LABEL(Exit)
9898

9999
NOP_3_BYTE // padding for alignment of constant
100100

101101
movabs r10, 0xF0F0F0F0F0F0F0F0
102102

103103
cmp rsi, r10
104104
.byte 0x73,0x2B
105-
// jae Exit
105+
// jae LOCAL_LABEL(Exit)
106106

107107
nop // padding for alignment of constant
108108

@@ -112,10 +112,10 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
112112
shr rdi, 0x0B
113113
cmp byte ptr [rdi + rax], 0xFF
114114
.byte 0x75, 0x02
115-
// jne UpdateCardTable
115+
// jne LOCAL_LABEL(UpdateCardTable)
116116
REPRET
117117

118-
UpdateCardTable:
118+
LOCAL_LABEL(UpdateCardTable):
119119
mov byte ptr [rdi + rax], 0xFF
120120

121121
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -126,17 +126,17 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
126126
cmp byte ptr [rdi + rax], 0xFF
127127

128128
.byte 0x75, 0x02
129-
// jne UpdateCardBundle_WriteWatch_PostGrow64
129+
// jne LOCAL_LABEL(UpdateCardBundle_WriteWatch_PostGrow64)
130130
REPRET
131131

132-
UpdateCardBundle_WriteWatch_PostGrow64:
132+
LOCAL_LABEL(UpdateCardBundle_WriteWatch_PostGrow64):
133133
mov byte ptr [rdi + rax], 0xFF
134134
#endif
135135

136136
ret
137137

138138
.balign 16
139-
Exit:
139+
LOCAL_LABEL(Exit):
140140
REPRET
141141

142142
NOP_3_BYTE
@@ -184,15 +184,15 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
184184

185185
// Check the lower and upper ephemeral region bounds
186186
cmp rsi, rax
187-
// jb Exit
187+
// jb LOCAL_LABEL(Exit)
188188
.byte 0x72, 0x36
189189

190190
nop // padding for alignment of constant
191191

192192
movabs r8, 0xF0F0F0F0F0F0F0F0
193193

194194
cmp rsi, r8
195-
// jae Exit
195+
// jae LOCAL_LABEL(Exit)
196196
.byte 0x73, 0x26
197197

198198
nop // padding for alignment of constant
@@ -203,10 +203,10 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
203203
shr rdi, 0Bh
204204
cmp byte ptr [rdi + rax], 0FFh
205205
.byte 0x75, 0x02
206-
// jne UpdateCardTable
206+
// jne LOCAL_LABEL(UpdateCardTable)
207207
REPRET
208208

209-
UpdateCardTable:
209+
LOCAL_LABEL(UpdateCardTable):
210210
mov byte ptr [rdi + rax], 0FFh
211211

212212
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
@@ -220,17 +220,17 @@ LEAF_ENTRY JIT_WriteBarrier, _TEXT
220220
cmp byte ptr [rdi + rax], 0FFh
221221

222222
.byte 0x75, 0x02
223-
// jne UpdateCardBundle
223+
// jne LOCAL_LABEL(UpdateCardBundle)
224224
REPRET
225225

226-
UpdateCardBundle:
226+
LOCAL_LABEL(UpdateCardBundle):
227227
mov byte ptr [rdi + rax], 0FFh
228228
#endif
229229

230230
ret
231231

232232
.balign 16
233-
Exit:
233+
LOCAL_LABEL(Exit):
234234
REPRET
235235
#endif
236236

@@ -277,30 +277,30 @@ LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
277277
// See if this is in GCHeap
278278
PREPARE_EXTERNAL_VAR g_lowest_address, rax
279279
cmp rdi, [rax]
280-
jb NotInHeap_ByRefWriteBarrier
280+
jb LOCAL_LABEL(NotInHeap_ByRefWriteBarrier)
281281
PREPARE_EXTERNAL_VAR g_highest_address, rax
282282
cmp rdi, [rax]
283-
jnb NotInHeap_ByRefWriteBarrier
283+
jnb LOCAL_LABEL(NotInHeap_ByRefWriteBarrier)
284284

285285
#ifdef WRITE_BARRIER_CHECK
286286
// **ALSO update the shadow GC heap if that is enabled**
287287
// Do not perform the work if g_GCShadow is 0
288288
PREPARE_EXTERNAL_VAR g_GCShadow, rax
289289
cmp qword ptr [rax], 0
290-
je NoShadow_ByRefWriteBarrier
290+
je LOCAL_LABEL(NoShadow_ByRefWriteBarrier)
291291

292292
// If we end up outside of the heap don't corrupt random memory
293293
mov r10, rdi
294294
PREPARE_EXTERNAL_VAR g_lowest_address, rax
295295
sub r10, [rax]
296-
jb NoShadow_ByRefWriteBarrier
296+
jb LOCAL_LABEL(NoShadow_ByRefWriteBarrier)
297297

298298
// Check that our adjusted destination is somewhere in the shadow gc
299299
PREPARE_EXTERNAL_VAR g_GCShadow, rax
300300
add r10, [rax]
301301
PREPARE_EXTERNAL_VAR g_GCShadowEnd, rax
302302
cmp r10, [rax]
303-
jnb NoShadow_ByRefWriteBarrier
303+
jnb LOCAL_LABEL(NoShadow_ByRefWriteBarrier)
304304

305305
// Write ref into real GC
306306
mov [rdi], rcx
@@ -315,73 +315,73 @@ LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
315315
mov r11, [rdi]
316316
mov rax, [r10]
317317
cmp rax, r11
318-
je DoneShadow_ByRefWriteBarrier
318+
je LOCAL_LABEL(DoneShadow_ByRefWriteBarrier)
319319
movabs r11, INVALIDGCVALUE
320320
mov [r10], r11
321321

322-
jmp DoneShadow_ByRefWriteBarrier
322+
jmp LOCAL_LABEL(DoneShadow_ByRefWriteBarrier)
323323

324324
// If we don't have a shadow GC we won't have done the write yet
325-
NoShadow_ByRefWriteBarrier:
325+
LOCAL_LABEL(NoShadow_ByRefWriteBarrier):
326326
mov [rdi], rcx
327327

328328
// If we had a shadow GC then we already wrote to the real GC at the same time
329329
// as the shadow GC so we want to jump over the real write immediately above.
330330
// Additionally we know for sure that we are inside the heap and therefore don't
331331
// need to replicate the above checks.
332-
DoneShadow_ByRefWriteBarrier:
332+
LOCAL_LABEL(DoneShadow_ByRefWriteBarrier):
333333
#endif
334334

335335
#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
336336
// Update the write watch table if necessary
337337
PREPARE_EXTERNAL_VAR g_sw_ww_enabled_for_gc_heap, rax
338338
cmp byte ptr [rax], 0x0
339-
je CheckCardTable_ByRefWriteBarrier
339+
je LOCAL_LABEL(CheckCardTable_ByRefWriteBarrier)
340340
mov rax, rdi
341341
shr rax, 0xC // SoftwareWriteWatch::AddressToTableByteIndexShift
342342
PREPARE_EXTERNAL_VAR g_sw_ww_table, r10
343343
add rax, qword ptr [r10]
344344
cmp byte ptr [rax], 0x0
345-
jne CheckCardTable_ByRefWriteBarrier
345+
jne LOCAL_LABEL(CheckCardTable_ByRefWriteBarrier)
346346
mov byte ptr [rax], 0xFF
347347
#endif
348348

349-
CheckCardTable_ByRefWriteBarrier:
349+
LOCAL_LABEL(CheckCardTable_ByRefWriteBarrier):
350350
// See if we can just quick out
351351
PREPARE_EXTERNAL_VAR g_ephemeral_low, rax
352352
cmp rcx, [rax]
353-
jb Exit_ByRefWriteBarrier
353+
jb LOCAL_LABEL(Exit_ByRefWriteBarrier)
354354
PREPARE_EXTERNAL_VAR g_ephemeral_high, rax
355355
cmp rcx, [rax]
356-
jnb Exit_ByRefWriteBarrier
356+
jnb LOCAL_LABEL(Exit_ByRefWriteBarrier)
357357

358358
mov rax, rcx
359359

360360
PREPARE_EXTERNAL_VAR g_region_shr, rcx
361361
mov cl, [rcx]
362362
test cl, cl
363-
je SkipCheck_ByRefWriteBarrier
363+
je LOCAL_LABEL(SkipCheck_ByRefWriteBarrier)
364364

365365
// check if the source is in gen 2 - then it's not an ephemeral pointer
366366
shr rax, cl
367367
PREPARE_EXTERNAL_VAR g_region_to_generation_table, r10
368368
mov r10, [r10]
369369
cmp byte ptr [rax + r10], 0x82
370-
je Exit_ByRefWriteBarrier
370+
je LOCAL_LABEL(Exit_ByRefWriteBarrier)
371371

372372
// check if the destination happens to be in gen 0
373373
mov rax, rdi
374374
shr rax, cl
375375
cmp byte ptr [rax + r10], 0
376-
je Exit_ByRefWriteBarrier
377-
SkipCheck_ByRefWriteBarrier:
376+
je LOCAL_LABEL(Exit_ByRefWriteBarrier)
377+
LOCAL_LABEL(SkipCheck_ByRefWriteBarrier):
378378

379379
PREPARE_EXTERNAL_VAR g_card_table, r10
380380
mov r10, [r10]
381381

382382
PREPARE_EXTERNAL_VAR g_region_use_bitwise_write_barrier, rax
383383
cmp byte ptr [rax], 0
384-
je CheckCardTableByte_ByRefWriteBarrier
384+
je LOCAL_LABEL(CheckCardTableByte_ByRefWriteBarrier)
385385

386386
// compute card table bit
387387
mov ecx, edi
@@ -400,28 +400,28 @@ LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
400400
shr rcx, 0xB
401401
// Check if this card table bit is already set
402402
test byte ptr [rcx + r10], al
403-
je SetCardTableBit_ByRefWriteBarrier
403+
je LOCAL_LABEL(SetCardTableBit_ByRefWriteBarrier)
404404
REPRET
405405

406-
SetCardTableBit_ByRefWriteBarrier:
406+
LOCAL_LABEL(SetCardTableBit_ByRefWriteBarrier):
407407
lock or byte ptr [rcx + r10], al
408408

409-
jmp CheckCardBundle_ByRefWriteBarrier
409+
jmp LOCAL_LABEL(CheckCardBundle_ByRefWriteBarrier)
410410

411-
CheckCardTableByte_ByRefWriteBarrier:
411+
LOCAL_LABEL(CheckCardTableByte_ByRefWriteBarrier):
412412
// move current rdi value into rcx and then increment the pointers
413413
mov rcx, rdi
414414
add rsi, 0x8
415415
add rdi, 0x8
416416

417417
shr rcx, 0xB
418418
cmp byte ptr [rcx + r10], 0xFF
419-
jne SetCardTableByte_ByRefWriteBarrier
419+
jne LOCAL_LABEL(SetCardTableByte_ByRefWriteBarrier)
420420
REPRET
421-
SetCardTableByte_ByRefWriteBarrier:
421+
LOCAL_LABEL(SetCardTableByte_ByRefWriteBarrier):
422422
mov byte ptr [rcx + r10], 0xFF
423423

424-
CheckCardBundle_ByRefWriteBarrier:
424+
LOCAL_LABEL(CheckCardBundle_ByRefWriteBarrier):
425425

426426
#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
427427
// Shift rcx by 0x0A more to get the card bundle byte (we shifted by 0x0B already)
@@ -433,25 +433,25 @@ LEAF_ENTRY JIT_ByRefWriteBarrier, _TEXT
433433
// Check if this bundle byte is dirty
434434
cmp byte ptr [rcx], 0xFF
435435

436-
jne UpdateCardBundle_ByRefWriteBarrier
436+
jne LOCAL_LABEL(UpdateCardBundle_ByRefWriteBarrier)
437437
REPRET
438438

439-
UpdateCardBundle_ByRefWriteBarrier:
439+
LOCAL_LABEL(UpdateCardBundle_ByRefWriteBarrier):
440440
mov byte ptr [rcx], 0xFF
441441
#endif
442442

443443
ret
444444

445445
.balign 16
446-
NotInHeap_ByRefWriteBarrier:
446+
LOCAL_LABEL(NotInHeap_ByRefWriteBarrier):
447447
// If WRITE_BARRIER_CHECK then we won't have already done the mov and should do it here
448448
// If !WRITE_BARRIER_CHECK we want _NotInHeap and _Leave to be the same and have both
449449
// 16 byte aligned.
450450
#ifdef WRITE_BARRIER_CHECK
451451
// rcx is [rsi]
452452
mov [rdi], rcx
453453
#endif
454-
Exit_ByRefWriteBarrier:
454+
LOCAL_LABEL(Exit_ByRefWriteBarrier):
455455
// Increment the pointers before leaving
456456
add rdi, 0x8
457457
add rsi, 0x8

src/tests/issues.targets

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@
6969
<ExcludeList Include="$(XunitTestBinBase)/GC/Regressions/Github/Runtime_76219/Runtime_76219/*">
7070
<Issue>https://github.com/dotnet/runtime/issues/78899</Issue>
7171
</ExcludeList>
72-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Regression/JitBlue/Runtime_82535/Runtime_82535/*">
73-
<Issue>https://github.com/dotnet/runtime/issues/89585</Issue>
72+
<ExcludeList Include="$(XunitTestBinBase)/readytorun/GenericCycleDetection/Depth3Test/*">
73+
<Issue>https://github.com/dotnet/runtime/issues/88586</Issue>
7474
</ExcludeList>
7575
</ItemGroup>
7676

0 commit comments

Comments
 (0)