diff options
author | Mike McLaughlin <mikem@microsoft.com> | 2015-02-23 10:09:14 -0800 |
---|---|---|
committer | Mike McLaughlin <mikem@microsoft.com> | 2015-02-23 10:09:14 -0800 |
commit | bfb8bffa32b422b538a3359af84305d47a912d6c (patch) | |
tree | b0728d94a9ffd995ac00ed2670e370671bae23f1 /src | |
parent | 639ac0872d1491d6f7b88bddbd84b3fb36bdc62a (diff) | |
parent | 63976a08fbe6ece34a2936ebccdf735ea32044a2 (diff) | |
download | coreclr-bfb8bffa32b422b538a3359af84305d47a912d6c.tar.gz coreclr-bfb8bffa32b422b538a3359af84305d47a912d6c.tar.bz2 coreclr-bfb8bffa32b422b538a3359af84305d47a912d6c.zip |
Merge remote-tracking branch 'upstream/master' into soscommand1
Diffstat (limited to 'src')
36 files changed, 220 insertions, 1543 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 95a56e1baa..95a9640e32 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,19 +10,16 @@ include_directories("classlibnative/bcltype") include_directories("classlibnative/cryptography") include_directories("classlibnative/inc") -if(WIN32) -enable_language(ASM_MASM) -else() -enable_language(ASM) -# This prevents inclusion of standard C compiler headers -add_compile_options(-nostdinc) +if(CLR_CMAKE_PLATFORM_UNIX) + # This prevents inclusion of standard C compiler headers + add_compile_options(-nostdinc) -if(NOT CLR_CMAKE_PLATFORM_DARWIN) - # This prevents inclusion of standard C++ compiler headers - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") -endif(NOT CLR_CMAKE_PLATFORM_DARWIN) + if(NOT CLR_CMAKE_PLATFORM_DARWIN) + # This prevents inclusion of standard C++ compiler headers + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") + endif(NOT CLR_CMAKE_PLATFORM_DARWIN) -endif(WIN32) +endif(CLR_CMAKE_PLATFORM_UNIX) add_subdirectory(utilcode) add_subdirectory(gcinfo) diff --git a/src/inc/debugreturn.h b/src/inc/debugreturn.h index 9eb204d92c..eadf827893 100644 --- a/src/inc/debugreturn.h +++ b/src/inc/debugreturn.h @@ -65,6 +65,7 @@ class __SafeToReturn { public: static int safe_to_return() {return 0;}; + static int used() {return 0;}; }; class __YouCannotUseAReturnStatementHere { @@ -76,9 +77,10 @@ private: // static int safe_to_return() {return 0;}; public: - // Some compilers warn if all member functions in a class are private. - // Rather than disable the warning, we'll work around it here. - static void dont_call_this() { _ASSERTE(!"Don't call this!"); } + // Some compilers warn if all member functions in a class are private + // or if a typedef is unused. Rather than disable the warning, we'll work + // around it here. + static int used() {return 0;}; }; typedef __SafeToReturn __ReturnOK; @@ -93,15 +95,15 @@ typedef __SafeToReturn __ReturnOK; // #define return if (0 && __ReturnOK::safe_to_return()) { } else return -#define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { typedef __YouCannotUseAReturnStatementHere __ReturnOK; -#define DEBUG_ASSURE_NO_RETURN_END(arg) } +#define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { typedef __YouCannotUseAReturnStatementHere __ReturnOK; if (0 && __ReturnOK::used()) { } else { +#define DEBUG_ASSURE_NO_RETURN_END(arg) } } // rotor_pal.h defaulted these to empty macros; this file redefines them #undef DEBUG_OK_TO_RETURN_BEGIN #undef DEBUG_OK_TO_RETURN_END -#define DEBUG_OK_TO_RETURN_BEGIN(arg) { typedef __SafeToReturn __ReturnOK; -#define DEBUG_OK_TO_RETURN_END(arg) } +#define DEBUG_OK_TO_RETURN_BEGIN(arg) { typedef __SafeToReturn __ReturnOK; if (0 && __ReturnOK::used()) { } else { +#define DEBUG_OK_TO_RETURN_END(arg) } } #else // !_DEBUG diff --git a/src/inc/staticcontract.h b/src/inc/staticcontract.h index 282a21f64e..5c7a33b8f7 100644 --- a/src/inc/staticcontract.h +++ b/src/inc/staticcontract.h @@ -244,6 +244,10 @@ namespace StaticContract STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SO_TOLERANT; } + + static void used() + { + } }; struct ScanThrowMarkerTerminal @@ -252,6 +256,10 @@ namespace StaticContract { METHOD_CANNOT_BE_FOLDED_DEBUG; } + + static void used() + { + } }; struct ScanThrowMarkerIgnore @@ -260,6 +268,10 @@ namespace StaticContract { METHOD_CANNOT_BE_FOLDED_DEBUG; } + + static void used() + { + } }; } typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker; @@ -270,13 +282,13 @@ typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker; #define SCAN_THROW_MARKER do { ScanThrowMarker __throw_marker; } while (0) #define SCAN_IGNORE_THROW_MARKER \ - typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker + typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker; if (0) ScanThrowMarker::used(); // Terminal exceptions are asynchronous and cannot be included in THROWS contract // analysis. As such, this uses typedef to reassign the ScanThrowMarker to a // non-annotating struct so that SCAN does not see the block as throwing. #define STATIC_CONTRACT_THROWS_TERMINAL \ - typedef StaticContract::ScanThrowMarkerTerminal ScanThrowMarker; + typedef StaticContract::ScanThrowMarkerTerminal ScanThrowMarker; if (0) ScanThrowMarker::used(); #if defined(_DEBUG) && !defined(DACCESS_COMPILE) && defined(FEATURE_STACK_PROBE) && !defined(_TARGET_ARM_) // @ARMTODO extern void EnsureSOIntolerantOK(const char *szFunction, const char *szFile, int lineNum); diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 22a4cf21c9..de924fc424 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -449,7 +449,7 @@ int PALAPI PAL_Initialize( int argc, - const char *argv[]); + const char * const argv[]); PALIMPORT DWORD @@ -4737,18 +4737,6 @@ SetUnhandledExceptionFilter( typedef EXCEPTION_DISPOSITION (PALAPI *PVECTORED_EXCEPTION_HANDLER)( struct _EXCEPTION_POINTERS *ExceptionPointers); -PALIMPORT -void -PALAPI -SetVectoredExceptionHandler( - IN PVECTORED_EXCEPTION_HANDLER lpHandler); - -PALIMPORT -void -PALAPI -SetVectoredContinueHandler( - IN PVECTORED_EXCEPTION_HANDLER lpHandler); - #endif // FEATURE_PAL_SXS // Define BitScanForward64 and BitScanForward @@ -5894,206 +5882,94 @@ typedef EXCEPTION_DISPOSITION (*PFN_PAL_EXCEPTION_FILTER)( PAL_DISPATCHER_CONTEXT *DispatcherContext, void *pvParam); -struct _Unwind_Exception *PAL_TryExcept( - PFN_PAL_BODY pfnBody, - PFN_PAL_EXCEPTION_FILTER pfnFilter, - void *pvParam, - BOOL *pfExecuteHandler); - -// -// Possible results from PAL_TryExcept: -// -// returned exception pfExecuteHandler means -// ------------------ ---------------- ---------------------------------------- -// NULL any No exception escaped from the try block. -// non-NULL FALSE An exception escaped from the try block, -// but the filter did not want to handle it. -// non-NULL TRUE An exception escaped from the try block, -// and the filter wanted to handle it. -// - -#define DEBUG_OK_TO_RETURN_BEGIN(arg) -#define DEBUG_OK_TO_RETURN_END(arg) - -#ifdef _PPC_ -// This function does not do anything. It is just here to be called by -// PAL_TRY, so we can avoid the body of PAL_TRY being translated by the -// compiler into a leaf function (i.e., one that does not set up its -// own frame), because on a hardware fault in a leaf function, we would -// get a stack that would not be unwindable. -PALIMPORT VOID PALAPI PAL_DummyCall(); -#define PAL_DUMMY_CALL PAL_DummyCall(); -#else -#define PAL_DUMMY_CALL -#endif - #ifdef __cplusplus -class PAL_CatchHolder -{ -public: - PAL_CatchHolder(_Unwind_Exception *exceptionObject) - { - __cxa_begin_catch(exceptionObject); - } - ~PAL_CatchHolder() - { - __cxa_end_catch(); - } -}; - -class PAL_ExceptionHolder +struct PAL_SEHException { -private: - _Unwind_Exception *m_exceptionObject; public: - PAL_ExceptionHolder(_Unwind_Exception *exceptionObject) - { - m_exceptionObject = exceptionObject; - } - - ~PAL_ExceptionHolder() - { - if (m_exceptionObject) - { - _Unwind_DeleteException(m_exceptionObject); - } - } - - void SuppressRelease() + // Note that the following two are actually embedded in this heap-allocated + // instance - in contrast to Win32, where the exception record would usually + // be allocated on the stack. This is needed because foreign cleanup handlers + // partially unwind the stack on the second pass. + EXCEPTION_POINTERS ExceptionPointers; + EXCEPTION_RECORD ExceptionRecord; + CONTEXT ContextRecord; + + PAL_SEHException(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContextRecord) { - m_exceptionObject = NULL; + ExceptionPointers.ExceptionRecord = &ExceptionRecord; + ExceptionPointers.ContextRecord = &ContextRecord; + ExceptionRecord = *pExceptionRecord; + ContextRecord = *pContextRecord; } }; -class PAL_NoHolder -{ -public: - void SuppressRelease() {} -}; #endif // __cplusplus +// Start of a try block for exceptions raised by RaiseException #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ { \ - struct __HandlerData \ - { \ - __ParamType __param; \ - EXCEPTION_DISPOSITION __handlerDisposition; \ - __HandlerData(__ParamType param) : __param(param) {} \ + __ParamType __param = __paramRef; \ + auto tryBlock = [](__ParamType __paramDef) \ + { + +// Start of an exception handler. If an exception raised by the RaiseException +// occurs in the try block and the disposition is EXCEPTION_EXECUTE_HANDLER, +// the handler code is executed. If the disposition is EXCEPTION_CONTINUE_SEARCH, +// the exception is rethrown. The EXCEPTION_CONTINUE_EXECUTION disposition is +// not supported. +#define PAL_EXCEPT(dispositionExpression) \ }; \ - __HandlerData __handlerData(__paramRef); \ - class __Body \ + const bool isFinally = false; \ + auto finallyBlock = []() {}; \ + try \ { \ - public: \ - static void Run(void *__pvHandlerData) \ + tryBlock(__param); \ + } \ + catch (PAL_SEHException& ex) \ + { \ + EXCEPTION_DISPOSITION disposition = dispositionExpression; \ + _ASSERTE(disposition != EXCEPTION_CONTINUE_EXECUTION); \ + if (disposition == EXCEPTION_CONTINUE_SEARCH) \ { \ - __ParamType __paramDef = ((__HandlerData *)__pvHandlerData)->__param; \ - PAL_DUMMY_CALL; - -// On Windows 32bit, we dont invoke filters on the second pass. -// To ensure the same happens on the Mac, we check if we are -// in the first phase or not. If we are, we invoke the -// filter and save the disposition in a local static. -// -// However, if we are not in the first phase but in the second, -// and thus unwinding, then we return the disposition saved -// from the first pass back (similar to how CRT -// does it on x86). -#define PAL_EXCEPT(dispositionExpression) \ - } \ - static EXCEPTION_DISPOSITION Handler( \ - EXCEPTION_POINTERS *ExceptionPointers, \ - PAL_DISPATCHER_CONTEXT *DispatcherContext, \ - void *pvHandlerData) \ - { \ - DEBUG_OK_TO_RETURN_BEGIN(PAL_EXCEPT) \ - __HandlerData *pHandlerData = (__HandlerData *)pvHandlerData; \ - void *pvParam = NULL; \ - pvParam = pHandlerData->__param; \ - if (!(ExceptionPointers->ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)) \ - pHandlerData->__handlerDisposition = (EXCEPTION_DISPOSITION) (dispositionExpression); \ - return pHandlerData->__handlerDisposition; \ - DEBUG_OK_TO_RETURN_END(PAL_EXCEPT) \ - } \ - }; \ - BOOL __fExecuteHandler; \ - _Unwind_Exception *__exception = \ - PAL_TryExcept(__Body::Run, __Body::Handler, &__handlerData, &__fExecuteHandler); \ - PAL_NoHolder __exceptionHolder; \ - if (__exception && __fExecuteHandler) \ - { \ - PAL_CatchHolder __catchHolder(__exception); \ - __exception = NULL; - -#define PAL_EXCEPT_FILTER(filter) PAL_EXCEPT(filter(ExceptionPointers, pvParam)) - -// Executes the handler if the specified exception code matches -// the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH. -#define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) \ - PAL_EXCEPT(((ExceptionPointers->ExceptionRecord->ExceptionCode == dwExceptionCode)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH)) + throw; \ + } -#define PAL_FINALLY \ - } \ - static EXCEPTION_DISPOSITION Filter( \ - EXCEPTION_POINTERS *ExceptionPointers, \ - PAL_DISPATCHER_CONTEXT *DispatcherContext, \ - void *pvHandlerData) \ - { \ - DEBUG_OK_TO_RETURN_BEGIN(PAL_FINALLY) \ - return EXCEPTION_CONTINUE_SEARCH; \ - DEBUG_OK_TO_RETURN_END(PAL_FINALLY) \ - } \ - }; \ - BOOL __fExecuteHandler; \ - _Unwind_Exception *__exception = \ - PAL_TryExcept(__Body::Run, __Body::Filter, &__handlerData, &__fExecuteHandler); \ - PAL_ExceptionHolder __exceptionHolder(__exception); \ - { -#define PAL_ENDTRY \ - } \ - if (__exception) \ - { \ - __exceptionHolder.SuppressRelease(); \ - PAL_Leave(PAL_BoundaryBottom); \ - _Unwind_Resume(__exception); \ - } \ +// 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)) + +// Start of a finally block. The finally block is executed both when the try block +// finishes or when an exception is raised using the RaiseException in it. +#define PAL_FINALLY \ + }; \ + const bool isFinally = true; \ + auto finallyBlock = [&]() \ + { + +// End of an except or a finally block. +#define PAL_ENDTRY \ + }; \ + if (isFinally) \ + { \ + try \ + { \ + tryBlock(__param); \ + } \ + catch (...) \ + { \ + finallyBlock(); \ + throw; \ + } \ + finallyBlock(); \ + } \ } -#if _DEBUG -void PAL_CheckVirtualUnwind(); -#else // _DEBUG -#define PAL_CheckVirtualUnwind() -#endif // _DEBUG - - #endif // FEATURE_PAL_SXS -PALIMPORT -PAL_NORETURN -VOID -PALAPI -PAL_CppRethrow(); - -// Define PAL_CPP_THROW in terms of PAL_CPP_RETHROW, which does not throw -// using the C++ runtime, but our own implementation that will also call -// vectored handlers. -#define PAL_CPP_THROW(type,expr) \ - { \ - type __exn = expr; \ - PAL_Leave(PAL_BoundaryBottom); \ - PAL_CPP_TRY \ - { \ - throw __exn; \ - } \ - PAL_CPP_CATCH_ALL \ - { \ - PAL_CPP_RETHROW; \ - } \ - PAL_CPP_ENDTRY \ - } -#define PAL_CPP_RETHROW PAL_CppRethrow(); - +#define PAL_CPP_THROW(type, obj) { throw obj; } +#define PAL_CPP_RETHROW { throw; } #define PAL_CPP_TRY try { #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); diff --git a/src/pal/inc/pal_assert.h b/src/pal/inc/pal_assert.h index a1c4711381..d5a1d2d4a5 100644 --- a/src/pal/inc/pal_assert.h +++ b/src/pal/inc/pal_assert.h @@ -23,21 +23,13 @@ extern "C" { // C_ASSERT() can be used to perform many compile-time assertions: // type sizes, field offsets, etc. // -// An assertion failure results in error C2118: negative subscript. -// or -// size of array `__C_ASSERT__' is negative -// - -#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#define C_ASSERT(e) static_assert(e, #e) // // CPP_ASSERT() can be used within a class definition, to perform a // compile-time assertion involving private names within the class. // -// MS compiler doesn't allow redefinition of the typedef within a template. -// gcc doesn't allow redefinition of the typedef within a class, though -// it does at file scope. -#define CPP_ASSERT(n, e) typedef char __C_ASSERT__##n[(e) ? 1 : -1]; +#define CPP_ASSERT(n, e) static_assert(e, #e) #endif // __cplusplus diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt index 3e4e9bbcc8..721bbba4a9 100644 --- a/src/pal/src/CMakeLists.txt +++ b/src/pal/src/CMakeLists.txt @@ -39,6 +39,7 @@ add_compile_options(-fPIC) set(SOURCES arch/i386/context.cpp + arch/i386/context2.S arch/i386/processor.cpp cruntime/file.cpp cruntime/filecrt.cpp diff --git a/src/pal/src/arch/i386/context.cpp b/src/pal/src/arch/i386/context.cpp index 518539fffc..cb1d045e7d 100644 --- a/src/pal/src/arch/i386/context.cpp +++ b/src/pal/src/arch/i386/context.cpp @@ -31,12 +31,8 @@ Abstract: SET_DEFAULT_DEBUG_CHANNEL(DEBUG); - -void CONTEXT_CaptureContext(LPCONTEXT lpContext) -{ - // TODO: this needs to be implemented. See context2.s - _ASSERT(FALSE); -} +// in context2.S +extern void CONTEXT_CaptureContext(LPCONTEXT lpContext); #ifdef _X86_ #define CONTEXT_ALL_FLOATING (CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS) diff --git a/src/pal/src/arch/i386/context2.s b/src/pal/src/arch/i386/context2.S index 535506cf00..6ec622a51b 100644 --- a/src/pal/src/arch/i386/context2.s +++ b/src/pal/src/arch/i386/context2.S @@ -8,6 +8,8 @@ // and is always apply to the current thread. // +#include "macros.inc" + #ifdef BIT64 #define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags @@ -76,8 +78,8 @@ // Incoming: // RDI: Context* // - .globl _CONTEXT_CaptureContext -_CONTEXT_CaptureContext: + .globl C_FUNC(CONTEXT_CaptureContext) +C_FUNC(CONTEXT_CaptureContext): testb $CONTEXT_INTEGER, CONTEXT_ContextFlags(%rdi) je 0f mov %rdi, CONTEXT_Rdi(%rdi) @@ -166,8 +168,8 @@ _CONTEXT_CaptureContext: #define CONTEXT_Xmm6 CONTEXT_Xmm5+16 #define CONTEXT_Xmm7 CONTEXT_Xmm6+16 - .globl _CONTEXT_CaptureContext -_CONTEXT_CaptureContext: + .globl C_FUNC(CONTEXT_CaptureContext) +C_FUNC(CONTEXT_CaptureContext): push %eax mov 8(%esp), %eax mov %edi, CONTEXT_Edi(%eax) diff --git a/src/pal/src/arch/i386/runfilter.s b/src/pal/src/arch/i386/runfilter.s deleted file mode 100644 index 1bf2f7438b..0000000000 --- a/src/pal/src/arch/i386/runfilter.s +++ /dev/null @@ -1,158 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -// -// Implementation of the PAL_RunFilter primitive that allows -// to run a filter guarded by a personality routine that can -// deal with nested exceptions. -// - -#define ALIGN_UP(x) ((x + 15) & ~15) - -#ifdef BIT64 - -#define SIZEOF_ARG_REGISTERS 32 -#define FRAME_SIZE ALIGN_UP(SIZEOF_ARG_REGISTERS) - - .text - .globl _PAL_RunFilter -_PAL_RunFilter: -LFB7: - push %rbp -LCFI0: - mov %rsp, %rbp -LCFI1: - sub $FRAME_SIZE, %rsp - mov %rdi, (%rsp) // ExceptionPointers - mov %rsi, 8(%rsp) // DispatcherContext - mov %rdx, 16(%rsp) // pvParam - mov %rcx, 24(%rsp) // pfnFilter - - // Filters need to be passed ExceptionPointers and pvParam arguments, in that order. - // ExceptionPointers is already in the right register (RDI), so setup pvParam to be - // in RSI - mov %rdx, %rsi -LEHB0: - call *%rcx // Invoke the filter -LEHE0: - leave - ret -LFE7: - -#else // BIT64 - -#define SIZEOF_ARG_REGISTERS 12 -#define FRAME_SIZE ALIGN_UP(8 + SIZEOF_ARG_REGISTERS) - 8 - - .text - .globl _PAL_RunFilter -_PAL_RunFilter: -LFB7: - pushl %ebp -LCFI0: - movl %esp, %ebp -LCFI1: - subl $FRAME_SIZE, %esp - movl 8(%ebp), %eax // exception pointers - movl %eax, (%esp) - movl 12(%ebp), %eax // dispatcher context - movl %eax, 4(%esp) - movl 16(%ebp), %eax // param - movl %eax, 8(%esp) -LEHB0: - call *20(%ebp) // filter -LEHE0: - leave - ret -LFE7: - -#endif // BIT64 else - - .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -CIE_SEHFilterPersonality: - .long LECIE1-LSCIE1 -LSCIE1: - .long 0x0 - .byte 0x1 - .ascii "zPLR\0" - .byte 0x1 -#ifdef BIT64 - .byte 0x78 // data_align: -8 - .byte 16 // return address register: rip -#else // BIT64 - .byte 0x7c // data_align: -4 - .byte 0x8 // return address register: eip -#endif // BIT64 else - .byte 0x7 - .byte 0x9b -#ifdef BIT64 - .long _PAL_SEHFilterPersonalityRoutine+4@GOTPCREL -#else // BIT64 - .long L_PAL_SEHFilterPersonalityRoutine$non_lazy_ptr-. -#endif // BIT64 else - .byte 0x10 - .byte 0x10 - .byte 0xc // DW_CFA_def_cfa -#ifdef BIT64 - .byte 0x7 // operand1 = rsp - .byte 0x8 // operand2 = offset 8 - .byte 0x80 | 16 // DW_CFA_offset of return address register -#else // BIT64 - .byte 0x5 // operand1 = esp - .byte 0x4 // operand2 = offset 4 - .byte 0x80 | 8 // DW_CFA_offset of return address register -#endif // BIT64 else - .byte 0x1 // operand1 = 1 word - .align 2 -LECIE1: - - .globl _PAL_RunFilter.eh -_PAL_RunFilter.eh: -LSFDE1: - .set LLFDE1,LEFDE1-LASFDE1 - .set LFL7,LFE7-LFB7 - .long LLFDE1 -LASFDE1: - .long LASFDE1-CIE_SEHFilterPersonality -#ifdef BIT64 - .quad LFB7-. - .quad LFL7 - .byte 0x8 - .quad 0x0 -#else // BIT64 - .long LFB7-. - .long LFL7 - .byte 0x4 - .long 0x0 -#endif // BIT64 else - .byte 0x4 // DW_CFA_advance_loc4 - .long LCFI0-LFB7 - .byte 0xe // DW_CFA_def_cfa_offset -#ifdef BIT64 - .byte 0x10 - .byte 0x80 | 6 // DW_CFA_offset rbp -#else // BIT64 - .byte 0x8 - .byte 0x80 | 4 // DW_CFA_offset ebp -#endif // BIT64 else - .byte 0x2 - .byte 0x4 // DW_CFA_advance_loc4 - .long LCFI1-LCFI0 - .byte 0xd // DW_CFA_def_cfa_register -#ifdef BIT64 - .byte 6 // operand1 = rbp -#else // BIT64 - .byte 4 // operand1 = ebp -#endif // BIT64 - .align 2 -LEFDE1: - -#ifndef BIT64 - - .section __IMPORT,__pointers,non_lazy_symbol_pointers -L_PAL_SEHFilterPersonalityRoutine$non_lazy_ptr: - .indirect_symbol _PAL_SEHFilterPersonalityRoutine - .long 0 - -#endif // BIT64 diff --git a/src/pal/src/arch/i386/tryexcept.s b/src/pal/src/arch/i386/tryexcept.s deleted file mode 100644 index f0bea999ad..0000000000 --- a/src/pal/src/arch/i386/tryexcept.s +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -// ==++== -// - -// ==--== -// -// Implementation of the PAL_TryExcept primitive for MSVC-style -// exception handling. -// - -#define ALIGN_UP(x) ((x + 15) & ~15) - -#ifdef BIT64 - -// GCC follows the AMD64 ABI calling convention which is considerably different from the Microsoft AMD64 calling convention. -// -// With MSVC, the first four arguments are passed in RCX, RDX, R8, R9 and the remaining on the stack. -// With GCC, the first six arguments are passed in RDI, RSI, RDX, RCX, R8, R9 and the remaining on the stack. - -// => Size of the total number of arguments PAL_TryExcept takes (32 bytes) + -// => 1 stack slot (8 bytes) to preserve "actions" flags when PAL_SEHPersonalityRoutine is invoked during unwind copies -// data to the stack location before fixing the context to invoke PAL_CallRunHandler + -// => 1 stack slot (8 bytes) to ensure stack is 16bytes aligned. -// -// Hence, the 48 bytes frame size. -#define SIZEOF_ARG_REGISTERS 48 -#define FRAME_SIZE ALIGN_UP(SIZEOF_ARG_REGISTERS) - - .text - .globl _PAL_TryExcept -_PAL_TryExcept: -LFB7: - push %rbp -LCFI0: - mov %rsp, %rbp -LCFI1: - sub $FRAME_SIZE, %rsp - mov %rdi, (%rsp) // Move the Body address to the stack - mov %rsi, 8(%rsp) // Move the Filter address to the stack - mov %rdx, 16(%rsp) // Move pvParam (i.e. HandlerData) to the stack - mov %rcx, 24(%rsp) // Move pfExecuteHandler value to the stack - mov %rdi, %r9 // Move the body address to r9 - mov %rdx, %rdi // Move the HandlerData argument to RDI - this will serve as the first (and only) argument passed to the __try block body below -LEHB0: - call *%r9 // ..and invoke the body of the __try block -LEHE0: - xor %rax, %rax // NULL, meaning "do not run handler" - jmp Lepilog - .globl _PAL_CallRunHandler -_PAL_CallRunHandler: - // Note: First two args (actions and exceptionObject) have already been - // setup by PAL_SEHPersonalityRoutine's cleanup phase handling. They are at - // RSP+32 and RSP+48 respectively. - // - // Prepare the arguments to be passed to PAL_RunHandler. - mov 32(%rsp), %rdi // actions - mov 40(%rsp), %rsi // exceptionObject - mov 8(%rsp), %rdx // filter - mov 16(%rsp), %rcx // param - mov 24(%rsp), %r8 // pfExecuteHandler - call _PAL_RunHandler -Lepilog: - leave - ret -LFE7: - -#else // BIT64 - -#define SIZEOF_ARG_REGISTERS 20 -#define FRAME_SIZE ALIGN_UP(8 + SIZEOF_ARG_REGISTERS) - 8 - - .text - .globl _PAL_TryExcept -_PAL_TryExcept: -LFB7: - pushl %ebp -LCFI0: - movl %esp, %ebp -LCFI1: - subl $FRAME_SIZE, %esp - movl 16(%ebp), %eax // param - movl %eax, (%esp) -LEHB0: - call *8(%ebp) // body -LEHE0: - xor %eax, %eax // NULL, meaning "do not run handler" - jmp Lepilog - .globl _PAL_CallRunHandler -_PAL_CallRunHandler: - // note: first two args already set when we get here - mov 12(%ebp), %eax // filter - mov %eax, 8(%esp) - mov 16(%ebp), %eax // param - mov %eax, 12(%esp) - mov 20(%ebp), %eax // pfExecuteHandler - mov %eax, 16(%esp) - call L_PAL_RunHandler$stub -Lepilog: - leave - ret -LFE7: - -#endif // BIT64 else - - .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -CIE_SEHPersonality: - .long LECIE1-LSCIE1 -LSCIE1: - .long 0x0 - .byte 0x1 - #ifdef BIT64 - .ascii "zPLR\0" - .byte 0x1 - .byte 0x78 // data_align: -8 - .byte 16 // return address register: rip - .byte 0x7 - .byte 0x9b - .long _PAL_SEHPersonalityRoutine+4@GOTPCREL - .byte 0x10 - .byte 0x10 - .byte 0xc // DW_CFA_def_cfa - .byte 0x7 // operand1 = rsp - .byte 0x8 // operand2 = offset 8 - .byte 0x80 | 16 // DW_CFA_offset of return address register - .byte 0x1 // operand1 = 1 word - .align 2 -#else // BIT64 - .ascii "zPLR\0" - .byte 0x1 - .byte 0x7c // data_align: -4 - .byte 0x8 // return address register: eip - .byte 0x7 - .byte 0x9b - .long L_PAL_SEHPersonalityRoutine$non_lazy_ptr-. - .byte 0x10 - .byte 0x10 - .byte 0xc // DW_CFA_def_cfa - .byte 0x5 // operand1 = esp - .byte 0x4 // operand2 = offset 4 - .byte 0x80 | 8 // DW_CFA_offset of return address register - .byte 0x1 // operand1 = 1 word - .align 2 -#endif // BIT64 else -LECIE1: - - .globl _PAL_TryExcept.eh -_PAL_TryExcept.eh: -LSFDE1: - .set LLFDE1,LEFDE1-LASFDE1 - .set LFL7,LFE7-LFB7 - .long LLFDE1 -LASFDE1: - .long LASFDE1-CIE_SEHPersonality -#ifdef BIT64 - .quad LFB7-. - .quad LFL7 - .byte 0x8 - .quad 0x0 - .byte 0x4 // DW_CFA_advance_loc4 -#else // BIT64 - .long LFB7-. - .long LFL7 - .byte 0x4 - .long 0x0 - .byte 0x4 // DW_CFA_advance_loc4 -#endif // BIT64 else - .long LCFI0-LFB7 - .byte 0xe // DW_CFA_def_cfa_offset -#ifdef BIT64 - .byte 0x10 - .byte 0x80 | 6 // DW_CFA_offset rbp -#else // BIT64 - .byte 0x8 - .byte 0x80 | 4 // DW_CFA_offset ebp -#endif // BIT64 else - .byte 0x2 - .byte 0x4 // DW_CFA_advance_loc4 - .long LCFI1-LCFI0 - .byte 0xd // DW_CFA_def_cfa_register -#ifdef BIT64 - .byte 6 // operand1 = rbp - .align 2 -#else // BIT64 - .byte 4 // operand1 = ebp - .align 2 -#endif // BIT64 - -LEFDE1: - -#ifndef BIT64 - - .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 -L_PAL_RunHandler$stub: - .indirect_symbol _PAL_RunHandler - hlt ; hlt ; hlt ; hlt ; hlt - - .section __IMPORT,__pointers,non_lazy_symbol_pointers -L_PAL_SEHPersonalityRoutine$non_lazy_ptr: - .indirect_symbol _PAL_SEHPersonalityRoutine - .long 0 - -#endif // !BIT64 - diff --git a/src/pal/src/config.h.in b/src/pal/src/config.h.in index 6a32a57d2c..03f31a0fe9 100644 --- a/src/pal/src/config.h.in +++ b/src/pal/src/config.h.in @@ -13,6 +13,7 @@ #cmakedefine01 HAVE_SYS_TIME_H #cmakedefine01 HAVE_PTHREAD_NP_H #cmakedefine01 HAVE_SYS_LWP_H +#cmakedefine01 HAVE_LIBUNWIND_H #cmakedefine01 HAVE_KQUEUE #cmakedefine01 HAVE_GETPWUID_R diff --git a/src/pal/src/configure.cmake b/src/pal/src/configure.cmake index 0da2498e47..972d6add36 100644 --- a/src/pal/src/configure.cmake +++ b/src/pal/src/configure.cmake @@ -6,6 +6,7 @@ include(CheckIncludeFiles) include(CheckStructHasMember) include(CheckTypeSize) +set(CMAKE_REQUIRED_DEFINITIONS "-D_DEFAULT_SOURCE") check_include_files(ieeefp.h HAVE_IEEEFP_H) check_include_files(alloca.h HAVE_ALLOCA_H) check_include_files(sys/vmparam.h HAVE_SYS_VMPARAM_H) @@ -16,6 +17,7 @@ check_include_files(crt_externs.h HAVE_CRT_EXTERNS_H) check_include_files(sys/time.h HAVE_SYS_TIME_H) check_include_files(pthread_np.h HAVE_PTHREAD_NP_H) check_include_files(sys/lwp.h HAVE_SYS_LWP_H) +check_include_files(libunwind.h HAVE_LIBUNWIND_H) check_function_exists(kqueue HAVE_KQUEUE) check_function_exists(getpwuid_r HAVE_GETPWUID_R) @@ -51,7 +53,6 @@ check_function_exists(semget HAS_SYSV_SEMAPHORES) check_function_exists(pthread_mutex_init HAS_PTHREAD_MUTEXES) check_function_exists(ttrace HAVE_TTRACE) -set(CMAKE_REQUIRED_DEFINITIONS "-D_DEFAULT_SOURCE") check_struct_has_member ("struct stat" st_atimespec "sys/types.h;sys/stat.h" HAVE_STAT_TIMESPEC) check_struct_has_member ("struct stat" st_atimensec "sys/types.h;sys/stat.h" HAVE_STAT_NSEC) check_struct_has_member ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) @@ -76,7 +77,6 @@ set(CMAKE_EXTRA_INCLUDE_FILE procfs.h) check_type_size(prwatch_t PRWATCH_T) set(CMAKE_EXTRA_INCLUDE_FILE) check_type_size(off_t SIZEOF_OFF_T) -set(CMAKE_REQUIRED_DEFINITIONS) check_cxx_symbol_exists(tzname "time.h" HAVE_TZNAME) check_cxx_symbol_exists(timezone "time.h" HAVE_TIMEZONE_VAR) @@ -834,6 +834,7 @@ int main() return 1; }" FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL) +set(CMAKE_REQUIRED_DEFINITIONS) if(CMAKE_SYSTEM_NAME STREQUAL Darwin) set(HAVE_COREFOUNDATION 1) @@ -853,6 +854,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL Darwin) set(HAS_FTRUNCATE_LENGTH_ISSUE 1) set(UNWIND_CONTEXT_IS_UCONTEXT_T 0) else() + if(NOT HAVE_LIBUNWIND_H) + unset(HAVE_LIBUNWIND_H CACHE) + message(FATAL_ERROR "Cannot find libunwind. Try installing libunwind8 and libunwind8-dev (or the appropriate packages for your platform)") + endif() set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(PAL_PTRACE "ptrace((cmd), (pid), (void*)(addr), (data))") set(PAL_PT_ATTACH PTRACE_ATTACH) diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index b3b5d18f87..0b3a51187a 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/src/pal/src/exception/seh-unwind.cpp @@ -28,52 +28,16 @@ Abstract: #include "pal/context.h" #include <dlfcn.h> #include <exception> +#if HAVE_LIBUNWIND_H #define UNW_LOCAL_ONLY #include <libunwind.h> - -//---------------------------------------------------------------------- -// Exception Handling ABI Level I: Base ABI -//---------------------------------------------------------------------- - -typedef UINT_PTR _Unwind_Ptr; - -struct dwarf_eh_bases -{ - _Unwind_Ptr dataRelBase, textRelBase; -}; - -extern "C" _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context *context); -extern "C" _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context *context); - -typedef BYTE fde; -extern "C" const fde *_Unwind_Find_FDE(void *ip, dwarf_eh_bases *bases); - -//---------------------------------------------------------------------- -// Exception Handling ABI Level II: C++ ABI -//---------------------------------------------------------------------- - -struct __cxa_exception -{ - std::type_info *exceptionType; - void (*exceptionDestructor)(void *); - std::unexpected_handler unexpectedHandler; - std::terminate_handler terminateHandler; - __cxa_exception *nextException; - - int handlerCount; - int handlerSwitchValue; - const char *actionRecord; - const char *languageSpecificData; - void *catchTemp; - void *adjustedPtr; - - _Unwind_Exception unwindHeader; -}; +#endif //---------------------------------------------------------------------- // Virtual Unwinding //---------------------------------------------------------------------- +#if HAVE_LIBUNWIND_H #if UNWIND_CONTEXT_IS_UCONTEXT_T static void WinContextToUnwindContext(CONTEXT *winContext, unw_context_t *unwContext) { @@ -195,297 +159,10 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP return TRUE; } - -#if _DEBUG -//---------------------------------------------------------------------- -// Virtual Unwinding Debugging Assertions -//---------------------------------------------------------------------- - -// Print a trace of virtually unwinding the stack. -// This helps us diagnose non-unwindable stacks. -// Unfortunately, calling this function from gdb will not be very useful, -// since gdb makes it look like it had been called directly from "start" -// (whose unwind info says we reached the end of the stack). -// You can still call it from, say, RaiseTheExceptionInternalOnly. - -// (non-static to ease debugging) -void DisplayContext(_Unwind_Context *context) -{ - fprintf(stderr, " ip =%p", _Unwind_GetIP(context)); - fprintf(stderr, " cfa=%p", _Unwind_GetCFA(context)); -#if defined(_X86_) - // TODO: display more registers -#endif - fprintf(stderr, "\n"); -} - -static _Unwind_Reason_Code PrintVirtualUnwindCallback(_Unwind_Context *context, void *pvParam) -{ - int *pFrameNumber = (int *) pvParam; - - void *ip = _Unwind_GetIP(context); - const char *module = NULL; - const char *name = 0; - int offset = 0; - - Dl_info dl_info; - if (dladdr(ip, &dl_info)) - { - module = dl_info.dli_fname; - if (dl_info.dli_sname) - { - name = dl_info.dli_sname; - offset = (char *) ip - (char *) dl_info.dli_saddr; - } - else - { - name = "<img-base>"; - offset = (char *) ip - (char *) dl_info.dli_fbase; - } - } - - if (module) - fprintf(stderr, "#%-3d %s!%s+%d\n", *pFrameNumber, module, name, offset); - else - fprintf(stderr, "#%-3d ??\n", *pFrameNumber); - DisplayContext(context); - (*pFrameNumber)++; - return _URC_NO_REASON; -} - -extern "C" void PAL_PrintVirtualUnwind() -{ - BOOL fEntered = PAL_ReenterForEH(); - - fprintf(stderr, "\nVirtual unwind of PAL thread %p\n", InternalGetCurrentThread()); - int frameNumber = 0; - _Unwind_Reason_Code urc = _Unwind_Backtrace(PrintVirtualUnwindCallback, &frameNumber); - fprintf(stderr, "End of stack (return code=%d).\n", urc); - - if (fEntered) - { - PAL_Leave(PAL_BoundaryEH); - } -} - -static const char *PAL_CHECK_UNWINDABLE_STACKS = "PAL_CheckUnwindableStacks"; - -enum CheckUnwindableStacksMode -{ - // special value to indicate we've not initialized yet - CheckUnwindableStacks_Uninitialized = -1, - - CheckUnwindableStacks_Off = 0, - CheckUnwindableStacks_On = 1, - CheckUnwindableStacks_Thorough = 2, - - CheckUnwindableStacks_Default = CheckUnwindableStacks_On -}; - -static CheckUnwindableStacksMode s_mode = CheckUnwindableStacks_Uninitialized; - -// A variant of the above. This one's not meant for CLR developers to use for tracing, -// but implements debug checks to assert stack consistency. -static _Unwind_Reason_Code CheckVirtualUnwindCallback(_Unwind_Context *context, void *pvParam) -{ - void *ip = _Unwind_GetIP(context); - - // If we reach an IP that we cannot find a module for, - // then we ended up in dynamically-generated code and - // the stack will not be unwindable past this point. - Dl_info dl_info; - if (dladdr(ip, &dl_info) == 0 || - ((s_mode == CheckUnwindableStacks_Thorough) && - ( dl_info.dli_sname == NULL || - ( _Unwind_Find_FDE(ip, NULL) == NULL && - strcmp(dl_info.dli_sname, "start") && - strcmp(dl_info.dli_sname, "_thread_create_running"))))) - { - *(BOOL *) pvParam = FALSE; - } - - return _URC_NO_REASON; -} - -extern "C" void PAL_CheckVirtualUnwind() -{ - if (s_mode == CheckUnwindableStacks_Uninitialized) - { - const char *checkUnwindableStacks = getenv(PAL_CHECK_UNWINDABLE_STACKS); - s_mode = checkUnwindableStacks ? - (CheckUnwindableStacksMode) atoi(checkUnwindableStacks) : CheckUnwindableStacks_Default; - } - - if (s_mode != CheckUnwindableStacks_Off) - { - BOOL fUnwindable = TRUE; - _ASSERTE(_Unwind_Backtrace(CheckVirtualUnwindCallback, &fUnwindable) == _URC_END_OF_STACK); - if (!fUnwindable) - { - PAL_PrintVirtualUnwind(); - ASSERT("Stack not unwindable. Throwing may terminate the process.\n"); - } - } -} -#endif // _DEBUG - -//---------------------------------------------------------------------- -// Registering Vectored Handlers -//---------------------------------------------------------------------- - -static PVECTORED_EXCEPTION_HANDLER VectoredExceptionHandler = NULL; -static PVECTORED_EXCEPTION_HANDLER VectoredContinueHandler = NULL; - -void SetVectoredExceptionHandler(PVECTORED_EXCEPTION_HANDLER pHandler) -{ - PERF_ENTRY(SetVectoredExceptionHandler); - ENTRY("SetVectoredExceptionHandler(pHandler=%p)\n", pHandler); - - _ASSERTE(VectoredExceptionHandler == NULL); - VectoredExceptionHandler = pHandler; - - LOGEXIT("SetVectoredExceptionHandler returns\n"); - PERF_EXIT(SetVectoredExceptionHandler); - -} - -void SetVectoredContinueHandler(PVECTORED_EXCEPTION_HANDLER pHandler) -{ - PERF_ENTRY(SetVectoredContinueHandler); - ENTRY("SetVectoredContinueHandler(pHandler=%p)\n", pHandler); - - _ASSERTE(VectoredContinueHandler == NULL); - VectoredContinueHandler = pHandler; - - LOGEXIT("SetVectoredContinueHandler returns\n"); - PERF_EXIT(SetVectoredContinueHandler); -} - -//---------------------------------------------------------------------- -// Representation of an SEH Exception as a C++ object -//---------------------------------------------------------------------- - -struct PAL_SEHException -{ -public: - // Note that the following two are actually embedded in this heap-allocated - // instance - in contrast to Win32, where the exception record would usually - // be allocated on the stack. This is needed because foreign cleanup handlers - // partially unwind the stack on the second pass. - EXCEPTION_POINTERS ExceptionPointers; - EXCEPTION_RECORD ExceptionRecord; - CONTEXT ContextRecord; - - PAL_SEHException(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContextRecord) - { - ExceptionPointers.ExceptionRecord = &ExceptionRecord; - ExceptionPointers.ContextRecord = &ContextRecord; - ExceptionRecord = *pExceptionRecord; - ContextRecord = *pContextRecord; - nestedExceptionEstablisherFrame = NULL; - } - - static PAL_SEHException *FromExceptionObject(_Unwind_Exception *exceptionObject) - { - if (exceptionObject->exception_class == Class) - { - if (*((__cxa_exception *) (exceptionObject + 1) - 1)->exceptionType == typeid(PAL_SEHException)) - { - return (PAL_SEHException *) (exceptionObject + 1); - } - } - return NULL; - } - - void NestedIn(_Unwind_Context *context) - { - nestedExceptionEstablisherFrame = _Unwind_GetCFA(context); - ExceptionRecord.ExceptionFlags |= EXCEPTION_NESTED_CALL; - } - - void RanThroughFilter(_Unwind_Context *context) - { - if (nestedExceptionEstablisherFrame == _Unwind_GetCFA(context)) - { - // We were processing a nested exception, and we have repeated - // the search phase past the filter that threw the nested exception. - // Thus, clear the corresponding flag now. - ExceptionRecord.ExceptionFlags &= ~EXCEPTION_NESTED_CALL; - } - } - -private: -#ifdef __GNUC__ - static const __uint64_t Class = 0x474e5543432b2b00ULL; // vendor = GNUC, language = C++\0 #else -#error Vendor code not defined for this platform. +#error don't know how to unwind on this platform #endif - // If we encountered a nested exception, the EXCEPTION_NESTED_CALL flag must - // remain set on the exception while unwinding to the frame with the CFA - // stored below. Note that this will always be a PAL_TryExcept frame. - void *nestedExceptionEstablisherFrame; -}; - -EXCEPTION_POINTERS * -PALAPI -PAL_GetExceptionPointers(_Unwind_Exception *exceptionObject) -{ - PAL_SEHException *pSEHException = PAL_SEHException::FromExceptionObject(exceptionObject); - if (pSEHException) - { - return &pSEHException->ExceptionPointers; - } - return NULL; -} - -//---------------------------------------------------------------------- -// Raising Exceptions -//---------------------------------------------------------------------- - -static void DeleteThrownException(_Unwind_Exception *exceptionObject) -{ - // The argument exception has been thrown. - _ASSERTE(std::uncaught_exception()); - - // Deleting it in this way will adjust the uncaught exceptions count. - __cxa_begin_catch(exceptionObject); - __cxa_end_catch(); -} - -static void RunVectoredHandler(EXCEPTION_POINTERS *pExceptionPointers, _Unwind_Exception *exceptionObject, PVECTORED_EXCEPTION_HANDLER pHandler) -{ - if (pHandler != NULL) - { - EXCEPTION_DISPOSITION disposition = pHandler(pExceptionPointers); - switch (disposition) - { - case EXCEPTION_CONTINUE_EXECUTION: - { - BOOL fNonContinuable = pExceptionPointers->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE; - CONTEXT *context = pExceptionPointers->ContextRecord; - if (fNonContinuable) - { - RaiseException(EXCEPTION_NONCONTINUABLE_EXCEPTION, - EXCEPTION_NONCONTINUABLE, 0, NULL); - } - else - { - SetThreadContext(PAL_GetCurrentThread(), context); - } - } - abort(); // should never reach here - case EXCEPTION_CONTINUE_SEARCH: - break; - default: - DeleteThrownException(exceptionObject); - RaiseException(EXCEPTION_INVALID_DISPOSITION, - EXCEPTION_NONCONTINUABLE, 0, NULL); - abort(); // should never reach here - } - } -} - PAL_NORETURN static void RtlpRaiseException(EXCEPTION_RECORD *ExceptionRecord) { @@ -495,35 +172,19 @@ static void RtlpRaiseException(EXCEPTION_RECORD *ExceptionRecord) ContextRecord.ContextFlags = CONTEXT_FULL; CONTEXT_CaptureContext(&ContextRecord); - // Find the caller of RtlpRaiseException. This provides the exact context - // that handlers expect to see, which is the one they would want to fix up - // to resume after a continuable exception. + // Find the caller of RtlpRaiseException. PAL_VirtualUnwind(&ContextRecord, NULL); - // The frame we're looking at now is either RaiseException or PAL_TryExcept. - // If it's RaiseException, we have to unwind one level further to get the - // actual context user code could be resumed at. + // The frame we're looking at now is RaiseException. We have to unwind one + // level further to get the actual context user code could be resumed at. + PAL_VirtualUnwind(&ContextRecord, NULL); #if defined(_X86_) - void *pc = (void *) ContextRecord.Eip; + ExceptionRecord->ExceptionAddress = (void *) ContextRecord.Eip; #elif defined(_AMD64_) - void *pc = (void *) ContextRecord.Rip; + ExceptionRecord->ExceptionAddress = (void *) ContextRecord.Rip; #else #error unsupported architecture #endif - if ((SIZE_T) pc - (SIZE_T) RaiseException < (SIZE_T) pc - (SIZE_T) PAL_TryExcept) - { - PAL_VirtualUnwind(&ContextRecord, NULL); -#if defined(_PPC_) - pc = (void *) ContextRecord.Iar; -#elif defined(_X86_) - pc = (void *) ContextRecord.Eip; -#elif defined(_AMD64_) - pc = (void *) ContextRecord.Rip; -#else -#error unsupported architecture -#endif - } - ExceptionRecord->ExceptionAddress = pc; EXCEPTION_POINTERS pointers; pointers.ExceptionRecord = ExceptionRecord; @@ -533,155 +194,11 @@ static void RtlpRaiseException(EXCEPTION_RECORD *ExceptionRecord) } PAL_NORETURN -static void RaiseExceptionObject(_Unwind_Exception *exceptionObject) -{ - // Dummy exception record for use by foreign exceptions. - EXCEPTION_RECORD ForeignExceptionRecord = { EXCEPTION_FOREIGN, EXCEPTION_NONCONTINUABLE, NULL, NULL, 0 }; - EXCEPTION_POINTERS ForeignExceptionPointers = { &ForeignExceptionRecord, NULL }; - - bool fSkipVEH = false; - - EXCEPTION_POINTERS *pExceptionPointers = PAL_GetExceptionPointers(exceptionObject); - if (!pExceptionPointers) - { - pExceptionPointers = &ForeignExceptionPointers; - } - else - { - fSkipVEH =(pExceptionPointers->ExceptionRecord->ExceptionFlags & EXCEPTION_SKIP_VEH)?true:false; - if (!fSkipVEH) - { - // For exceptions that we know about, keep a reference in the corresponding - // EXCEPTION_RECORD incase this turns out to be an async exception in managed code. - pExceptionPointers->ExceptionRecord->ExceptionInformation[NATIVE_EXCEPTION_ASYNC_SLOT] = (ULONG_PTR)exceptionObject; - } - } - - if (!fSkipVEH) - { - RunVectoredHandler(pExceptionPointers, exceptionObject, VectoredExceptionHandler); - } - - _Unwind_Reason_Code urc; - PAL_Leave(PAL_BoundaryEH); - urc = _Unwind_RaiseException(exceptionObject); - - // _Unwind_RaiseException is supposed to return an _Unwind_Reason_Code. - // However, it's not implemented according to spec. So we always have - // to assume that we got _URC_END_OF_STACK. - if (urc == (_Unwind_Reason_Code) (UINT_PTR) exceptionObject) - { - urc = _URC_END_OF_STACK; - } - _ASSERTE(urc == _URC_END_OF_STACK); - - PAL_Reenter(PAL_BoundaryEH); - RunVectoredHandler(pExceptionPointers, exceptionObject, VectoredContinueHandler); - - DeleteThrownException(exceptionObject); - - WARN("unhandled exception; terminating self\n"); - - abort(); - // unreached -} - -static void ThrowHelper(void *pvParam) -{ - PEXCEPTION_POINTERS lpExceptionPointers = (PEXCEPTION_POINTERS) pvParam; - PAL_Leave(PAL_BoundaryEH); - throw PAL_SEHException(lpExceptionPointers->ExceptionRecord, lpExceptionPointers->ContextRecord); -} - -static void RethrowHelper(void *pvParam) -{ - PAL_Leave(PAL_BoundaryEH); - throw; -} - -static EXCEPTION_DISPOSITION ThrowFilter( - EXCEPTION_POINTERS *ExceptionPointers, - PAL_DISPATCHER_CONTEXT *DispatcherContext, - void *pvParam) -{ - return EXCEPTION_EXECUTE_HANDLER; -} - -PAL_NORETURN -VOID -PALAPI -PAL_CppRethrow() -{ - // Throw the exception using C++ throw, but intercept the exception so that - // we can raise it using our runtime, which supported vectored handlers. - BOOL fExecuteHandler; - _Unwind_Exception *exceptionObject = - PAL_TryExcept(RethrowHelper, ThrowFilter, NULL, &fExecuteHandler); - _ASSERTE(exceptionObject != NULL); - PAL_CheckVirtualUnwind(); - RaiseExceptionObject(exceptionObject); -} - -PAL_NORETURN void SEHRaiseException(CPalThread *pthrCurrent, PEXCEPTION_POINTERS lpExceptionPointers, int signal_code) { - _Unwind_Exception *exceptionObject = NULL; - - if (lpExceptionPointers->ExceptionRecord->ExceptionFlags & EXCEPTION_SKIP_VEH) - { - // If we are going to skip VEH, then it implies we are going to dispatch - // an async exception in managed code. For this case, extract the - // native exception object from the ExceptionInformation array that was saved there - // when PAL_DispatchException had initially raised the exception. - exceptionObject = (_Unwind_Exception *)lpExceptionPointers->ExceptionRecord->ExceptionInformation[NATIVE_EXCEPTION_ASYNC_SLOT]; - lpExceptionPointers->ExceptionRecord->ExceptionInformation[NATIVE_EXCEPTION_ASYNC_SLOT] = (ULONG_PTR)NULL; - } - - if (exceptionObject == NULL) - { - // Throw the exception using C++ throw, but intercept the exception so that - // we can raise it using our runtime, which supported vectored handlers. - BOOL fExecuteHandler; - exceptionObject = PAL_TryExcept(ThrowHelper, ThrowFilter, lpExceptionPointers, &fExecuteHandler); - } - - _ASSERTE(exceptionObject != NULL); - - // Note: We cannot call PAL_CheckVirtualUnwind here, since we this function - // may be called for a fault in dynamically-generated code. - -#if defined(_AMD64_) - // When PAL_TryExcept returns, it has executed the second pass for handling the exception - // that was raised by ThrowHelper. As part of processing the second pass, PAL_RunHandler - // would have set the EXCEPTION_UNWINDING flag (and possibly, even the EXCEPTION_TARGET_UNWIND flag) - // in the ExceptionRecord contained inside the exception object. - // - // When this exception object is passed to the RunVectoredExceptionHandler, the exception pointers - // passed to the vectored handler would be the one extracted from the exception object. Since that - // would have the unwinding flag set, any code that checks for the flag to conditional process the - // exception would go awry. - // - // To fix this problem, we will fetch the ExceptionPointers from the exception object and clear off - // any such flags. - // - // Note 1: This problem is also present when the exception object is seen by the various native - // personality routines (e.g. UnwindThunkPersonality). However, stack frame based handling - // of exceptions is not affected by this problem since all of our native personality routines - // clear off the existing flags and reset them again based upon the active phase (first or second) - // of exception dispatch before passing the exception record to CLR's managed personality routines. - // - // Note 2: This problem is also applicable to Mac X86. TODO: Fix this problem for MacX86. - EXCEPTION_POINTERS *pExceptionPointers = PAL_GetExceptionPointers(exceptionObject); - _ASSERTE(pExceptionPointers != NULL); - - // Clear of the EXCEPTION_UNWINDING/EXCEPTION_TARGET_UNWIND flags - pExceptionPointers->ExceptionRecord->ExceptionFlags = - (pExceptionPointers->ExceptionRecord->ExceptionFlags & ~(EXCEPTION_UNWINDING|EXCEPTION_TARGET_UNWIND)); -#endif // defined(_AMD64_) - - RaiseExceptionObject(exceptionObject); + throw PAL_SEHException(lpExceptionPointers->ExceptionRecord, lpExceptionPointers->ContextRecord); } /*++ @@ -712,7 +229,13 @@ RaiseException(IN DWORD dwExceptionCode, dwExceptionCode ^= RESERVED_SEH_BIT; } - PAL_CheckVirtualUnwind(); + if (nNumberOfArguments > EXCEPTION_MAXIMUM_PARAMETERS) + { + WARN("Number of arguments (%d) exceeds the limit " + "EXCEPTION_MAXIMUM_PARAMETERS (%d); ignoring extra parameters.\n", + nNumberOfArguments, EXCEPTION_MAXIMUM_PARAMETERS); + nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; + } EXCEPTION_RECORD exceptionRecord; ZeroMemory(&exceptionRecord, sizeof(EXCEPTION_RECORD)); @@ -724,13 +247,6 @@ RaiseException(IN DWORD dwExceptionCode, exceptionRecord.NumberParameters = nNumberOfArguments; if (nNumberOfArguments) { - if (nNumberOfArguments > EXCEPTION_MAXIMUM_PARAMETERS) - { - WARN("Number of arguments (%d) exceeds the limit " - "EXCEPTION_MAXIMUM_PARAMETERS (%d); ignoring extra parameters.\n", - nNumberOfArguments, EXCEPTION_MAXIMUM_PARAMETERS); - nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; - } CopyMemory(exceptionRecord.ExceptionInformation, lpArguments, nNumberOfArguments * sizeof(ULONG_PTR)); } @@ -738,372 +254,3 @@ RaiseException(IN DWORD dwExceptionCode, LOGEXIT("RaiseException returns\n"); } - -PAL_NORETURN -VOID -PALAPI -PAL_RaiseException( - IN PEXCEPTION_POINTERS ExceptionPointers) -{ - PAL_CheckVirtualUnwind(); - ExceptionPointers->ExceptionRecord->ExceptionFlags |= EXCEPTION_NONCONTINUABLE; - SEHRaiseException(InternalGetCurrentThread(), ExceptionPointers, 0); -} - -//---------------------------------------------------------------------- -// SEH Personality -//---------------------------------------------------------------------- - -#if defined(__LINUX__) || defined(__APPLE__) -// TODO: Enable these routines for Linux. -EXCEPTION_DISPOSITION -PAL_RunFilter( - PEXCEPTION_POINTERS ExceptionPointers, - PAL_DISPATCHER_CONTEXT *DispatcherContext, - void *pvParam, - PFN_PAL_EXCEPTION_FILTER Filter) -{ - _ASSERT(FALSE); - return 0; -} - -void PAL_CallRunHandler() -{ - _ASSERT(FALSE); -} - -extern "C" -PALAPI -struct _Unwind_Exception *PAL_TryExcept( - PFN_PAL_BODY pfnBody, - PFN_PAL_EXCEPTION_FILTER pfnFilter, - void *pvParam, - BOOL *pfExecuteHandler) -{ - // UNIXTODO: Exception handling - pfnBody(pvParam); - *pfExecuteHandler = FALSE; - return NULL; -} -#else -// from runfilter.s -extern "C" -EXCEPTION_DISPOSITION -PAL_RunFilter(PEXCEPTION_POINTERS ExceptionPointers, - PAL_DISPATCHER_CONTEXT *DispatcherContext, - void *pvParam, - PFN_PAL_EXCEPTION_FILTER Filter); -extern "C" void PAL_CallRunHandler(); -#endif // __LINUX__ - -extern "C" -_Unwind_Reason_Code PAL_SEHPersonalityRoutine( - int version, - _Unwind_Action actions, - __uint64_t exceptionClass, - _Unwind_Exception *exceptionObject, - _Unwind_Context *context) -{ - _Unwind_Reason_Code urc = _URC_NO_REASON; - PAL_Reenter(PAL_BoundaryEH); - - TRACE("actions=%x\n", actions); - _ASSERTE(version == 1); - - // Determine what state the frame is in for which this personality routine - // was invoked. The only function this personality routine is affiliated - // with is PAL_TryExcept, which is assembly code. That function contains - // two calls: one to run the try block, one to run a handler. The - // PAL_CallRunHandler label sits in-between these two, thus we can - // use it to make the distinction which call the exception escaped from. - if (_Unwind_GetIP(context) > (void *) PAL_CallRunHandler) - { - // This personality routine had invoked the handler associated - // with this frame, and the handler raised an exception. - // This is called a "collided unwind". - TRACE("collided unwind\n"); - PAL_SEHException *pSEHException = PAL_SEHException::FromExceptionObject(exceptionObject); - if (pSEHException) - { - pSEHException->ExceptionRecord.ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND; - } - urc = _URC_CONTINUE_UNWIND; - goto exit; - } - - if ((actions & _UA_PHASE_MASK) == _UA_SEARCH_PHASE) - { - // Determine whether this is an SEH exception or a foreign exception. - PAL_SEHException *pSEHException = PAL_SEHException::FromExceptionObject(exceptionObject); - if (pSEHException) - { - pSEHException->ExceptionRecord.ExceptionFlags &= ~EXCEPTION_UNWIND; - } - - // Obtain the filter and parameter from the original frame. - PFN_PAL_EXCEPTION_FILTER pfnFilter; - void *pvParam; -#if defined(_X86_) - pfnFilter = ((PFN_PAL_EXCEPTION_FILTER *) _Unwind_GetGR(context, 4))[3]; // [ebp+12] - pvParam = ((void **) _Unwind_GetGR(context, 4))[4]; // [ebp+16] -#elif defined(_AMD64_) - // Filter address is stored at RSP+8 - // pvParam is stored at RSP+16 - // Refer to PAL_TryExcept implementation for details. - pfnFilter = ((PFN_PAL_EXCEPTION_FILTER *) _Unwind_GetCFA(context))[1]; - pvParam = ((void **) _Unwind_GetCFA(context))[2]; -#else -#error unsupported architecture -#endif - - // Make some of our state available to the filter. - PAL_DISPATCHER_CONTEXT dispatcherContext; - dispatcherContext.actions = actions; - dispatcherContext.exception_object = exceptionObject; - dispatcherContext.context = context; - - // Dummy exception record for use by foreign exceptions. - EXCEPTION_RECORD ForeignExceptionRecord = { EXCEPTION_FOREIGN, EXCEPTION_NONCONTINUABLE, NULL, NULL, 0 }; - EXCEPTION_POINTERS ForeignExceptionPointers = { &ForeignExceptionRecord, NULL }; - - // Run the filter. If this throws, the PAL_SEHFilterPersonalityRoutine - // will be invoked. - EXCEPTION_DISPOSITION disposition = - PAL_RunFilter(pSEHException ? &pSEHException->ExceptionPointers : &ForeignExceptionPointers, - &dispatcherContext, - pvParam, pfnFilter); - TRACE("filter returned %d\n", disposition); - - if (pSEHException) - { - pSEHException->RanThroughFilter(context); - } - - switch (disposition) - { - case EXCEPTION_CONTINUE_EXECUTION: - if (!pSEHException || // foreign exceptions are never continuable - (pSEHException->ExceptionRecord.ExceptionFlags & EXCEPTION_NONCONTINUABLE)) - { - DeleteThrownException(exceptionObject); - RaiseException(EXCEPTION_NONCONTINUABLE_EXCEPTION, - EXCEPTION_NONCONTINUABLE, 0, NULL); - } - else - { - CONTEXT *newContext = pSEHException->ExceptionPointers.ContextRecord; - DeleteThrownException(exceptionObject); - SetThreadContext(PAL_GetCurrentThread(), newContext); - } - abort(); // should never reach here - case EXCEPTION_EXECUTE_HANDLER: - urc = _URC_HANDLER_FOUND; - goto exit; - case EXCEPTION_CONTINUE_SEARCH: - urc = _URC_CONTINUE_UNWIND; - goto exit; - default: - DeleteThrownException(exceptionObject); - RaiseException(EXCEPTION_INVALID_DISPOSITION, - EXCEPTION_NONCONTINUABLE, 0, NULL); - // The above call should never return, but the compiler doesn't know that. - urc = _URC_FATAL_PHASE1_ERROR; - goto exit; - } - } - else - { - _ASSERTE((actions & _UA_PHASE_MASK) == _UA_CLEANUP_PHASE); - - // There is a cleanup to run. Here we behave differently from - // Windows SEH: We unwind the stack up to the frame that installed - // this personality routine, and run the handler from there. - // The advantage is that this is consistent with C++ on this - // platform, wich unwinds the stack also to run destructors for - // objects allocated on the stack. By behaving in the same way, - // we can deal with C++ exceptions colliding with SEH unwinds. -#if defined(_PPC_) - _Unwind_SetGR(context, 3, (void *) actions); - _Unwind_SetGR(context, 4, exceptionObject); -#elif defined(_X86_) - void **args = (void **) _Unwind_GetCFA(context); - args[0] = (void *) actions; - args[1] = exceptionObject; -#elif defined(_AMD64_) - // We have allocated two slots on the stack for preserving these two. - // They are beyond the locations where we spilled the args to PAL_TryExcept - // and hence, are at RSP+32 and RSP+40 respectively. - void **args = (void **) _Unwind_GetCFA(context); - args[4] = (void *) actions; - args[5] = exceptionObject; -#else -#error unsupported architecture -#endif - TRACE("unwinding to ip=%p, cfa=%p\n", _Unwind_GetIP(context), _Unwind_GetCFA(context)); - - // Fix the context to invoke PAL_CallRunHandler - _Unwind_SetIP(context, (void *) PAL_CallRunHandler); - urc = _URC_INSTALL_CONTEXT; - goto exit; - } - -exit: - _ASSERTE(urc != _URC_NO_REASON); - if (urc != _URC_INSTALL_CONTEXT) - { - // If we're installing a context, it's because we want to run - // code that depends on the PAL. Otherwise, bye-bye. - PAL_Leave(PAL_BoundaryEH); - } - return urc; -} - -extern "C" -_Unwind_Exception *PAL_RunHandler( - _Unwind_Action actions, - _Unwind_Exception *exceptionObject, - PFN_PAL_EXCEPTION_FILTER pfnFilter, - void *pvParam, - BOOL *pfExecuteHandler) -{ - _ASSERTE((actions & _UA_PHASE_MASK) == _UA_CLEANUP_PHASE); - - PAL_SEHException *pSEHException = PAL_SEHException::FromExceptionObject(exceptionObject); - - PAL_DISPATCHER_CONTEXT dispatcherContext; - dispatcherContext.actions = actions; - dispatcherContext.exception_object = exceptionObject; - dispatcherContext.context = NULL; - - // Dummy exception record for use by foreign exceptions. - EXCEPTION_RECORD ForeignExceptionRecord = { EXCEPTION_FOREIGN, EXCEPTION_NONCONTINUABLE, NULL, NULL, 0 }; - EXCEPTION_POINTERS ForeignExceptionPointers = { &ForeignExceptionRecord, NULL }; - EXCEPTION_RECORD *pExceptionRecord = &ForeignExceptionRecord; - if (pSEHException) - { - pExceptionRecord = &pSEHException->ExceptionRecord; - } - - pExceptionRecord->ExceptionFlags = - (pExceptionRecord->ExceptionFlags & ~(EXCEPTION_UNWINDING|EXCEPTION_TARGET_UNWIND)) | - EXCEPTION_UNWINDING | ((actions & _UA_HANDLER_FRAME) ? EXCEPTION_TARGET_UNWIND : 0); - - EXCEPTION_DISPOSITION disposition; - PAL_CPP_TRY - { - // MACTODO: Why do we invoke the PAL_EXCEPT macro's filter in the - // unwind pass when it simply returns with the original disposition that - // was provided in the first pass? - disposition = pfnFilter(pSEHException ? &pSEHException->ExceptionPointers : &ForeignExceptionPointers, - &dispatcherContext, pvParam); - } - PAL_CPP_CATCH_ALL - { - // In case of a collided unwind, delete the original exception - // and propagate the new one instead. - _Unwind_DeleteException(exceptionObject); - PAL_CPP_RETHROW; - } - PAL_CPP_ENDTRY - - if ((actions & _UA_HANDLER_FRAME) && disposition == EXCEPTION_EXECUTE_HANDLER) - { - // Return to PAL_TryExcept, which will return the exception that - // occurred, so that the PAL_EXCEPT/PAL_FINALLY body will be run. - *pfExecuteHandler = TRUE; - return exceptionObject; - } - else if (~(actions & _UA_HANDLER_FRAME) && disposition == EXCEPTION_CONTINUE_SEARCH) - { - // Cleanups have been run for this frame; continue running cleanups - // up the stack. - *pfExecuteHandler = FALSE; - return exceptionObject; - } - else - { - // This filter misbehaved; it claimed it would handle/not handle - // the exception, but it didn't/did. - DeleteThrownException(exceptionObject); - RaiseException(EXCEPTION_INVALID_DISPOSITION, - EXCEPTION_NONCONTINUABLE, 0, NULL); - // The above call should never return, but the compiler doesn't know that. - return NULL; - } -} - -//---------------------------------------------------------------------- -// SEH Filter Personality -//---------------------------------------------------------------------- - -extern "C" -_Unwind_Reason_Code PAL_SEHFilterPersonalityRoutine( - int version, - _Unwind_Action actions, - __uint64_t exceptionClass, - _Unwind_Exception *exceptionObject, - _Unwind_Context *context) -{ - PAL_Reenter(PAL_BoundaryEH); - - _ASSERTE(version == 1); - - // When this personality routine runs, we have two activations - // of _Unwind_RaiseException: The outer _Unwind_RaiseException - // was running a filter in the search phase, and that filter - // threw an exception. This is called a "nested exception". - // The inner _Unwind_RaiseException activation is dispatching - // the nested exception, and called this routine. - TRACE("actions=%x\n", actions); - - // Retrieve the dispatcher context of the outer _Unwind_RaiseException. - PAL_DISPATCHER_CONTEXT *outerDispatcherContext; -#if defined(_X86_) - outerDispatcherContext = (PAL_DISPATCHER_CONTEXT *) ((void **) _Unwind_GetGR(context, 4))[3]; // [ebp+12] -#elif defined(_AMD64_) - // Filter address is stored at RSP+8 - // Refer to PAL_RunFilter implementation for details. - outerDispatcherContext = (PAL_DISPATCHER_CONTEXT *)((void **)_Unwind_GetCFA(context))[1]; -#else -#error unsupported architecture -#endif - _ASSERTE(outerDispatcherContext->actions & _UA_SEARCH_PHASE); - - if ((actions & _UA_PHASE_MASK) == _UA_SEARCH_PHASE) - { - TRACE("nested exception\n"); - PAL_SEHException *pSEHException = PAL_SEHException::FromExceptionObject(exceptionObject); - if (pSEHException) - { - pSEHException->NestedIn(outerDispatcherContext->context); - } - else - { - // A foreign exception escaped from a filter. This is not a - // supported action for a filter to take (neither in our SEH - // model, nor in the unwind library's model). Let the system - // execute its (unspecified) behavior. - } - PAL_Leave(PAL_BoundaryEH); - return _URC_CONTINUE_UNWIND; - } - else - { - _ASSERTE((actions & _UA_PHASE_MASK) == _UA_CLEANUP_PHASE); - - // Rethrowing the exception itself from a filter is not supported. - // (That would mess up reference counting of the exception object - // in standard C++.) - _ASSERT(outerDispatcherContext->exception_object != exceptionObject); - - // We're in the cleanup phase of a nested exception. This means - // that nobody fixed up the context of that exception and resumed - // execution. In other words, we'll never resume the outer unwind - // and we have to clean up its state. - _Unwind_DeleteException(outerDispatcherContext->exception_object); - - // No cleanup to run for a nested exception. - PAL_Leave(PAL_BoundaryEH); - return _URC_CONTINUE_UNWIND; - } -} diff --git a/src/pal/src/init/pal.cpp b/src/pal/src/init/pal.cpp index 18e5f239e1..336a11c439 100644 --- a/src/pal/src/init/pal.cpp +++ b/src/pal/src/init/pal.cpp @@ -93,7 +93,7 @@ static PCRITICAL_SECTION init_critsec = NULL; char g_szCoreCLRPath[MAX_PATH] = { 0 }; static BOOL INIT_IncreaseDescriptorLimit(void); -static LPWSTR INIT_FormatCommandLine (CPalThread *pThread, int argc, const char **argv); +static LPWSTR INIT_FormatCommandLine (CPalThread *pThread, int argc, const char * const *argv); static LPWSTR INIT_FindEXEPath(CPalThread *pThread, LPCSTR exe_name); #ifdef _DEBUG @@ -135,7 +135,7 @@ int PALAPI PAL_Initialize( int argc, - const char *argv[]) + const char *const argv[]) { PAL_ERROR palError = ERROR_GEN_FAILURE; CPalThread *pThread = NULL; @@ -1064,7 +1064,7 @@ Note : not all peculiarities of Windows command-line processing are supported; passed to argv as \\a... there may be other similar cases -there may be other characters which must be escaped --*/ -static LPWSTR INIT_FormatCommandLine (CPalThread *pThread, int argc, const char **argv) +static LPWSTR INIT_FormatCommandLine (CPalThread *pThread, int argc, const char * const *argv) { LPWSTR retval; LPSTR command_line=NULL, command_ptr; diff --git a/src/pal/tests/palsuite/CMakeLists.txt b/src/pal/tests/palsuite/CMakeLists.txt index 4eda0238de..7095aa691b 100644 --- a/src/pal/tests/palsuite/CMakeLists.txt +++ b/src/pal/tests/palsuite/CMakeLists.txt @@ -9,7 +9,7 @@ add_compile_options(-Wno-int-to-void-pointer-cast) # TODO: make these tests compile # add_subdirectory(composite) -# add_subdirectory(exception_handling) +add_subdirectory(exception_handling) add_subdirectory(c_runtime) add_subdirectory(debug_api) diff --git a/src/pal/tests/palsuite/common/palsuite.h b/src/pal/tests/palsuite/common/palsuite.h index b61435ff48..4156f10190 100644 --- a/src/pal/tests/palsuite/common/palsuite.h +++ b/src/pal/tests/palsuite/common/palsuite.h @@ -18,6 +18,7 @@ #ifndef __PALSUITE_H__ #define __PALSUITE_H__ +#include <pal_assert.h> #include <pal.h> enum @@ -27,7 +28,7 @@ enum }; -void Trace(char *format, ...) +void Trace(const char *format, ...) { va_list arglist; @@ -38,7 +39,7 @@ void Trace(char *format, ...) va_end(arglist); } -void Fail(char *format, ...) +void Fail(const char *format, ...) { va_list arglist; diff --git a/src/pal/tests/palsuite/exception_handling/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/CMakeLists.txt index 23e82e1a7f..3e2c9eb9b5 100644 --- a/src/pal/tests/palsuite/exception_handling/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/CMakeLists.txt @@ -1,13 +1,13 @@ cmake_minimum_required(VERSION 2.8.12.2) -add_subdirectory(pal_except) -add_subdirectory(PAL_EXCEPT_FILTER) -add_subdirectory(PAL_EXCEPT_FILTER_EX) -add_subdirectory(pal_finally) -add_subdirectory(PAL_GetBottommostRegistration) -add_subdirectory(PAL_TRY_EXCEPT) -add_subdirectory(PAL_TRY_EXCEPT_EX) -add_subdirectory(PAL_TRY_LEAVE_FINALLY) +#add_subdirectory(pal_except) +#add_subdirectory(PAL_EXCEPT_FILTER) +#add_subdirectory(PAL_EXCEPT_FILTER_EX) +#add_subdirectory(pal_finally) +#add_subdirectory(PAL_GetBottommostRegistration) +#add_subdirectory(PAL_TRY_EXCEPT) +#add_subdirectory(PAL_TRY_EXCEPT_EX) +#add_subdirectory(PAL_TRY_LEAVE_FINALLY) add_subdirectory(RaiseException) -add_subdirectory(SetUnhandledExceptionFilter) +#add_subdirectory(SetUnhandledExceptionFilter) diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt index 48a7d44d79..3cd0a1f747 100644 --- a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test1.c + test1.cpp ) add_executable(paltest_raiseexception_test1 diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.c b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp index 2908aeb4d3..1e8dfaa34b 100644 --- a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.c +++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp @@ -17,11 +17,12 @@ #include <palsuite.h> +BOOL bExcept = FALSE; +BOOL bTry = FALSE; +BOOL bFinally = FALSE; + int __cdecl main(int argc, char *argv[]) { - BOOL bExcept = FALSE; - BOOL bTry = FALSE; - BOOL bFinally = FALSE; if(0 != (PAL_Initialize(argc, argv))) { @@ -31,7 +32,7 @@ int __cdecl main(int argc, char *argv[]) /********************************************************* * Tests that RaiseException throws a catchable exception */ - PAL_TRY + PAL_TRY(VOID*, unused, NULL) { bTry = TRUE; RaiseException(0,0,0,0); @@ -72,9 +73,9 @@ int __cdecl main(int argc, char *argv[]) * PAL_FINALLY * (bFinally should be set before bExcept) */ - PAL_TRY + PAL_TRY(VOID*, unused, NULL) { - PAL_TRY + PAL_TRY(VOID*, unused, NULL) { bTry = TRUE; RaiseException(0,0,0,0); diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt index fbb9a60a98..f7715f5b07 100644 --- a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test2.c + test2.cpp ) add_executable(paltest_raiseexception_test2 diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.c b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp index 7c08c15ea8..0265ce8114 100644 --- a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.c +++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp @@ -19,9 +19,9 @@ #include <palsuite.h> -BOOL bFilter = FALSE; -BOOL bTry = FALSE; -const int nValidator = 0; +BOOL bFilter; +BOOL bTry; +BOOL bExcept; ULONG_PTR lpArguments_test1[EXCEPTION_MAXIMUM_PARAMETERS]; DWORD nArguments_test1 = EXCEPTION_MAXIMUM_PARAMETERS; @@ -35,7 +35,7 @@ DWORD nArguments_test2 = EXCEPTION_MAXIMUM_PARAMETERS+1; ** Filter function that checks for the parameters ** **/ -LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *pnTestInt) +LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *unused) { int i; @@ -81,7 +81,7 @@ LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *pnTestInt) ** Filter function that checks for the maximum parameters ** **/ -LONG Filter_test2(EXCEPTION_POINTERS* ep, VOID *pnTestInt) +LONG Filter_test2(EXCEPTION_POINTERS* ep, VOID* unused) { /* let the main know we've hit the filter function */ bFilter = TRUE; @@ -99,8 +99,7 @@ LONG Filter_test2(EXCEPTION_POINTERS* ep, VOID *pnTestInt) int __cdecl main(int argc, char *argv[]) { - int i; - BOOL bExcept = FALSE; + bExcept = FALSE; if (0 != PAL_Initialize(argc, argv)) { @@ -111,12 +110,12 @@ int __cdecl main(int argc, char *argv[]) * Test that the correct arguments are passed * to the filter by RaiseException */ - PAL_TRY + PAL_TRY(VOID*, unused, NULL) { bTry = TRUE; /* indicate we hit the PAL_TRY block */ /* Initialize arguments to pass to filter */ - for( i = 0; ((DWORD)i) < nArguments_test1; i++ ) + for(int i = 0; ((DWORD)i) < nArguments_test1; i++ ) { lpArguments_test1[i] = i; } @@ -126,7 +125,7 @@ int __cdecl main(int argc, char *argv[]) Fail("RaiseException: ERROR -> code was executed after the " "exception was raised.\n"); } - PAL_EXCEPT_FILTER(Filter_test1, (LPVOID)&nValidator) + PAL_EXCEPT_FILTER(Filter_test1) { if (!bTry) { @@ -170,12 +169,12 @@ int __cdecl main(int argc, char *argv[]) * exceeds EXCEPTION_MAXIMUM_PARAMETERS, even though we * pass a greater number of arguments */ - PAL_TRY + PAL_TRY(VOID*, unused, NULL) { bTry = TRUE; /* indicate we hit the PAL_TRY block */ /* Initialize arguments to pass to filter */ - for( i = 0; ((DWORD)i) < nArguments_test2; i++ ) + for(int i = 0; ((DWORD)i) < nArguments_test2; i++ ) { lpArguments_test2[i] = i; } @@ -185,7 +184,7 @@ int __cdecl main(int argc, char *argv[]) Fail("RaiseException: ERROR -> code was executed after the " "exception was raised.\n"); } - PAL_EXCEPT_FILTER(Filter_test2, (LPVOID)&nValidator) + PAL_EXCEPT_FILTER(Filter_test2) { if (!bTry) { diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt index c176afcae4..61125b4d7d 100644 --- a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt +++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12.2) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SOURCES - test.c + test.cpp ) add_executable(paltest_raiseexception_test3 diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.c b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp index 434d475a66..1b0d4ec8ab 100644 --- a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.c +++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp @@ -17,16 +17,15 @@ #include <palsuite.h> BOOL bFilter = FALSE; -BOOL bTry = FALSE; -const int nValidator = 0; - +BOOL bTry = FALSE; +BOOL bExcept = FALSE; /** ** ** Filter function that checks for the parameters ** **/ -LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *pnTestInt) +LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID* unused) { /* let the main know we've hit the filter function */ bFilter = TRUE; @@ -53,7 +52,7 @@ LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *pnTestInt) int __cdecl main(int argc, char *argv[]) { - BOOL bExcept = FALSE; + bExcept = FALSE; if (0 != PAL_Initialize(argc, argv)) { @@ -64,7 +63,7 @@ int __cdecl main(int argc, char *argv[]) * Test that the correct arguments are passed * to the filter by RaiseException */ - PAL_TRY + PAL_TRY(VOID*, unused, NULL) { bTry = TRUE; /* indicate we hit the PAL_TRY block */ @@ -75,7 +74,7 @@ int __cdecl main(int argc, char *argv[]) Fail("RaiseException: ERROR -> code was executed after the " "exception was raised.\n"); } - PAL_EXCEPT_FILTER(Filter_test1, (LPVOID)&nValidator) + PAL_EXCEPT_FILTER(Filter_test1) { if (!bTry) { diff --git a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c index a2c6f639df..48cd83efb4 100644 --- a/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c +++ b/src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c @@ -84,7 +84,7 @@ int __cdecl main(int argc, char *argv[]) */ TimeDiff[i] = (DWORD)(((EndTime.QuadPart - StartTime.QuadPart)*1000)/ (Freq.QuadPart)); - TotalTimeDiff += abs(TimeDiff[i] - SleepInterval); + TotalTimeDiff += TimeDiff[i] - SleepInterval; } diff --git a/src/pal/tests/palsuite/paltestlist.txt b/src/pal/tests/palsuite/paltestlist.txt index fa3183e5e7..920a0cbb9b 100644 --- a/src/pal/tests/palsuite/paltestlist.txt +++ b/src/pal/tests/palsuite/paltestlist.txt @@ -438,6 +438,9 @@ c_runtime/_wsplitpath/test1/paltest_wsplitpath_test1 c_runtime/_wtoi/test1/paltest_wtoi_test1 c_runtime/__iscsym/test1/paltest_iscsym_test1 debug_api/OutputDebugStringW/test1/paltest_outputdebugstringw_test1 +exception_handling/RaiseException/test1/paltest_raiseexception_test1 +exception_handling/RaiseException/test2/paltest_raiseexception_test2 +exception_handling/RaiseException/test3/paltest_raiseexception_test3 filemapping_memmgt/CreateFileMappingA/test1/paltest_createfilemappinga_test1 filemapping_memmgt/CreateFileMappingA/test3/paltest_createfilemappinga_test3 filemapping_memmgt/CreateFileMappingA/test4/paltest_createfilemappinga_test4 diff --git a/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt b/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt index 0f135a040b..64b87d518a 100644 --- a/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt +++ b/src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt @@ -57,9 +57,6 @@ exception_handling/PAL_TRY_EXCEPT_EX/test1/paltest_pal_try_except_ex_test1 exception_handling/PAL_TRY_EXCEPT_EX/test2/paltest_pal_try_except_ex_test2 exception_handling/PAL_TRY_EXCEPT_EX/test3/paltest_pal_try_except_ex_test3 exception_handling/PAL_TRY_LEAVE_FINALLY/test1/paltest_pal_try_leave_finally_test1 -exception_handling/RaiseException/test1/paltest_raiseexception_test1 -exception_handling/RaiseException/test2/paltest_raiseexception_test2 -exception_handling/RaiseException/test3/paltest_raiseexception_test3 exception_handling/SetUnhandledExceptionFilter/test1/paltest_setunhandledexceptionfilter_test1 filemapping_memmgt/CreateFileMappingA/test5/paltest_createfilemappinga_test5 filemapping_memmgt/CreateFileMappingA/test6/paltest_createfilemappinga_test6 diff --git a/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c b/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c index b0fcdcee89..cce842ae52 100644 --- a/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c +++ b/src/pal/tests/palsuite/threading/SleepEx/test2/test2.c @@ -57,7 +57,7 @@ int __cdecl main( int argc, char **argv ) for (i=0;i<Iterations;i++) { RunTest(TRUE); - dwAvgDelta += abs(ThreadSleepDelta - InterruptTime); + dwAvgDelta += ThreadSleepDelta - InterruptTime; } dwAvgDelta /= Iterations; @@ -76,7 +76,7 @@ int __cdecl main( int argc, char **argv ) for (i=0;i<Iterations;i++) { RunTest(FALSE); - dwAvgDelta += abs(ThreadSleepDelta - ChildThreadSleepTime); + dwAvgDelta += ThreadSleepDelta - ChildThreadSleepTime; } dwAvgDelta /= Iterations; diff --git a/src/pal/tests/palsuite/threading/SuspendThread/test4/test4.c b/src/pal/tests/palsuite/threading/SuspendThread/test4/test4.c index 4b3c5b7d99..ca8a4c63e8 100644 --- a/src/pal/tests/palsuite/threading/SuspendThread/test4/test4.c +++ b/src/pal/tests/palsuite/threading/SuspendThread/test4/test4.c @@ -19,6 +19,9 @@ #include <palsuite.h> +// Declare sched_yield(), as we cannot include <sched.h> here. +int sched_yield(void); + #define NUM_MALLOCS 256 #define MAX_THREADS 64 int numThreads, numIterations, targetThreadsSelectionAlgo, targetThreadsPos; diff --git a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c index 1f8534246b..ee40fed95c 100644 --- a/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c +++ b/src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c @@ -57,8 +57,8 @@ int __cdecl main( int argc, char **argv ) // Make sure that the wait returns in time greater than interrupt and less than // wait timeout if ( - ((ThreadWaitDelta >= ChildThreadWaitTime) && ( abs( ThreadWaitDelta - ChildThreadWaitTime) > TOLERANCE )) - || (( ThreadWaitDelta < InterruptTime) && ( abs( ThreadWaitDelta - InterruptTime) > TOLERANCE ) ) + ((ThreadWaitDelta >= ChildThreadWaitTime) && (ThreadWaitDelta - ChildThreadWaitTime) > TOLERANCE) + || (( ThreadWaitDelta < InterruptTime) && (ThreadWaitDelta - InterruptTime) > TOLERANCE) ) { Fail("Expected thread to wait for %d ms (and get interrupted).\n" @@ -75,7 +75,7 @@ int __cdecl main( int argc, char **argv ) // Make sure that time taken for thread to return from wait is more than interrupt // and also not less than the complete child thread wait time - delta = abs( ThreadWaitDelta - ChildThreadWaitTime); + delta = ThreadWaitDelta - ChildThreadWaitTime; if( (ThreadWaitDelta < ChildThreadWaitTime) && ( delta > TOLERANCE) ) { Fail("Expected thread to wait for %d ms (and not get interrupted).\n" diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c index 35ecb1ee5f..deacabf1be 100644 --- a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c @@ -75,7 +75,7 @@ int __cdecl main( int argc, char **argv ) */ RunTest(TRUE); - if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and get interrupted).\n" "Thread waited for %d ms! (Acceptable delta: %d)\n", @@ -88,7 +88,7 @@ int __cdecl main( int argc, char **argv ) * it, if it is not in an alertable state. */ RunTest(FALSE); - if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and not be interrupted).\n" "Thread waited for %d ms! (Acceptable delta: %d)\n", diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c index ad8697c52c..a788e72e6f 100644 --- a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c @@ -50,7 +50,7 @@ int __cdecl main( int argc, char **argv ) */ RunTest(TRUE); - if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and get interrupted).\n" "Thread waited for %d ms! (Acceptable delta: %d)\n", @@ -63,7 +63,7 @@ int __cdecl main( int argc, char **argv ) * it, if it is not in an alertable state. */ RunTest(FALSE); - if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and not be interrupted).\n" "Thread waited for %d ms! (Acceptable delta: %d)\n", diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c index b7b035819a..63e2fc3723 100644 --- a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c @@ -51,7 +51,7 @@ int __cdecl main( int argc, char **argv ) */ RunTest(TRUE); - if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + if ((ThreadWaitDelta - InterruptTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and get interrupted).\n" "Thread waited for %d ms! (Acceptable delta: %d)\n", @@ -64,7 +64,7 @@ int __cdecl main( int argc, char **argv ) * it, if it is not in an alertable state. */ RunTest(FALSE); - if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + if ((ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and not be interrupted).\n" "Thread waited for %d ms! (Acceptable delta: %d)\n", diff --git a/src/vm/amd64/unixasmhelpers.S b/src/vm/amd64/unixasmhelpers.S index 873db7ad1e..17846947fa 100644 --- a/src/vm/amd64/unixasmhelpers.S +++ b/src/vm/amd64/unixasmhelpers.S @@ -101,7 +101,7 @@ NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler // Make sure to preserve r11 as well as it is used to pass the stack argument size from JIT // PUSH_ARGUMENT_REGISTERS - push r11 + push_register r11 // // Allocate space for XMM parameter registers @@ -123,12 +123,12 @@ NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler // // epilogue, rax contains the native target address // - add rsp, 0x80 + free_stack 0x80 // // Restore integer parameter registers and r11 // - pop r11 + pop_register r11 POP_ARGUMENT_REGISTERS TAILJMP_RAX @@ -153,9 +153,9 @@ LEAF_END moveOWord, _TEXT NESTED_ENTRY JIT_RareDisableHelper, _TEXT, NoHandler // First integer return register - push rax + push_register rax // Second integer return register - push rdx + push_register rdx alloc_stack 0x28 END_PROLOGUE // First float return register @@ -167,9 +167,9 @@ NESTED_ENTRY JIT_RareDisableHelper, _TEXT, NoHandler movdqa xmm0, [rsp] movdqa xmm1, [rsp+0x10] - add rsp, 0x28 - pop rdx - pop rax + free_stack 0x28 + pop_register rdx + pop_register rax ret NESTED_END JIT_RareDisableHelper, _TEXT diff --git a/src/vm/amd64/unixasmmacros.inc b/src/vm/amd64/unixasmmacros.inc index 8fb0ff201b..aaf4390c47 100644 --- a/src/vm/amd64/unixasmmacros.inc +++ b/src/vm/amd64/unixasmmacros.inc @@ -173,11 +173,15 @@ C_FUNC(\Name\()_End): .endm -.macro push_argument_register Reg +.macro push_register Reg push \Reg .cfi_adjust_cfa_offset 8 .endm +.macro push_argument_register Reg + push_register \Reg +.endm + .macro PUSH_ARGUMENT_REGISTERS push_argument_register r9 @@ -189,11 +193,15 @@ C_FUNC(\Name\()_End): .endm -.macro pop_argument_register Reg +.macro pop_register Reg pop \Reg .cfi_adjust_cfa_offset -8 .endm +.macro pop_argument_register Reg + pop_register \Reg +.endm + .macro POP_ARGUMENT_REGISTERS pop_argument_register rdi diff --git a/src/vm/object.h b/src/vm/object.h index 009e505cea..396d1acbb9 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -1107,9 +1107,9 @@ class StringObject : public Object static SIZE_T GetSize(DWORD stringLength); DWORD GetStringLength() { LIMITED_METHOD_DAC_CONTRACT; return( m_StringLength );} - WCHAR* GetBuffer() { LIMITED_METHOD_CONTRACT; _ASSERTE(this); return (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_Characters) ); } - WCHAR* GetBuffer(DWORD *pdwSize) { LIMITED_METHOD_CONTRACT; _ASSERTE(this && pdwSize); *pdwSize = GetStringLength(); return GetBuffer(); } - WCHAR* GetBufferNullable() { LIMITED_METHOD_CONTRACT; return( (this == 0) ? 0 : (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_Characters) ) ); } + WCHAR* GetBuffer() { LIMITED_METHOD_CONTRACT; _ASSERTE(this != nullptr); return (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_Characters) ); } + WCHAR* GetBuffer(DWORD *pdwSize) { LIMITED_METHOD_CONTRACT; _ASSERTE((this != nullptr) && pdwSize); *pdwSize = GetStringLength(); return GetBuffer(); } + WCHAR* GetBufferNullable() { LIMITED_METHOD_CONTRACT; return( (this == nullptr) ? nullptr : (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_Characters) ) ); } DWORD GetHighCharState() { WRAPPER_NO_CONTRACT; diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 0d21e1579a..3fc78f1e8a 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -3577,7 +3577,7 @@ Thread::~Thread() #endif #ifdef _DEBUG - if (m_pFiberInfo) { + if (m_pFiberInfo != NULL) { delete [] (DWORD_PTR*)m_pFiberInfo[0]; } #endif |