diff options
Diffstat (limited to 'src/vm/exceptionhandling.cpp')
-rw-r--r-- | src/vm/exceptionhandling.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index c6d42eddd7..a52ccd7c2a 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -5186,6 +5186,38 @@ BOOL IsSafeToHandleHardwareException(PCONTEXT contextRecord, PEXCEPTION_RECORD e IsIPInMarkedJitHelper(controlPc)); } +#ifdef _TARGET_ARM_ +static inline BOOL HandleArmSingleStep(PCONTEXT pContext, PEXCEPTION_RECORD pExceptionRecord, Thread *pThread) +{ +#ifdef __linux__ + // On ARM Linux exception point to the break instruction, + // but the rest of the code expects that it points to an instruction after the break + if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) + { + SetIP(pContext, GetIP(pContext) + CORDbg_BREAK_INSTRUCTION_SIZE); + pExceptionRecord->ExceptionAddress = (void *)GetIP(pContext); + } +#endif + // On ARM we don't have any reliable hardware support for single stepping so it is emulated in software. + // The implementation will end up throwing an EXCEPTION_BREAKPOINT rather than an EXCEPTION_SINGLE_STEP + // and leaves other aspects of the thread context in an invalid state. Therefore we use this opportunity + // to fixup the state before any other part of the system uses it (we do it here since only the debugger + // uses single step functionality). + + // First ask the emulation itself whether this exception occurred while single stepping was enabled. If so + // it will fix up the context to be consistent again and return true. If so and the exception was + // EXCEPTION_BREAKPOINT then we translate it to EXCEPTION_SINGLE_STEP (otherwise we leave it be, e.g. the + // instruction stepped caused an access violation). + if (pThread->HandleSingleStep(pContext, pExceptionRecord->ExceptionCode) && (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)) + { + pExceptionRecord->ExceptionCode = EXCEPTION_SINGLE_STEP; + pExceptionRecord->ExceptionAddress = (void *)GetIP(pContext); + return TRUE; + } + return FALSE; +} +#endif // _TARGET_ARM_ + BOOL HandleHardwareException(PAL_SEHException* ex) { _ASSERTE(IsSafeToHandleHardwareException(ex->GetContextRecord(), ex->GetExceptionRecord())); @@ -5249,6 +5281,9 @@ BOOL HandleHardwareException(PAL_SEHException* ex) Thread *pThread = GetThread(); if (pThread != NULL && g_pDebugInterface != NULL) { +#ifdef _TARGET_ARM_ + HandleArmSingleStep(ex->GetContextRecord(), ex->GetExceptionRecord(), pThread); +#endif if (ex->GetExceptionRecord()->ExceptionCode == STATUS_BREAKPOINT) { // If this is breakpoint context, it is set up to point to an instruction after the break instruction. |