From d5012a8471ebf16265951fb199eb58ec6d33116b Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Wed, 15 Apr 2015 16:59:56 -0700 Subject: Changed the VM's hardware exception to return if not in manged code. For DAC's hardware exception handling, add hardware exception holder used to determine if a C++ exception should be thrown for a hardware exception. Cleaned up PAL initialization interactions between the debugger modules (PAL_InitializeDLL) and coreclr (PAL_InitializeCoreCLR). --- src/pal/inc/pal.h | 51 +++++++++++------- src/pal/src/exception/machexception.cpp | 17 ++---- src/pal/src/exception/seh.cpp | 93 ++++++++++++++++++++++++++++----- src/pal/src/exception/signal.cpp | 28 +++------- src/pal/src/include/pal/module.h | 4 +- src/pal/src/include/pal/seh.hpp | 24 +++++++-- src/pal/src/init/pal.cpp | 4 +- src/pal/src/loader/module.cpp | 84 ++++++++++++----------------- src/pal/src/misc/miscpalapi.cpp | 7 ++- 9 files changed, 190 insertions(+), 122 deletions(-) (limited to 'src/pal') diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index e2aff4e28c..ca8856c4ec 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -600,12 +600,6 @@ PAL_CleanupDacTableAddress( ); -PALIMPORT -BOOL -PALAPI -PAL_RegisterMacEHPort(); - - /******************* winuser.h Entrypoints *******************************/ PALIMPORT @@ -5849,18 +5843,18 @@ public: class PAL_EnterHolder { public: // using constructor to suppress the "unused variable" warnings - PAL_EnterHolder(){} + PAL_EnterHolder() {} }; class PAL_LeaveHolder { public: // using constructor to suppress the "unused variable" warnings - PAL_LeaveHolder(){} + PAL_LeaveHolder() {} }; #endif // __cplusplus #endif // FEATURE_PAL_SXS -#if FEATURE_PAL_SXS +#ifdef __cplusplus #include "pal_unwind.h" @@ -5889,8 +5883,6 @@ typedef EXCEPTION_DISPOSITION (*PFN_PAL_EXCEPTION_FILTER)( PAL_DISPATCHER_CONTEXT *DispatcherContext, void *pvParam); -#ifdef __cplusplus - struct PAL_SEHException { public: @@ -5916,16 +5908,34 @@ typedef VOID (PALAPI *PHARDWARE_EXCEPTION_HANDLER)(PAL_SEHException* ex); PALIMPORT VOID PALAPI -PAL_SetHardwareExceptionHandler(IN PHARDWARE_EXCEPTION_HANDLER handler); +PAL_SetHardwareExceptionHandler( + IN PHARDWARE_EXCEPTION_HANDLER exceptionHandler); -#endif // __cplusplus +class PAL_CatchHardwareExceptionHolder +{ +public: + PAL_CatchHardwareExceptionHolder(); + + ~PAL_CatchHardwareExceptionHolder(); + + static bool IsEnabled(); +}; + +#ifdef FEATURE_ENABLE_HARDWARE_EXCEPTIONS +#define HardwareExceptionHolder PAL_CatchHardwareExceptionHolder __catchHardwareException; +#else +#define HardwareExceptionHolder +#endif // FEATURE_ENABLE_HARDWARE_EXCEPTIONS + +#ifdef FEATURE_PAL_SXS // Start of a try block for exceptions raised by RaiseException #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ { \ __ParamType __param = __paramRef; \ auto tryBlock = [](__ParamType __paramDef) \ - { + { \ + HardwareExceptionHolder // Start of an exception handler. If an exception raised by the RaiseException // occurs in the try block and the disposition is EXCEPTION_EXECUTE_HANDLER, @@ -5949,7 +5959,6 @@ PAL_SetHardwareExceptionHandler(IN PHARDWARE_EXCEPTION_HANDLER handler); throw; \ } - // Start of an exception handler. It works the same way as the PAL_EXCEPT except // that the disposition is obtained by calling the specified filter. #define PAL_EXCEPT_FILTER(filter) PAL_EXCEPT(filter(&ex.ExceptionPointers, __param)) @@ -5984,7 +5993,7 @@ PAL_SetHardwareExceptionHandler(IN PHARDWARE_EXCEPTION_HANDLER handler); #define PAL_CPP_THROW(type, obj) { throw obj; } #define PAL_CPP_RETHROW { throw; } -#define PAL_CPP_TRY try { +#define PAL_CPP_TRY try { HardwareExceptionHolder #define PAL_CPP_CATCH_EXCEPTION(ident) } catch (Exception *ident) { PAL_Reenter(PAL_BoundaryBottom); #define PAL_CPP_CATCH_EXCEPTION_NOARG } catch (Exception *) { PAL_Reenter(PAL_BoundaryBottom); #define PAL_CPP_CATCH_DERIVED(type, ident) } catch (type *ident) { PAL_Reenter(PAL_BoundaryBottom); @@ -6005,18 +6014,24 @@ PAL_SetHardwareExceptionHandler(IN PHARDWARE_EXCEPTION_HANDLER handler); { \ ParamType __param = paramRef; \ ParamType paramDef; paramDef = __param; \ - try { + try { \ + HardwareExceptionHolder + #define PAL_TRY_FOR_DLLMAIN(ParamType, paramDef, paramRef, _reason) \ { \ ParamType __param = paramRef; \ ParamType paramDef; paramDef = __param; \ - try { + try { \ + HardwareExceptionHolder + #define PAL_ENDTRY \ } \ } #endif // FEATURE_PAL_SXS +#endif // __cplusplus + #define EXCEPTION_CONTINUE_SEARCH 0 #define EXCEPTION_EXECUTE_HANDLER 1 #define EXCEPTION_CONTINUE_EXECUTION -1 diff --git a/src/pal/src/exception/machexception.cpp b/src/pal/src/exception/machexception.cpp index 33ed24a68a..7d31f76e4f 100644 --- a/src/pal/src/exception/machexception.cpp +++ b/src/pal/src/exception/machexception.cpp @@ -532,20 +532,11 @@ void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 } #endif // FEATURE_PAL_SXS - if (g_hardwareExceptionHandler != NULL) - { - PAL_SEHException exception(pExRecord, pContext); - - g_hardwareExceptionHandler(&exception); - - ASSERT("HandleHardwareException has returned, it should not.\n"); - } - else - { - ASSERT("Unhandled hardware exception\n"); - } + EXCEPTION_POINTERS pointers; + pointers.ExceptionRecord = pExRecord; + pointers.ContextRecord = pContext; - ExitProcess(pExRecord->ExceptionCode); + SEHProcessException(&pointers); } #if defined(_X86_) || defined(_AMD64_) diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp index e6f7b7aa63..4091914603 100644 --- a/src/pal/src/exception/seh.cpp +++ b/src/pal/src/exception/seh.cpp @@ -55,6 +55,17 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); /* Bit 28 of exception codes is reserved. */ const UINT RESERVED_SEH_BIT = 0x800000; +/* Internal variables definitions **********************************************/ + +PHARDWARE_EXCEPTION_HANDLER g_hardwareExceptionHandler = NULL; + +#ifdef __llvm__ +__thread +#else // __llvm__ +__declspec(thread) +#endif // !__llvm__ +int t_holderCount = 0; + /* Internal function declarations *********************************************/ BOOL SEHInitializeConsole(); @@ -81,7 +92,8 @@ Return value : TRUE if SEH support initialization succeeded FALSE otherwise --*/ -BOOL SEHInitialize (CPalThread *pthrCurrent, DWORD flags) +BOOL +SEHInitialize (CPalThread *pthrCurrent, DWORD flags) { BOOL bRet = FALSE; @@ -124,7 +136,8 @@ Parameters : (no return value) --*/ -void SEHCleanup (DWORD flags) +VOID +SEHCleanup(DWORD flags) { TRACE("Cleaning up SEH\n"); @@ -135,23 +148,59 @@ void SEHCleanup (DWORD flags) #endif } -PHARDWARE_EXCEPTION_HANDLER g_hardwareExceptionHandler = NULL; +/*++ +Function: + PAL_SetHardwareExceptionHandler + Register a hardware exception handler. + +Parameters: + handler - exception handler + +Return value: + None +--*/ VOID PALAPI -PAL_SetHardwareExceptionHandler(PHARDWARE_EXCEPTION_HANDLER handler) +PAL_SetHardwareExceptionHandler( + IN PHARDWARE_EXCEPTION_HANDLER exceptionHandler) + { - g_hardwareExceptionHandler = handler; + g_hardwareExceptionHandler = exceptionHandler; } -#ifdef FEATURE_PAL_SXS -BOOL -PALAPI -PAL_RegisterMacEHPort() +/*++ +Function: + SEHProcessException + + Build the PAL exception and sent it to any handler registered. + +Parameters: + PEXCEPTION_POINTERS pointers + +Return value: + Does not return +--*/ +PAL_NORETURN +VOID +SEHProcessException(PEXCEPTION_POINTERS pointers) { - return SEHEnable(InternalGetCurrentThread()) == ERROR_SUCCESS; -} + PAL_SEHException exception(pointers->ExceptionRecord, pointers->ContextRecord); + if (g_hardwareExceptionHandler != NULL) + { + g_hardwareExceptionHandler(&exception); + } + + if (PAL_CatchHardwareExceptionHolder::IsEnabled()) + { + throw exception; + } + + ASSERT("Unhandled hardware exception %08x\n", pointers->ExceptionRecord->ExceptionCode); + + ExitProcess(pointers->ExceptionRecord->ExceptionCode); +} /*++ Function : @@ -206,6 +255,26 @@ PAL_ERROR SEHDisable(CPalThread *pthrCurrent) #error not yet implemented #endif // HAVE_MACH_EXCEPTIONS } -#endif // FEATURE_PAL_SXS + +/*++ + +PAL_HandlerExceptionHolder implementation + +--*/ + +PAL_CatchHardwareExceptionHolder::PAL_CatchHardwareExceptionHolder() +{ + ++t_holderCount; +} + +PAL_CatchHardwareExceptionHolder::~PAL_CatchHardwareExceptionHolder() +{ + --t_holderCount; +} + +bool PAL_CatchHardwareExceptionHolder::IsEnabled() +{ + return t_holderCount > 0; +} #include "seh-unwind.cpp" diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index 4a90a55832..8e5f52825c 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -132,6 +132,10 @@ void SEHInitializeSignals(DWORD flags) handle_signal(SIGFPE, sigfpe_handler); handle_signal(SIGBUS, sigbus_handler); handle_signal(SIGSEGV, sigsegv_handler); +#if USE_SIGNALS_FOR_THREAD_SUSPENSION + handle_signal(SIGUSR1, suspend_handler); + handle_signal(SIGUSR2, resume_handler); +#endif if (flags & PAL_INITIALIZE_ALL_SIGNALS) { @@ -160,10 +164,6 @@ void SEHInitializeSignals(DWORD flags) #ifdef SIGINFO handle_signal(SIGINFO, NULL); #endif // SIGINFO -#if USE_SIGNALS_FOR_THREAD_SUSPENSION - handle_signal(SIGUSR1, suspend_handler); - handle_signal(SIGUSR2, resume_handler); -#endif /* The default action for SIGPIPE is process termination. Since SIGPIPE can be signaled when trying to write on a socket for which @@ -548,25 +548,13 @@ static void common_signal_handler(PEXCEPTION_POINTERS pointers, int code, /* Unmask signal so we can receive it again */ sigemptyset(&signal_set); - sigaddset(&signal_set,code); - if(-1 == sigprocmask(SIG_UNBLOCK,&signal_set,NULL)) + sigaddset(&signal_set, code); + if(-1 == sigprocmask(SIG_UNBLOCK, &signal_set, NULL)) { - ASSERT("sigprocmask failed; error is %d (%s)\n",errno, strerror(errno)); + ASSERT("sigprocmask failed; error is %d (%s)\n", errno, strerror(errno)); } - if (g_hardwareExceptionHandler != NULL) - { - PAL_SEHException exception(pointers->ExceptionRecord, pointers->ContextRecord); - - g_hardwareExceptionHandler(&exception); - ASSERT("HardwareExceptionHandler has returned, it should not."); - } - else - { - ASSERT("Unhandled hardware exception\n"); - } - - ExitProcess(pointers->ExceptionRecord->ExceptionCode); + SEHProcessException(pointers); } /*++ diff --git a/src/pal/src/include/pal/module.h b/src/pal/src/include/pal/module.h index 0e65766468..803ca36dc7 100644 --- a/src/pal/src/include/pal/module.h +++ b/src/pal/src/include/pal/module.h @@ -225,13 +225,13 @@ int LOADGetLibRotorPalSoFileName(LPSTR pszBuf); mscorwks). Parameters: - void + Core CLR path Return value: TRUE if successful FALSE if failure --*/ -BOOL LOADInitCoreCLRModules(); +BOOL LOADInitCoreCLRModules(const char *szCoreCLRPath); #if defined(CORECLR) && defined(__APPLE__) // Abstract the API used to load and query for functions in the CoreCLR binary to make it easier to change the diff --git a/src/pal/src/include/pal/seh.hpp b/src/pal/src/include/pal/seh.hpp index bc596bace9..399a417ea7 100644 --- a/src/pal/src/include/pal/seh.hpp +++ b/src/pal/src/include/pal/seh.hpp @@ -25,8 +25,6 @@ Abstract: #include "pal/palinternal.h" #include "pal/corunix.hpp" -extern PHARDWARE_EXCEPTION_HANDLER g_hardwareExceptionHandler; - // Uncomment this define to turn off the signal handling thread. // #define DO_NOT_USE_SIGNAL_HANDLING_THREAD @@ -45,7 +43,8 @@ Return value: FALSE otherwise --*/ -BOOL SEHInitialize(CorUnix::CPalThread *pthrCurrent, DWORD flags); +BOOL +SEHInitialize(CorUnix::CPalThread *pthrCurrent, DWORD flags); /*++ Function : @@ -58,7 +57,24 @@ Parameters: (no return value) --*/ -void SEHCleanup(DWORD flags); +VOID +SEHCleanup(DWORD flags); + +/*++ +Function: + SEHProcessException + + Build the PAL exception and sent it to any handler registered. + +Parameters: + None + +Return value: + Does not return +--*/ +PAL_NORETURN +VOID +SEHProcessException(PEXCEPTION_POINTERS pointers); /*++ Function : diff --git a/src/pal/src/init/pal.cpp b/src/pal/src/init/pal.cpp index 554cde6c62..7135e0c5c0 100644 --- a/src/pal/src/init/pal.cpp +++ b/src/pal/src/init/pal.cpp @@ -658,12 +658,14 @@ PAL_InitializeCoreCLR( int result = PAL_Initialize(1, &szExePath); #endif // __APPLE__ if (result != 0) + { return GetLastError(); + } // Now that the PAL is initialized it's safe to call the initialization methods for the code that used to // be dynamically loaded libraries but is now statically linked into CoreCLR just like the PAL, i.e. the // PAL RT and mscorwks. - if (!LOADInitCoreCLRModules()) + if (!LOADInitCoreCLRModules(g_szCoreCLRPath)) { return ERROR_DLL_INIT_FAILED; } diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp index 80bc1c17a1..45b217b724 100644 --- a/src/pal/src/loader/module.cpp +++ b/src/pal/src/loader/module.cpp @@ -91,11 +91,6 @@ CRITICAL_SECTION module_critsec; MODSTRUCT exe_module; /* always the first, in the in-load-order list */ MODSTRUCT pal_module; /* always the second, in the in-load-order list */ -PDLLMAIN g_pRuntimeDllMain = NULL; -// Use the g_szCoreCLRPath global to determine whether we're really part of CoreCLR or just a standalone PAL -// linked into some utility. -extern char g_szCoreCLRPath[MAX_PATH]; - /* static function declarations ***********************************************/ static BOOL LOADValidateModule(MODSTRUCT *module); @@ -634,6 +629,8 @@ GetModuleFileNameW( LockModuleList(); + wcscpy_s(lpFileName, nSize, W("")); + if(hModule && !LOADValidateModule((MODSTRUCT *)hModule)) { TRACE("Can't find name for invalid module handle %p\n", hModule); @@ -644,7 +641,7 @@ GetModuleFileNameW( if(!wide_name) { - ASSERT("Can't find name for valid module handle %p\n", hModule); + TRACE("Can't find name for valid module handle %p\n", hModule); SetLastError(ERROR_INTERNAL_ERROR); goto done; } @@ -869,8 +866,6 @@ Notes : extern "C" BOOL LOADInitializeModules(LPWSTR exe_name) { - LPWSTR lpwstr = NULL; - #if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN LPSTR pszExeName = NULL; CPalThread *pThread = NULL; @@ -889,55 +884,27 @@ BOOL LOADInitializeModules(LPWSTR exe_name) /* initialize module for main executable */ TRACE("Initializing module for main executable\n"); - exe_module.self=(HMODULE)&exe_module; - exe_module.dl_handle=dlopen(NULL, RTLD_LAZY); + exe_module.self = (HMODULE)&exe_module; + exe_module.dl_handle = dlopen(NULL, RTLD_LAZY); if(!exe_module.dl_handle) { ASSERT("Main executable module will be broken : dlopen(NULL) failed. " "dlerror message is \"%s\" \n", dlerror()); } exe_module.lib_name = exe_name; - exe_module.refcount=-1; - exe_module.next=&pal_module; - exe_module.prev=&pal_module; + exe_module.refcount = -1; + exe_module.next = &pal_module; + exe_module.prev = &pal_module; exe_module.pDllMain = NULL; exe_module.ThreadLibCalls = TRUE; TRACE("Initializing module for PAL library\n"); - pal_module.self=(HANDLE)&pal_module; - - if (g_szCoreCLRPath[0] == '\0') - { - pal_module.lib_name=NULL; - pal_module.dl_handle=NULL; - } else - { - TRACE("PAL library is %s\n", g_szCoreCLRPath); - lpwstr = UTIL_MBToWC_Alloc(g_szCoreCLRPath, -1); - if(NULL == lpwstr) - { - ERROR("MBToWC failure, unable to save full name of PAL module\n"); - goto Done; - } - pal_module.lib_name=lpwstr; - pal_module.dl_handle=dlopen(g_szCoreCLRPath, RTLD_LAZY); - - if(pal_module.dl_handle) - { - g_pRuntimeDllMain = (PDLLMAIN)dlsym(pal_module.dl_handle, "CoreDllMain"); - } - else - { -#if !defined(__hppa__) - ASSERT("PAL module will be broken : dlopen(%s) failed. dlerror " - "message is \"%s\"\n ", g_szCoreCLRPath, dlerror()); -#endif - } - } - - pal_module.refcount=-1; - pal_module.next=&exe_module; - pal_module.prev=&exe_module; + pal_module.self = (HANDLE)&pal_module; + pal_module.lib_name = NULL; + pal_module.dl_handle = NULL; + pal_module.refcount= - 1; + pal_module.next = &exe_module; + pal_module.prev = &exe_module; pal_module.pDllMain = NULL; pal_module.ThreadLibCalls = TRUE; @@ -1905,15 +1872,32 @@ Done: mscorwks). Parameters: - void + Core CLR path Return value: TRUE if successful FALSE if failure --*/ -BOOL LOADInitCoreCLRModules() +BOOL LOADInitCoreCLRModules( + const char *szCoreCLRPath) { - return g_pRuntimeDllMain((HMODULE)&pal_module, DLL_PROCESS_ATTACH, NULL); + TRACE("PAL library is %s\n", szCoreCLRPath); + LPWSTR lpwstr = UTIL_MBToWC_Alloc(szCoreCLRPath, -1); + if(!lpwstr) + { + ERROR("MBToWC failure, unable to save full name of PAL module\n"); + return FALSE; + } + pal_module.lib_name = lpwstr; + pal_module.dl_handle = dlopen(szCoreCLRPath, RTLD_LAZY); + if(!pal_module.dl_handle) + { + ERROR("PAL module will be broken : dlopen(%s) failed. dlerror message is \"%s\"\n ", + szCoreCLRPath, dlerror()); + return FALSE; + } + PDLLMAIN pRuntimeDllMain = (PDLLMAIN)dlsym(pal_module.dl_handle, "CoreDllMain"); + return pRuntimeDllMain((HMODULE)&pal_module, DLL_PROCESS_ATTACH, NULL); } // Get base address of the module containing a given symbol diff --git a/src/pal/src/misc/miscpalapi.cpp b/src/pal/src/misc/miscpalapi.cpp index a9d11c6cd2..88e285929a 100644 --- a/src/pal/src/misc/miscpalapi.cpp +++ b/src/pal/src/misc/miscpalapi.cpp @@ -37,8 +37,6 @@ Revision History: #include #endif // __APPLE__ -extern char g_szCoreCLRPath[MAX_PATH]; - SET_DEFAULT_DEBUG_CHANNEL(MISC); static const char RANDOM_DEVICE_NAME[] ="/dev/random"; @@ -71,6 +69,11 @@ PAL_GetPALDirectoryW( OUT LPWSTR lpDirectoryName, IN UINT cchDirectoryName ) ENTRY( "PAL_GetPALDirectoryW( %p, %d )\n", lpDirectoryName, cchDirectoryName ); lpFullPathAndName = pal_module.lib_name; + if (lpFullPathAndName == NULL) + { + SetLastError(ERROR_INTERNAL_ERROR); + goto EXIT; + } lpEndPoint = PAL_wcsrchr( lpFullPathAndName, '/' ); if ( lpEndPoint ) { -- cgit v1.2.3