summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike McLaughlin <mikem@microsoft.com>2015-02-23 10:09:14 -0800
committerMike McLaughlin <mikem@microsoft.com>2015-02-23 10:09:14 -0800
commitbfb8bffa32b422b538a3359af84305d47a912d6c (patch)
treeb0728d94a9ffd995ac00ed2670e370671bae23f1 /src
parent639ac0872d1491d6f7b88bddbd84b3fb36bdc62a (diff)
parent63976a08fbe6ece34a2936ebccdf735ea32044a2 (diff)
downloadcoreclr-bfb8bffa32b422b538a3359af84305d47a912d6c.tar.gz
coreclr-bfb8bffa32b422b538a3359af84305d47a912d6c.tar.bz2
coreclr-bfb8bffa32b422b538a3359af84305d47a912d6c.zip
Merge remote-tracking branch 'upstream/master' into soscommand1
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt19
-rw-r--r--src/inc/debugreturn.h16
-rw-r--r--src/inc/staticcontract.h16
-rw-r--r--src/pal/inc/pal.h260
-rw-r--r--src/pal/inc/pal_assert.h12
-rw-r--r--src/pal/src/CMakeLists.txt1
-rw-r--r--src/pal/src/arch/i386/context.cpp8
-rw-r--r--src/pal/src/arch/i386/context2.S (renamed from src/pal/src/arch/i386/context2.s)10
-rw-r--r--src/pal/src/arch/i386/runfilter.s158
-rw-r--r--src/pal/src/arch/i386/tryexcept.s207
-rw-r--r--src/pal/src/config.h.in1
-rw-r--r--src/pal/src/configure.cmake9
-rw-r--r--src/pal/src/exception/seh-unwind.cpp889
-rw-r--r--src/pal/src/init/pal.cpp6
-rw-r--r--src/pal/tests/palsuite/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/common/palsuite.h5
-rw-r--r--src/pal/tests/palsuite/exception_handling/CMakeLists.txt18
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp (renamed from src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.c)13
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp (renamed from src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.c)25
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt2
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp (renamed from src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.c)13
-rw-r--r--src/pal/tests/palsuite/miscellaneous/queryperformancecounter/test1/test1.c2
-rw-r--r--src/pal/tests/palsuite/paltestlist.txt3
-rw-r--r--src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt3
-rw-r--r--src/pal/tests/palsuite/threading/SleepEx/test2/test2.c4
-rw-r--r--src/pal/tests/palsuite/threading/SuspendThread/test4/test4.c3
-rw-r--r--src/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.c6
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c4
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c4
-rw-r--r--src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c4
-rw-r--r--src/vm/amd64/unixasmhelpers.S16
-rw-r--r--src/vm/amd64/unixasmmacros.inc12
-rw-r--r--src/vm/object.h6
-rw-r--r--src/vm/threads.cpp2
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