Fix Issue #5542 (#5827)
authorchunseoklee <chunseoklee@naver.com>
Fri, 24 Jun 2016 12:56:55 +0000 (21:56 +0900)
committerJan Kotas <jkotas@microsoft.com>
Fri, 24 Jun 2016 12:56:55 +0000 (05:56 -0700)
On arm32, NullReference exception for interface call is not handled
properly. Especially, when callsite is a virtualstub(dispatch/resolve), AV exception
occurs on indirect cell. Since this stub is not a part of
managed or markedjithelper, exception handler considers this is a native
seg fault.
I added :
(1) FaultingExceptionFrame construction routine for virtualstub
(2) Checking and IP-adjusting routine for VirtualStub

src/vm/arm/exceparm.cpp
src/vm/arm/excepcpu.h
src/vm/exceptionhandling.cpp

index 9b14d41..6852adc 100644 (file)
@@ -54,6 +54,38 @@ FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTE
     return (FaultingExceptionFrame*)((TADDR)pDispatcherContext->ContextRecord->R4);
 }
 
+//Return TRUE if pContext->Pc is in VirtualStub
+BOOL IsIPinVirtualStub(PCODE f_IP)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    Thread * pThread = GetThread();
+
+    // We may not have a managed thread object. Example is an AV on the helper thread.
+    // (perhaps during StubManager::IsStub)
+    if (pThread == NULL)
+    {
+        return FALSE;
+    }
+
+    VirtualCallStubManager::StubKind sk;
+    VirtualCallStubManager::FindStubManager(f_IP, &sk);
+
+    if (sk == VirtualCallStubManager::SK_DISPATCH)
+    {
+        return TRUE;
+    }
+    else if (sk == VirtualCallStubManager::SK_RESOLVE)
+    {
+        return TRUE;
+    }
+
+    else {
+        return FALSE;
+    }
+}
+
+
 // Returns TRUE if caller should resume execution.
 BOOL
 AdjustContextForVirtualStub(
index fc0c44e..f13d81f 100644 (file)
@@ -46,5 +46,6 @@ PCODE GetAdjustedCallAddress(PCODE returnAddress)
 }
 
 BOOL AdjustContextForVirtualStub(EXCEPTION_RECORD *pExceptionRecord, T_CONTEXT *pContext);
+BOOL IsIPinVirtualStub(PCODE f_IP);
 
 #endif // __excepcpu_h__
index 3e5e22b..e74b2d8 100644 (file)
@@ -19,6 +19,7 @@
 #include "eedbginterfaceimpl.inl"
 #include "perfcounters.h"
 #include "eventtrace.h"
+#include "virtualcallstub.h"
 
 #ifndef DACCESS_COMPILE
 
@@ -5075,6 +5076,9 @@ BOOL PALAPI IsSafeToHandleHardwareException(PCONTEXT contextRecord, PEXCEPTION_R
         exceptionRecord->ExceptionCode == STATUS_BREAKPOINT || 
         exceptionRecord->ExceptionCode == STATUS_SINGLE_STEP ||
         (IsSafeToCallExecutionManager() && ExecutionManager::IsManagedCode(controlPc)) ||
+#ifdef _TARGET_ARM_
+        IsIPinVirtualStub(controlPc) ||  // access violation comes from DispatchStub of Interface call
+#endif
         IsIPInMarkedJitHelper(controlPc));
 }
 
@@ -5124,6 +5128,12 @@ VOID PALAPI HandleHardwareException(PAL_SEHException* ex)
                 PAL_VirtualUnwind(&ex->ContextRecord, NULL);
                 ex->ExceptionRecord.ExceptionAddress = (PVOID)GetIP(&ex->ContextRecord);
             }
+#ifdef _TARGET_ARM_
+            else if (IsIPinVirtualStub(controlPc)) 
+            {
+                AdjustContextForVirtualStub(&ex->ExceptionRecord, &ex->ContextRecord);
+            }
+#endif
             fef.InitAndLink(&ex->ContextRecord);
         }