Translate AV in RhpByRefAssignRef to NullReferenceException (#85575)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Mon, 1 May 2023 11:56:46 +0000 (20:56 +0900)
committerGitHub <noreply@github.com>
Mon, 1 May 2023 11:56:46 +0000 (04:56 -0700)
Fixes dotnet/runtimelab#197.

Ran into this again when curiosity made my try a newly added JIT test with NativeAOT.

src/coreclr/nativeaot/Runtime/EHHelpers.cpp
src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.S
src/coreclr/nativeaot/Runtime/amd64/WriteBarriers.asm
src/coreclr/nativeaot/Runtime/arm/WriteBarriers.S
src/coreclr/nativeaot/Runtime/arm64/WriteBarriers.S
src/coreclr/nativeaot/Runtime/arm64/WriteBarriers.asm
src/tests/issues.targets

index 2881dae..28e33fb 100644 (file)
@@ -285,6 +285,11 @@ EXTERN_C void * RhpCheckedLockCmpXchgAVLocation;
 EXTERN_C void * RhpCheckedXchgAVLocation;
 EXTERN_C void * RhpLockCmpXchg32AVLocation;
 EXTERN_C void * RhpLockCmpXchg64AVLocation;
+EXTERN_C void * RhpByRefAssignRefAVLocation1;
+
+#if !defined(HOST_ARM64)
+EXTERN_C void * RhpByRefAssignRefAVLocation2;
+#endif
 
 #if defined(HOST_ARM64) && !defined(LSE_INSTRUCTIONS_ENABLED_BY_DEFAULT)
 EXTERN_C void* RhpCheckedLockCmpXchgAVLocation2;
@@ -302,6 +307,10 @@ static bool InWriteBarrierHelper(uintptr_t faultingIP)
         (uintptr_t)&RhpCheckedXchgAVLocation,
         (uintptr_t)&RhpLockCmpXchg32AVLocation,
         (uintptr_t)&RhpLockCmpXchg64AVLocation,
+        (uintptr_t)&RhpByRefAssignRefAVLocation1,
+#if !defined(HOST_ARM64)
+        (uintptr_t)&RhpByRefAssignRefAVLocation2,
+#endif
 #if defined(HOST_ARM64) && !defined(LSE_INSTRUCTIONS_ENABLED_BY_DEFAULT)
         (uintptr_t)&RhpCheckedLockCmpXchgAVLocation2,
         (uintptr_t)&RhpCheckedXchgAVLocation2,
index 3888d0a..cc740a9 100644 (file)
@@ -260,8 +260,13 @@ LEAF_END RhpCheckedXchg, _TEXT
 //      rdi, rsi are incremented by 8,
 //      rcx, r10, r11: trashed
 //
+// WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpByRefAssignRefAVLocation1/2
+// - Function "UnwindSimpleHelperToCaller" assumes the stack contains just the pushed return address
 LEAF_ENTRY RhpByRefAssignRef, _TEXT
+ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
     mov     rcx, [rsi]
+ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
     mov     [rdi], rcx
 
     // Check whether the writes were even into the heap. If not there's no card update required.
index 753ca45..148aa7d 100644 (file)
@@ -276,8 +276,13 @@ LEAF_END RhpCheckedXchg, _TEXT
 ;;      rdi, rsi are incremented by 8,
 ;;      rcx, r10, r11: trashed
 ;;
+;; WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+;; - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpByRefAssignRefAVLocation1/2
+;; - Function "UnwindSimpleHelperToCaller" assumes the stack contains just the pushed return address
 LEAF_ENTRY RhpByRefAssignRef, _TEXT
+ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
     mov     rcx, [rsi]
+ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
     mov     [rdi], rcx
 
     ;; Check whether the writes were even into the heap. If not there's no card update required.
index 863e17c..30e20c4 100644 (file)
@@ -322,11 +322,16 @@ LEAF_END RhpCheckedXchg, _TEXT
 //      r0, r1 are incremented by 4,
 //      r2, r3: trashed
 //
+// WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpByRefAssignRefAVLocation1/2
+// - Function "UnwindSimpleHelperToCaller" assumes no registers were pushed and LR contains the return address
 LEAF_ENTRY RhpByRefAssignRef, _TEXT
           // See comment in RhpAssignRef
           dmb
 
+ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
           ldr          r2, [r1]
+ALTERNATE_ENTRY RhpByRefAssignRefAVLocation2
           str          r2, [r0]
 
           // Check whether the writes were even into the heap. If not there's no card update required.
index dc2fd73..d00ffb3 100644 (file)
 //   x15  : trashed
 //   x12, x17  : trashed
 //
+// WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+// - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpByRefAssignRefAVLocation1
+// - Function "UnwindSimpleHelperToCaller" assumes no registers were pushed and LR contains the return address
 LEAF_ENTRY RhpByRefAssignRefArm64, _TEXT
 
+    ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
         ldr     x15, [x13], 8
         b       C_FUNC(RhpCheckedAssignRefArm64)
 
index 5a7be69..26a8ef3 100644 (file)
@@ -206,8 +206,12 @@ INVALIDGCVALUE  EQU 0xCCCCCCCD
 ;;   x15  : trashed
 ;;   x12, x17  : trashed
 ;;
+;; WARNING: Code in EHHelpers.cpp makes assumptions about write barrier code, in particular:
+;; - Function "InWriteBarrierHelper" assumes an AV due to passed in null pointer will happen at RhpByRefAssignRefAVLocation1
+;; - Function "UnwindSimpleHelperToCaller" assumes no registers were pushed and LR contains the return address
     LEAF_ENTRY RhpByRefAssignRefArm64, _TEXT
 
+    ALTERNATE_ENTRY RhpByRefAssignRefAVLocation1
         ldr     x15, [x13], 8
         b       RhpCheckedAssignRefArm64
 
index 9d6698b..25b5e94 100644 (file)
         <ExcludeList Include="$(XunitTestBinBase)/JIT/Regression/CLR-x86-JIT/v2.2/ddb/b429039/b429039/*">
             <Issue>https://github.com/dotnet/runtimelab/issues/155: RuntimeHelpers.InitializeArray</Issue>
         </ExcludeList>
-        <ExcludeList Include="$(XunitTestBinBase)/JIT/Regression/JitBlue/GitHub_19444/GitHub_19444/*">
-            <Issue>https://github.com/dotnet/runtimelab/issues/197</Issue>
-        </ExcludeList>
         <ExcludeList Include="$(XunitTestBinBase)/JIT/Regression/JitBlue/GitHub_22583/GitHub_22583/*">
             <Issue>https://github.com/dotnet/runtimelab/issues/155: Type equivalence</Issue>
         </ExcludeList>