summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/exception_handling
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /src/pal/tests/palsuite/exception_handling
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/pal/tests/palsuite/exception_handling')
-rw-r--r--src/pal/tests/palsuite/exception_handling/CMakeLists.txt13
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c118
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c154
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c206
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c197
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c142
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c208
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat18
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt5
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c82
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c68
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c133
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c123
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c130
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat16
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c77
-rw-r--r--src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat17
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp130
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat13
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp224
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat28
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp115
-rw-r--r--src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat14
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c82
-rw-r--r--src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat15
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt10
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c67
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat23
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c111
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat25
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c120
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat27
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c105
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat27
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c112
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat27
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c160
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat25
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c67
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat24
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c302
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat19
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt4
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt97
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp75
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src3
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp75
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src3
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp117
-rw-r--r--src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat13
90 files changed, 4605 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/exception_handling/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/CMakeLists.txt
new file mode 100644
index 0000000000..d0de335427
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(pal_sxs)
+#add_subdirectory(pal_except)
+#add_subdirectory(PAL_EXCEPT_FILTER)
+#add_subdirectory(PAL_EXCEPT_FILTER_EX)
+#add_subdirectory(pal_finally)
+#add_subdirectory(PAL_TRY_EXCEPT)
+#add_subdirectory(PAL_TRY_EXCEPT_EX)
+#add_subdirectory(PAL_TRY_LEAVE_FINALLY)
+add_subdirectory(RaiseException)
+#add_subdirectory(SetUnhandledExceptionFilter)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt
new file mode 100644
index 0000000000..adbc8ae86a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_EXCEPT_FILTER.c
+)
+
+add_executable(paltest_pal_except_filter_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c
new file mode 100644
index 0000000000..ee65f43d2c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/PAL_EXCEPT_FILTER.c
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+** exception is forced and a known value is passed to the filter
+** fuction. The known value as well as booleans are tested to
+** ensure proper functioning.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+const int nValidator = 12321;
+
+LONG ExitFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+ /* was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Parameter passed to filter function"
+ " should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* pointer to NULL */
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT_FILTER(ExitFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the filter"
+ " function was not executed.\n");
+ }
+
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat
new file mode 100644
index 0000000000..b0b90d3ab4
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER
+Name = Test for PAL_EXCEPT_FILTER
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+= exception is forced and a known value is passed to the filter
+= fuction. The known value as well as booleans are tested to
+= ensure proper functioning.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt
new file mode 100644
index 0000000000..62cda706d5
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter.c
+)
+
+add_executable(paltest_pal_except_filter_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c
new file mode 100644
index 0000000000..ccf53fb0ba
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/pal_except_filter.c
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+** exception is forced and the filter returns
+** EXCEPTION_CONTINUE_EXECUTION to allow execution to continue.
+**
+**
+**===================================================================*/
+
+
+#include <palsuite.h>
+
+char* p; /* pointer to be abused */
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ExitFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+ void *Temp;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+ /* was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Parameter passed to filter function"
+ " should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+
+ /* Are we dealing with the exception we expected? */
+ if (EXCEPTION_ACCESS_VIOLATION != ep->ExceptionRecord->ExceptionCode)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Unexpected Exception"
+ " should have been \"%x\" but was \"%x\".\n",
+ EXCEPTION_ACCESS_VIOLATION,
+ ep->ExceptionRecord->ExceptionCode);
+ }
+
+ /* attempt to correct the problem by commiting the page at address 'p' */
+ Temp= VirtualAlloc(p, 1, MEM_COMMIT, PAGE_READWRITE);
+ if (!Temp)
+ {
+ Fail("EXCEPTION_CONTINUE_EXECUTION: last error = %u - probably "
+ "out of memory. Unable to continue, not proof of exception "
+ "failure\n",
+ GetLastError());
+ }
+ /* The memory that 'p' points to is now valid */
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* reserve an address chunk for p to point to */
+ p = (char*) VirtualAlloc(0, 1, MEM_RESERVE, PAGE_READONLY);
+ if (!p)
+ {
+ Fail("EXCEPTION_CONTINUE_EXECUTION: test setup via "
+ "VirtualAlloc failed.\n");
+ }
+
+ *p = 13; /* causes an access violation exception */
+
+ bTry2 = TRUE;
+
+
+ }
+ PAL_EXCEPT_FILTER(ExitFilter, (LPVOID)&nValidator)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER block */
+ Fail("PAL_EXCEPT_FILTER: ERROR -> in handler despite filter's "
+ "continue choice\n");
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER block was executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the filter"
+ " function was not executed.\n");
+ }
+
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY"
+ " block after the exception causing statements was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat
new file mode 100644
index 0000000000..729d2a4c49
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER
+Name = Test for PAL_EXCEPT_FILTER
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER. An
+= exception is forced and the filter returns
+= EXCEPTION_CONTINUE_EXECUTION to allow execution to continue.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt
new file mode 100644
index 0000000000..cc68fb031c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter.c
+)
+
+add_executable(paltest_pal_except_filter_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c
new file mode 100644
index 0000000000..20c36840b1
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/pal_except_filter.c
@@ -0,0 +1,206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER in the
+** presence of a call stack. An
+** exception is forced and passed to two nested exception filters for
+** consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+** so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+** initial exception handler should be skipped, and the second
+** executed
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+BOOL bFilterCS = FALSE;
+BOOL bFilterEE = FALSE;
+BOOL bTry1 = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bExcept1 = FALSE;
+BOOL bExcept2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+
+ /* let the main know we've hit the filter function */
+ bFilterCS = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit after the ExecuteException "
+ "filter.\n");
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilterEE = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ExecExeption filter was hit before the ContSearch "
+ "filter.\n");
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void NestedFunc1 (void)
+{
+ int* p = 0x00000000; /* pointer to NULL */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The dummy handler was "
+ "being hit.\n");
+ bExcept2 = TRUE; /* indicate we hit the inner block */
+ }
+ PAL_ENDTRY;
+
+}
+
+void NestedFunc2 (void)
+{
+ NestedFunc1();
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block only based
+ ** on the return codes of the filters
+ */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */
+
+ NestedFunc2();
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the inner filter "
+ "being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the outer filter "
+ "being hit.\n");
+ }
+ bExcept1 = TRUE; /* indicate we hit the outer block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "inner PAL_EXCEPT_FILTER block was executed.\n");
+ }
+ if (!bExcept1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "outer PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "search continuing filter"
+ " function was not executed.\n");
+ }
+ if (!bFilterEE)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "execute handler filter"
+ " function was not executed.\n");
+ }
+
+
+ /* did we hit all the code blocks? */
+ if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS )
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat
new file mode 100644
index 0000000000..d2df399392
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER/test3/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for nested PAL_EXCEPT_FILTER functions & EXCEPTION_CONTINUE_SEARCH
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER with nested
+= functions to build a call stack. An
+= exception is forced and passed to two nested exception filters for
+= consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+= so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+= initial exception handler should be skipped, and the second
+= executed
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt
new file mode 100644
index 0000000000..21c3b5d33c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_EXCEPT_FILTER_EX.c
+)
+
+add_executable(paltest_pal_except_filter_ex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_ex_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_ex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c
new file mode 100644
index 0000000000..91f392d8d7
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/PAL_EXCEPT_FILTER_EX.c
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_EXCEPT_FILTER_EX.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+** There are two try blocks in this test. The first forces an
+** exception error to force hitting the first filter. The second
+** doesn't to make sure we don't hit the filter. A value is also
+** passed into the filter program and it is validated to make sure
+** it was passed correctly.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+const int nValidator = 12321;
+
+
+/**
+**
+** Filter function for the first try block
+**
+**/
+
+LONG Filter_01(EXCEPTION_POINTERS* ep, VOID *pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+ /* was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Parameter passed to filter"
+ " function should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+/**
+**
+** Filter function for the second try block. We shouldn't
+** hit this function.
+**
+**/
+
+LONG Filter_02(EXCEPTION_POINTERS* ep, VOID *pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The first PAL_EXCEPT_FILTER_EX was hit before PAL_TRY.\n");
+ }
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER_EX was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "first PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "first PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the first"
+ " filter function was not executed.\n");
+ }
+
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+ bTry = bExcept = bFilter = FALSE;
+
+
+ /*
+ ** test to make sure we skip the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " Second PAL_EXCEPT_FILTER_EX was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT_FILTER(Filter_02, (LPVOID)&nValidator)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER_EX was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "second PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the "
+ "second PAL_EXCEPT_FILTER_EX block was executed even though an"
+ " exception was not triggered.\n");
+ }
+
+ if (bFilter)
+ {
+ Trace("PAL_EXCEPT_FILTER_EX: ERROR -> It appears the code in the second"
+ " filter function was executed even though an exception was"
+ " not triggered.\n");
+ }
+
+
+ /* did we hit all the correct code blocks? */
+ if(!bTry || bExcept || bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat
new file mode 100644
index 0000000000..1d8f8f600e
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test1/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for PAL_EXCEPT_FILTER_EX
+Type = DEFAULT
+EXE1 = pal_except_filter_ex
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+= There are two try blocks in this test. The first forces an
+= exception error to force hitting the first filter. The second
+= doesn't to make sure we don't hit the filter. A value is also
+= passed into the filter program and it is validated to make sure
+= it was passed correctly.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt
new file mode 100644
index 0000000000..350acff036
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter_ex.c
+)
+
+add_executable(paltest_pal_except_filter_ex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_ex_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_ex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c
new file mode 100644
index 0000000000..ab25c49733
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/pal_except_filter_ex.c
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_EXCEPT_FILTER_EX.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+** There is a nested try blocks in this test. The nested
+** PAL_TRY creates an exception and the FILTER creates another.
+** This test makes sure that this case does not end in a
+** infinite loop.
+**
+**
+**===================================================================*/
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+BOOL bTry2 = FALSE;
+const int nValidator = 12321;
+
+/* Filter function for the first try block.
+ */
+LONG Filter_01(EXCEPTION_POINTERS* ep, VOID *pnTestInt)
+{
+ int nTestInt = *(int *)pnTestInt;
+
+ /* Signal main() that filter has been executed. */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("ERROR: The filter was executed without "
+ "entering the first PAL_TRY.\n");
+ }
+
+ if (!bTry2)
+ {
+ Fail("ERROR: The filter was executed without "
+ "entering the second PAL_TRY.\n");
+ }
+
+ /* Was the correct value passed? */
+ if (nValidator != nTestInt)
+ {
+ Fail("ERROR: Parameter passed to filter function "
+ "should have been \"%d\" but was \"%d\".\n",
+ nValidator,
+ nTestInt);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000;
+ BOOL bExcept = FALSE;
+ BOOL bExcept2 = FALSE;
+
+ /* Initalize the PAL.
+ */
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* Test a nested PAL_Try block.
+ */
+ PAL_TRY
+ {
+ /* Signal entry into first PAL_TRY block.*/
+ bTry = TRUE;
+
+ PAL_TRY
+ {
+ /* Signal entry into second PAL_TRY block.*/
+ bTry2 = TRUE;
+ /* Cause an exception.*/
+ *p = 13;
+ }
+ PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator)
+ {
+ /* Signal entry into second PAL_EXCEPT filter.*/
+ bExcept = TRUE;
+ /* Cause another exception.*/
+ *p = 13;
+ }
+ PAL_ENDTRY
+
+ }
+ PAL_EXCEPT_FILTER(Filter_01, (LPVOID)&nValidator)
+ {
+ /* Signal entry into second PAL_EXCEPT filter.*/
+ bExcept2 = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: The code in the first "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bTry2)
+ {
+ Trace("ERROR: The code in the nested "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: The code in the first "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bExcept2)
+ {
+ Trace("ERROR: The code in the second "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("ERROR: The code in the first "
+ "filter function was not executed.\n");
+ }
+
+ if(!bTry || !bTry2 || !bExcept || !bExcept2 || !bFilter )
+ {
+ Fail("");
+ }
+
+ /* Terminate the PAL.
+ */
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat
new file mode 100644
index 0000000000..0343d133e8
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test2/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for PAL_EXCEPT_FILTER_EX
+Type = DEFAULT
+EXE1 = pal_except_filter_ex
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX.
+= There is a nested try blocks in this test. The nested
+= PAL_TRY creates an exception and the FILTER creates another.
+= This test makes sure that this case does not end in a
+= infinite loop.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt
new file mode 100644
index 0000000000..7f485c8ca4
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_except_filter.c
+)
+
+add_executable(paltest_pal_except_filter_ex_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_filter_ex_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_except_filter_ex_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c
new file mode 100644
index 0000000000..a17cb4f6b3
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/pal_except_filter.c
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_except_filter_ex.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. An
+** exception is forced and passed to two nested exception filters for
+** consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+** so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+** initial exception handler should be skipped, and the second
+** executed
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+BOOL bFilterCS = FALSE;
+BOOL bFilterEE = FALSE;
+BOOL bTry1 = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+
+ /* let the main know we've hit the filter function */
+ bFilterCS = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit after the ExecuteException "
+ "filter.\n");
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilterEE = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ExecExeption filter was hit before the ContSearch "
+ "filter.\n");
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* pointer to NULL */
+ BOOL bExcept1 = FALSE;
+ BOOL bExcept2 = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block only based
+ ** on the return codes of the filters
+ */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */
+
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+
+ PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The dummy handler was "
+ "being hit.\n");
+ }
+ PAL_ENDTRY;
+
+ bExcept2 = TRUE; /* indicate we hit the inner block */
+ }
+ PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without PAL_TRY's code "
+ "being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on. "
+ "PAL_EXCEPT_FILTER's handler was hit without "
+ "the inner filter being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on. "
+ "PAL_EXCEPT_FILTER's handler was hit without "
+ "the outer filter being hit.\n");
+ }
+ bExcept1 = TRUE; /* indicate we hit the outer block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the inner"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "inner PAL_EXCEPT_FILTER block was executed.\n");
+ }
+ if (!bExcept1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "outer PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "search continuing filter"
+ " function was not executed.\n");
+ }
+ if (!bFilterEE)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "execute handler filter"
+ " function was not executed.\n");
+ }
+
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the PAL_TRY "
+ "block after the exception causing statements "
+ "was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS )
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat
new file mode 100644
index 0000000000..568296c399
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_EXCEPT_FILTER_EX/test3/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_EXCEPT_FILTER_EX
+Name = Test for nested PAL_EXCEPT_FILTER_EX & EXCEPTION_CONTINUE_SEARCH
+Type = DEFAULT
+EXE1 = pal_except_filter
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_EXCEPT_FILTER_EX. An
+= exception is forced and passed to two nested exception filters for
+= consideration. The first filter returns EXCEPTION_CONTINUE_SEARCH
+= so the second can run and return EXCEPTION_EXECUTE_HANDLER. The
+= initial exception handler should be skipped, and the second
+= executed
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt
new file mode 100644
index 0000000000..ef14ea5352
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8a1a832361
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT.c
+)
+
+add_executable(paltest_pal_try_except_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c
new file mode 100644
index 0000000000..4fb09bd276
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/PAL_TRY_EXCEPT.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. An exception is forced to ensure
+** the exception block is hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* NULL pointer */
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (bExcept)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> Something weird is going on."
+ " PAL_EXCEPT was hit before PAL_TRY.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> Something weird is going on."
+ " PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat
new file mode 100644
index 0000000000..1f663a8bc5
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT
+Name = Test for PAL_TRY and PAL_EXCEPT
+Type = DEFAULT
+EXE1 = pal_try_except
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In the PAL_TRY block, an access violation is forced to gain
+= access to the PAL_EXCEPT block. Booleans are used to ensure
+= each of the code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt
new file mode 100644
index 0000000000..cdf371926c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT.c
+)
+
+add_executable(paltest_pal_try_except_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c
new file mode 100644
index 0000000000..eb7b9d1257
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/PAL_TRY_EXCEPT.c
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Tests that the EXCEPTION block
+** is missed if no exceptions happen
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** Test to make sure we skip the exception block.
+ */
+
+ PAL_TRY
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was executed even though no exception was supposed to"
+ " happen.\n");
+ }
+
+ /* did we hit the correct code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat
new file mode 100644
index 0000000000..a5815f5722
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT (test 2)
+Name = Test for PAL_TRY and PAL_EXCEPT
+Type = DEFAULT
+EXE1 = pal_try_except
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In this test, no exceptions are forced to ensure the EXCEPTION block
+= isn't hit. Booleans are used to ensure the proper code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt
new file mode 100644
index 0000000000..c30877f65e
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT_EX.c
+)
+
+add_executable(paltest_pal_try_except_ex_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_ex_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_ex_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c
new file mode 100644
index 0000000000..8b4dd7b430
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/PAL_TRY_EXCEPT_EX.c
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 1)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Exceptions are forced to ensure
+** the exception blocks are hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* NULL pointer */
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+ BOOL bTestA = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first try block was hit a second time.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first except block was hit a second time.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first"
+ " PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block
+ */
+
+ bTry = FALSE;
+ bExcept = FALSE;
+ bTestA = FALSE; /* we are now going into the second block test */
+
+
+ PAL_TRY
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second try block was hit too early.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second except block was hit too early.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_TRY block was not executed.");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was not executed.");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat
new file mode 100644
index 0000000000..b571427935
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test1/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT_EX
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+Type = DEFAULT
+EXE1 = pal_try_except_ex
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In the PAL_TRY block, an access violation is forced to gain
+= access to the PAL_EXCEPT block. Booleans are used to ensure
+= each of the code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt
new file mode 100644
index 0000000000..0d4c4db240
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT_EX.c
+)
+
+add_executable(paltest_pal_try_except_ex_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_ex_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_ex_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c
new file mode 100644
index 0000000000..5ab4a95ce9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/PAL_TRY_EXCEPT_EX.c
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 2)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Exceptions are not forced to ensure
+** the proper blocks are hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+ BOOL bTestA = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first try block was hit a second time.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first"
+ " PAL_EXCEPT block was executed even though no exceptions were "
+ "encountered.\n");
+ }
+
+ /* did we hit all the proper code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("");
+ }
+
+
+ /*
+ ** test to make sure we skip the second exception block
+ */
+
+ bTry = FALSE;
+ bExcept = FALSE;
+ bTestA = FALSE; /* we are now going into the second block test */
+
+
+ PAL_TRY
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second try block was hit too early.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second except block was hit too early.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_EXCEPT block was executed even though no exceptions were "
+ "encountered.\n");
+ }
+
+ /* did we hit all the proper code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat
new file mode 100644
index 0000000000..f71964da1c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test2/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT_EX (test 2)
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+Type = DEFAULT
+EXE1 = pal_try_except_ex
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= In this test, no exceptions are forced to ensure the EXCEPTION block
+= isn't hit. Booleans are used to ensure the proper code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt
new file mode 100644
index 0000000000..dc797f2f09
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_EXCEPT_EX.c
+)
+
+add_executable(paltest_pal_try_except_ex_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_except_ex_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_try_except_ex_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c
new file mode 100644
index 0000000000..d6a948926b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/PAL_TRY_EXCEPT_EX.c
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: PAL_TRY_EXCEPT.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Force an exception in only one block
+** to ensure the proper exception block is hit.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ int* p = 0x00000000; /* NULL pointer */
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+ BOOL bTestA = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the exception block
+ */
+
+ PAL_TRY
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first try block was hit a second time.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+ Fail("PAL_TRY_EXCEPT: ERROR -> code was executed after the "
+ "access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR ->"
+ " It appears the first except block was hit a second time.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the first"
+ " PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("\n");
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block
+ */
+
+ bTry = FALSE;
+ bExcept = FALSE;
+ bTestA = FALSE; /* we are now going into the second block test */
+
+
+ PAL_TRY
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second try block was hit too early.\n");
+ }
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (bTestA)
+ {
+ Fail("PAL_TRY_EXCEPT: ERROR -> It appears"
+ " the second except block was hit too early.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the second "
+ " PAL_EXCEPT block was executed for some reason.\n");
+ }
+
+ /* did we hit all the correct code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("\n");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat
new file mode 100644
index 0000000000..a245447088
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_EXCEPT_EX/test3/testinfo.dat
@@ -0,0 +1,16 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_TRY and PAL_EXCEPT_EX (test3)
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+Type = DEFAULT
+EXE1 = pal_try_except_ex
+LANG = cpp
+Description
+= Since these two are so closely connected, they are tested together.
+= Only one of the PAL_TRY blocks will force and exception to ensure the
+= correct PAL_EXCEPT_EX block is hit. Booleans are used to ensure
+= the correct code blocks are hit.
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt
new file mode 100644
index 0000000000..a5fdd26924
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ PAL_TRY_LEAVE_FINALLY.c
+)
+
+add_executable(paltest_pal_try_leave_finally_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_try_leave_finally_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_try_leave_finally_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c
new file mode 100644
index 0000000000..675c2a5947
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/PAL_TRY_LEAVE_FINALLY.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_try_leave_finally.c
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY, PAL_LEAVE
+** and PAL_FINALLY functions.
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bFinally = FALSE;
+ BOOL bLeave = TRUE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ PAL_TRY
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ goto Done;
+
+ bLeave = FALSE; /* indicate we stuck around */
+ Done: ;
+ }
+ PAL_FINALLY
+ {
+ bFinally = TRUE; /* indicate we hit the PAL_FINALLY block */
+ }
+ PAL_ENDTRY;
+
+ /* did we go where we were meant to go */
+ if (!bTry)
+ {
+ Trace("PAL_TRY_FINALLY: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (!bLeave)
+ {
+ Trace("PAL_TRY_FINALLY: ERROR -> It appears code was executed after "
+ "PAL_LEAVE was called. It should have jumped directly to the "
+ "PAL_FINALLY block.\n");
+ }
+
+ if (!bFinally)
+ {
+ Trace("PAL_TRY_FINALLY: ERROR -> It appears the code in the PAL_FINALLY"
+ " block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bLeave || !bFinally)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat
new file mode 100644
index 0000000000..8a90ef392c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/PAL_TRY_LEAVE_FINALLY/test1/testinfo.dat
@@ -0,0 +1,17 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = file_io
+Function = PAL_TRY, PAL_LEAVE and PAL_FINALLY
+Name = Test for PAL_TRY, PAL_LEAVE and PAL_EXCEPT
+Type = DEFAULT
+EXE1 = pal_try_leave_finally
+LANG = cpp
+Description
+= Since these three are so closely connected, they are tested together.
+= The PAL_TRY block contains a PAL_LEAVE which kicks execution to
+= the PAL_FINALLY block. Booleans are used to ensure each of the
+= code blocks are properly hit.
+
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt
new file mode 100644
index 0000000000..1962ade358
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt
new file mode 100644
index 0000000000..2fba7dd9b3
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.cpp
+)
+
+add_executable(paltest_raiseexception_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_raiseexception_test1 coreclrpal)
+
+target_link_libraries(paltest_raiseexception_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp
new file mode 100644
index 0000000000..9130bc362d
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/test1.cpp
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Tests that RaiseException throws a catchable exception
+** and Tests the behaviour of RaiseException with
+** PAL_FINALLY
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+BOOL bExcept = FALSE;
+BOOL bTry = FALSE;
+BOOL bFinally = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /*********************************************************
+ * Tests that RaiseException throws a catchable exception
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE;
+ RaiseException(0,0,0,0);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+ /* Reinit flags */
+ bTry = bExcept = FALSE;
+
+
+ /*********************************************************
+ * Tests the behaviour of RaiseException with
+ * PAL_FINALLY
+ * (bFinally should be set before bExcept)
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE;
+ RaiseException(0,0,0,0);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_FINALLY
+ {
+ bFinally = TRUE;
+ }
+ PAL_ENDTRY;
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if( bFinally == FALSE )
+ {
+ Fail("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT executed before the code in PAL_FINALLY.\n");
+ }
+
+ bExcept = TRUE;
+ }
+
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bFinally)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_FINALLY block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFinally)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat
new file mode 100644
index 0000000000..890b5efec7
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = RaiseException
+Name = RaiseException test #1
+TYPE = DEFAULT
+EXE1 = test1
+LANG = cpp
+Description
+=Tests that RaiseException throws a catchable exception
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt
new file mode 100644
index 0000000000..7fc9f5f12c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.cpp
+)
+
+add_executable(paltest_raiseexception_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_raiseexception_test2 coreclrpal)
+
+target_link_libraries(paltest_raiseexception_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp
new file mode 100644
index 0000000000..f8db573ac0
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/test2.cpp
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c (exception_handling\raiseexception\test2)
+**
+** Purpose: Tests that the correct arguments are passed
+** to the filter by RaiseException and tests that
+** the number of arguments never exceeds
+** EXCEPTION_MAXIMUM_PARAMETERS, even though we
+** pass a greater number of arguments
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+BOOL bFilter;
+BOOL bTry;
+BOOL bExcept;
+
+ULONG_PTR lpArguments_test1[EXCEPTION_MAXIMUM_PARAMETERS];
+DWORD nArguments_test1 = EXCEPTION_MAXIMUM_PARAMETERS;
+
+ULONG_PTR lpArguments_test2[EXCEPTION_MAXIMUM_PARAMETERS+1];
+DWORD nArguments_test2 = EXCEPTION_MAXIMUM_PARAMETERS+1;
+
+
+/**
+**
+** Filter function that checks for the parameters
+**
+**/
+LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID *unused)
+{
+ int i;
+
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+
+ /* was the correct number of arguments passed */
+ if (ep->ExceptionRecord->NumberParameters != (DWORD) nArguments_test1)
+ {
+ Fail("RaiseException: ERROR -> Number of arguments passed to filter"
+ " was %d when it should have been %d",
+ ep->ExceptionRecord->NumberParameters,
+ nArguments_test1);
+
+ }
+
+ /* were the correct arguments passed */
+ for( i=0; ((DWORD)i)<nArguments_test1; i++ )
+ {
+ if( ep->ExceptionRecord->ExceptionInformation[i]
+ != lpArguments_test1[i])
+ {
+ Fail("RaiseException: ERROR -> Argument %d passed to filter"
+ " was %d when it should have been %d",
+ i,
+ ep->ExceptionRecord->ExceptionInformation[i],
+ lpArguments_test1[i]);
+ }
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+/**
+**
+** Filter function that checks for the maximum parameters
+**
+**/
+LONG Filter_test2(EXCEPTION_POINTERS* ep, VOID* unused)
+{
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (ep->ExceptionRecord->NumberParameters > EXCEPTION_MAXIMUM_PARAMETERS)
+ {
+ Fail("RaiseException: ERROR -> Number of arguments passed to filter"
+ " was %d which is greater than the maximum allowed of %d\n",
+ ep->ExceptionRecord->NumberParameters,
+ EXCEPTION_MAXIMUM_PARAMETERS);
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /********************************************************
+ * Test that the correct arguments are passed
+ * to the filter by RaiseException
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* Initialize arguments to pass to filter */
+ for(int i = 0; ((DWORD)i) < nArguments_test1; i++ )
+ {
+ lpArguments_test1[i] = i;
+ }
+
+ RaiseException(0,0,nArguments_test1,lpArguments_test1);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_test1)
+ {
+ if (!bTry)
+ {
+ Fail("RaiseException: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the"
+ " filter function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ /* Reinit flags */
+ bTry = bExcept = bFilter = FALSE;
+
+ /********************************************************
+ * Test that the number of arguments never
+ * exceeds EXCEPTION_MAXIMUM_PARAMETERS, even though we
+ * pass a greater number of arguments
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* Initialize arguments to pass to filter */
+ for(int i = 0; ((DWORD)i) < nArguments_test2; i++ )
+ {
+ lpArguments_test2[i] = i;
+ }
+
+ RaiseException(0,0,nArguments_test2,lpArguments_test2);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_test2)
+ {
+ if (!bTry)
+ {
+ Fail("RaiseException: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the"
+ " filter function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat
new file mode 100644
index 0000000000..ce85e67ace
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test2/testinfo.dat
@@ -0,0 +1,28 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = RaiseException
+
+Name = RaiseException test #2
+
+TYPE = DEFAULT
+
+EXE1 = test2
+LANG = cpp
+
+Description
+
+=Tests that the correct arguments are passed
+
+=to the filter by RaiseException and tests that
+
+=the number of arguments never exceeds
+
+=EXCEPTION_MAXIMUM_PARAMETERS, even though we
+
+=pass a greater number of arguments
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt
new file mode 100644
index 0000000000..72e5427b69
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test.cpp
+)
+
+add_executable(paltest_raiseexception_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_raiseexception_test3 coreclrpal)
+
+target_link_libraries(paltest_raiseexception_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp
new file mode 100644
index 0000000000..5278ad1772
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/test.cpp
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test.c (exception_handling\raiseexception\test3)
+**
+** Purpose: Tests that the correct ExceptionCode is passed
+** to the filter by RaiseException
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+BOOL bFilter = FALSE;
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+/**
+**
+** Filter function that checks for the parameters
+**
+**/
+LONG Filter_test1(EXCEPTION_POINTERS* ep, VOID* unused)
+{
+ /* let the main know we've hit the filter function */
+ bFilter = TRUE;
+
+ if (!bTry)
+ {
+ Fail("PAL_EXCEPT_FILTER_EX: ERROR -> Something weird is going on."
+ " The filter was hit without PAL_TRY being hit.\n");
+ }
+
+
+ /* was the correct exception code passed? */
+ if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
+ {
+ Fail("RaiseException: ERROR -> ep->ExceptionRecord->ExceptionCode"
+ " was %x when it was expected to be %x\n",
+ ep->ExceptionRecord->ExceptionCode,
+ EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
+
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /********************************************************
+ * Test that the correct arguments are passed
+ * to the filter by RaiseException
+ */
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED,
+ 0,
+ 0,NULL);
+
+ Fail("RaiseException: ERROR -> code was executed after the "
+ "exception was raised.\n");
+ }
+ PAL_EXCEPT_FILTER(Filter_test1)
+ {
+ if (!bTry)
+ {
+ Fail("RaiseException: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit without PAL_TRY being hit.\n");
+ }
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT_FILTER_EX block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the "
+ "PAL_EXCEPT_FILTER_EX block was not executed.\n");
+ }
+
+ if (!bFilter)
+ {
+ Trace("RaiseException: ERROR -> It appears the code in the"
+ " filter function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept || !bFilter)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat
new file mode 100644
index 0000000000..12a56f0efe
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/RaiseException/test3/testinfo.dat
@@ -0,0 +1,14 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = RaiseException
+Name = RaiseException test #3
+TYPE = DEFAULT
+EXE1 = test
+LANG = cpp
+Description
+= Tests that the exception code passed to
+= RaiseException makes it to the filter.
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt
new file mode 100644
index 0000000000..e526029bee
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_setunhandledexceptionfilter_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_setunhandledexceptionfilter_test1 coreclrpal)
+
+target_link_libraries(paltest_setunhandledexceptionfilter_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c
new file mode 100644
index 0000000000..5a067f9354
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/test1.c
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test1.c
+**
+** Purpose: Sets up a new unhandled exception filter, and makes sure it
+** returns the previous filter. Raises an unhandled exception and
+** makes sure this reaches the filter.
+**
+**
+**============================================================*/
+
+
+#include <palsuite.h>
+
+/* This isn't defined in the pal, so copied from win32 */
+#define EXCEPTION_EXECUTE_HANDLER 1
+#define EXCEPTION_CONTINUE_EXECUTION -1
+
+
+int InFilter = FALSE;
+
+LONG PALAPI FirstFilter(LPEXCEPTION_POINTERS p)
+{
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+LONG PALAPI ContinueFilter(LPEXCEPTION_POINTERS p)
+{
+ InFilter = TRUE;
+
+ Trace("This test has succeeded as far at the automated checks can "
+ "tell. Manual verification is now required to be completely sure.\n");
+ Trace("Now the PAL's handling of application errors will be tested "
+ "with an exception code of %u.\n",
+ p->ExceptionRecord->ExceptionCode);
+ Trace("Please verify that the actions that the PAL now takes are "
+ "as specified for it.\n");
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ LPTOP_LEVEL_EXCEPTION_FILTER OldFilter;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+
+ SetUnhandledExceptionFilter(FirstFilter);
+
+ OldFilter = SetUnhandledExceptionFilter(ContinueFilter);
+ if (OldFilter != FirstFilter)
+ {
+ Fail("SetUnhandledExceptionFilter did not return a pointer to the "
+ "previous filter!\n");
+ }
+
+ /*
+ * Raise an unhandled exception. This should cause our filter to be
+ * excecuted and the program to exit with a code the same as the
+ * exception code.
+ */
+ RaiseException(3,0,0,0);
+
+
+ /*
+ * This code should not be executed because the toplevelhandler is
+ * expected to "just" set the exit code and abend the program
+ */
+ Fail("An unhandled exception did not cause the program to abend with"
+ "the exit code == the ExceptionCode!\n");
+
+ PAL_Terminate();
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat
new file mode 100644
index 0000000000..2af29a299a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/SetUnhandledExceptionFilter/test1/testinfo.dat
@@ -0,0 +1,15 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = SetUnhandledExceptionFilter
+Name = SetUnhandledExceptionFilter test #1
+TYPE = DEFAULT
+EXE1 = test1
+LANG = cpp
+Description
+=Sets up a new unhandled exception filter, and makes sure it
+=returns the previous filter. Raises an unhandled exception and
+=makes sure this reaches the filter.
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt
new file mode 100644
index 0000000000..19ee487a6a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+add_subdirectory(test2)
+add_subdirectory(test3)
+add_subdirectory(test4)
+add_subdirectory(test5)
+add_subdirectory(test6)
+add_subdirectory(test7)
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt
new file mode 100644
index 0000000000..635e35d635
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test1.c
+)
+
+add_executable(paltest_pal_except_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c b/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c
new file mode 100644
index 0000000000..0fe48e7fc3
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/test1.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test1.c (exception_handling\pal_except\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat
new file mode 100644
index 0000000000..246553a9cb
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test1/testinfo.dat
@@ -0,0 +1,23 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test1
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt
new file mode 100644
index 0000000000..813b0e66a1
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test2.c
+)
+
+add_executable(paltest_pal_except_test2
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test2 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test2
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c b/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c
new file mode 100644
index 0000000000..bc0d4e300a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/test2.c
@@ -0,0 +1,111 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test2.c (exception_handling\pal_except\test2)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** that contains another PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+
+ /* Nested PAL_TRY */
+ PAL_TRY
+ {
+ bTry_nested = TRUE;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: Nested PAL_EXCEPT was hit without "
+ "nested PAL_TRY being hit.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without "
+ "nested PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat
new file mode 100644
index 0000000000..39a628b16c
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test2/testinfo.dat
@@ -0,0 +1,25 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT_EX
+
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+
+Type = DEFAULT
+
+EXE1 = test2
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT_EX block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= that contains another PAL_TRY-PAL_EXCEPT_EX block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt
new file mode 100644
index 0000000000..5fc3b096af
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test3.c
+)
+
+add_executable(paltest_pal_except_test3
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test3 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test3
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c b/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c
new file mode 100644
index 0000000000..0137697774
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/test3.c
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test3.c (exception_handling\pal_except\test3)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** that calls a function that contains
+** another PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_function = FALSE;
+BOOL bExcept_function = FALSE;
+
+/*
+ * Helper function that contains a PAL_TRY-PAL_EXCEPT block
+ */
+void Helper()
+{
+ /* Nested PAL_TRY */
+ PAL_TRY
+ {
+ int *lp = 0x00000000;
+
+ bTry_function = TRUE;
+
+ *lp = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the function's access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: Nested PAL_EXCEPT was hit without "
+ "the function's PAL_TRY being hit.\n");
+ }
+ bExcept_function = TRUE;
+ }
+ PAL_ENDTRY;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ Helper();
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_function)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without "
+ "function's PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_function)
+ {
+ Trace("ERROR: the code in the "
+ "function's PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_function)
+ {
+ Trace("ERROR: the code in the "
+ "function's PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_function || !bExcept_function)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat
new file mode 100644
index 0000000000..07da444a5a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test3/testinfo.dat
@@ -0,0 +1,27 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test3
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= that calls a function that contains
+
+= another PAL_TRY-PAL_EXCEPT block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt
new file mode 100644
index 0000000000..cc054d15dd
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test4.c
+)
+
+add_executable(paltest_pal_except_test4
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test4 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test4
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c b/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c
new file mode 100644
index 0000000000..87844973b0
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/test4.c
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test4.c (exception_handling\pal_except\test4)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** if the PAL_EXCEPT block contains a nested
+** PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ PAL_TRY
+ {
+ int *lp = 0x00000000;
+
+ bTry_nested = TRUE;
+ *lp = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the "
+ "nested access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry_nested)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit "
+ "in the nested block.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the nested "
+ "PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the nested "
+ "PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat
new file mode 100644
index 0000000000..d658cc85fa
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test4/testinfo.dat
@@ -0,0 +1,27 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test4
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= if the PAL_EXCEPT block contains a nested
+
+= PAL_TRY-PAL_EXCEPT block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt
new file mode 100644
index 0000000000..7b8f1d0361
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test5.c
+)
+
+add_executable(paltest_pal_except_test5
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test5 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test5
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c b/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c
new file mode 100644
index 0000000000..f9faf4440e
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/test5.c
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test5.c (exception_handling\pal_except\test5)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** if the PAL_EXCEPT block calls a function that contains
+** another PAL_TRY-PAL_EXCEPT block
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+
+ /* Nested PAL_TRY */
+ PAL_TRY
+ {
+ bTry_nested = TRUE;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: Nested PAL_EXCEPT was hit without "
+ "nested PAL_TRY being hit.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without "
+ "nested PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the "
+ "nested PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat
new file mode 100644
index 0000000000..2e12d0c64b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test5/testinfo.dat
@@ -0,0 +1,27 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test5
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= if the PAL_EXCEPT block calls a function that contains
+
+= another PAL_TRY-PAL_EXCEPT block
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt
new file mode 100644
index 0000000000..7f943bf126
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test6.c
+)
+
+add_executable(paltest_pal_except_test6
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test6 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test6
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c b/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c
new file mode 100644
index 0000000000..44b0ba1bc9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/test6.c
@@ -0,0 +1,160 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test6.c (exception_handling\pal_except\test6)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block
+** that contains multiple PAL_TRY-PAL_EXCEPT blocks
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+/* Execution flags */
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+BOOL bTry_nested = FALSE;
+BOOL bExcept_nested = FALSE;
+BOOL bTry_nested2 = FALSE;
+BOOL bExcept_nested2 = FALSE;
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /* First block */
+ PAL_TRY
+ {
+ int* p = 0x00000000; /* NULL pointer */
+
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+
+ /* Second PAL_TRY block */
+ PAL_TRY
+ {
+ bTry_nested = TRUE;
+
+ /* Third PAL_TRY block*/
+ PAL_TRY
+ {
+ bTry_nested2 = TRUE;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry_nested2)
+ {
+ Fail("ERROR: Third PAL_EXCEPT was hit without "
+ "third PAL_TRY being hit.\n");
+ }
+ bExcept_nested2 = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the nested access violation.\n");
+
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry_nested)
+ {
+ Fail("ERROR: Second PAL_EXCEPT was hit without "
+ "second PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested2)
+ {
+ Fail("ERROR: second PAL_EXCEPT was hit without "
+ "third PAL_EXCEPT being hit.\n");
+ }
+ bExcept_nested = TRUE;
+ }
+ PAL_ENDTRY;
+
+ *p = 13; /* causes an access violation exception */
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+ if (!bExcept_nested)
+ {
+ Fail("ERROR: first PAL_EXCEPT was hit without "
+ "second PAL_EXCEPT being hit.\n");
+ }
+ if (!bExcept_nested2)
+ {
+ Fail("ERROR: first PAL_EXCEPT was hit without "
+ "third PAL_EXCEPT being hit.\n");
+ }
+
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the "
+ "first PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the "
+ "first PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested)
+ {
+ Trace("ERROR: the code in the "
+ "second PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested)
+ {
+ Trace("ERROR: the code in the "
+ "second PAL_EXCEPT block was not executed.\n");
+ }
+
+ if (!bTry_nested2)
+ {
+ Trace("ERROR: the code in the "
+ "third PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept_nested2)
+ {
+ Trace("ERROR: the code in the "
+ "third PAL_EXCEPT block was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if(!bTry || !bExcept ||
+ !bTry_nested || !bExcept_nested ||
+ !bTry_nested2 || !bExcept_nested2)
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat
new file mode 100644
index 0000000000..f8901a7f50
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test6/testinfo.dat
@@ -0,0 +1,25 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT_EX
+
+Name = Test for PAL_TRY and PAL_EXCEPT_EX
+
+Type = DEFAULT
+
+EXE1 = test6
+
+LANG = cpp
+
+Description
+
+= Test to make sure the PAL_EXCEPT_EX block is executed
+
+= after an exception occurs in the PAL_TRY block
+
+= that contains multiple PAL_TRY-PAL_EXCEPT_EX blocks
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt
new file mode 100644
index 0000000000..09399c8f6b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ test7.c
+)
+
+add_executable(paltest_pal_except_test7
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_except_test7 coreclrpal)
+
+target_link_libraries(paltest_pal_except_test7
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c b/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c
new file mode 100644
index 0000000000..a8dc8331c2
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/test7.c
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: test7.c (exception_handling\pal_except\test7)
+**
+** Purpose: Tests the PAL implementation of the PAL_TRY and
+** PAL_EXCEPT functions. Tests that the EXCEPTION block
+** is missed if no exceptions happen
+**
+**
+**===================================================================*/
+
+
+
+#include <palsuite.h>
+
+
+int __cdecl main(int argc, char *argv[])
+{
+ BOOL bTry = FALSE;
+ BOOL bExcept = FALSE;
+
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+ /*
+ ** Test to make sure we skip the exception block.
+ */
+
+ PAL_TRY
+ {
+ bTry = TRUE; /* indicate we hit the PAL_TRY block */
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bExcept = TRUE; /* indicate we hit the PAL_EXCEPT block */
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_TRY"
+ " block was not executed.\n");
+ }
+
+ if (bExcept)
+ {
+ Trace("PAL_TRY_EXCEPT: ERROR -> It appears the code in the PAL_EXCEPT"
+ " block was executed even though no exception was supposed to"
+ " happen.\n");
+ }
+
+ /* did we hit the correct code blocks? */
+ if(!bTry || bExcept)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+ return PASS;
+
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat
new file mode 100644
index 0000000000..546d64cdec
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_except/test7/testinfo.dat
@@ -0,0 +1,24 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+
+Section = exception_handling
+
+Function = PAL_TRY and PAL_EXCEPT
+
+Name = Test for PAL_TRY and PAL_EXCEPT
+
+Type = DEFAULT
+
+EXE1 = test7
+
+LANG = cpp
+
+Description
+
+= In this test, no exceptions are forced to ensure the EXCEPTION block
+
+= isn't hit.
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt
new file mode 100644
index 0000000000..5d947ad7db
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ pal_finally.c
+)
+
+add_executable(paltest_pal_finally_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_pal_finally_test1 coreclrpal)
+
+target_link_libraries(paltest_pal_finally_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c
new file mode 100644
index 0000000000..f278f98956
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/pal_finally.c
@@ -0,0 +1,302 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: pal_finally.c (test 3)
+**
+** Purpose: Tests the PAL implementation of the PAL_FINALLY in the
+** presence of a call stack. An exception is forced and
+** passed to two nested exception filters for consideration.
+** The first filter returns EXCEPTION_CONTINUE_SEARCH so the
+** second can run and return EXCEPTION_EXECUTE_HANDLER. The
+** initial exception handler should be skipped, and the
+** second executed, and all the PAL_FINALLY blocks handled
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+BOOL bFilterCS = FALSE;
+BOOL bFilterEE = FALSE;
+BOOL bFinally1 = FALSE;
+BOOL bFinally2 = FALSE;
+BOOL bFinally3 = FALSE;
+BOOL bFinally4 = FALSE;
+BOOL bTry1 = FALSE;
+BOOL bTry2 = FALSE;
+BOOL bExcept1 = FALSE;
+BOOL bExcept2 = FALSE;
+BOOL bContinued = FALSE;
+const int nValidator = 12321;
+
+LONG ContSearchFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+
+ /* let the main know we've hit the filter function */
+ bFilterCS = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit after the ExecuteException "
+ "filter.\n");
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+LONG ExecExeptionFilter(EXCEPTION_POINTERS* ep, LPVOID pnTestInt)
+{
+ /* let the main know we've hit the filter function */
+ bFilterEE = TRUE;
+
+ if (!bTry1 || !bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ContSearch filter was hit without PAL_TRY being hit.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The ExecExeption filter was hit before the ContSearch "
+ "filter.\n");
+ }
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+void NestedFunc1 (void)
+{
+ int* p = 0x00000000; /* pointer to NULL */
+
+ PAL_TRY
+ {
+ PAL_TRY
+ {
+
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry2 = TRUE; /* indicate we hit the inner PAL_TRY block */
+ *p = 13; /* causes an access violation exception */
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_FINALLY
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler was hit without the outer "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler was hit without the inner "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler was hit without the inner "
+ "filter being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The first finally handler handler was hit without the "
+ "outer filter being hit.\n");
+ }
+ bFinally1 = TRUE; /* indicate we hit the first finally block */
+ }
+ PAL_ENDTRY;
+ }
+ PAL_EXCEPT_FILTER(ContSearchFilter, (LPVOID)&nValidator)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The dummy handler was "
+ "being hit.\n");
+ bExcept2 = TRUE; /* indicate we hit the inner block */
+ }
+ PAL_ENDTRY;
+
+}
+
+void NestedFunc2 (void)
+{
+ PAL_TRY
+ {
+ NestedFunc1();
+ }
+ PAL_FINALLY
+ {
+ if (!bFinally1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " The second finally handler handler was hit without the "
+ " top level one being hit.\n");
+ }
+ bFinally2 = TRUE;
+ }
+ PAL_ENDTRY ;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+ if (0 != PAL_Initialize(argc, argv))
+ {
+ return FAIL;
+ }
+
+
+ /*
+ ** test to make sure we get into the second exception block only based
+ ** on the return codes of the filters
+ */
+
+ PAL_TRY
+ {
+ PAL_TRY
+ {
+ PAL_TRY
+ {
+ if (bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going"
+ " on. PAL_EXCEPT_FILTER was hit before PAL_TRY.\n");
+ }
+ bTry1 = TRUE; /* indicate we hit the outer PAL_TRY block */
+
+ NestedFunc2();
+
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " We executed beyond the trapping code.\n");
+ }
+ PAL_FINALLY
+ {
+ if (!bFinally2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going"
+ " on. Finally handlers hit out of order (2->3)\n");
+ }
+ bFinally3 = TRUE;
+ }
+ PAL_ENDTRY;
+ }
+ PAL_EXCEPT_FILTER(ExecExeptionFilter, (LPVOID)&nValidator)
+ {
+ if (!bTry1)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the outer "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bTry2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the inner "
+ "PAL_TRY's code being hit.\n");
+ }
+ if (!bFilterCS)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the inner "
+ "filter being hit.\n");
+ }
+ if (!bFilterEE)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " PAL_EXCEPT_FILTER's handler was hit without the outer "
+ "filter being hit.\n");
+ }
+ bExcept1 = TRUE; /* indicate we hit the outer block */
+ }
+ PAL_ENDTRY;
+
+ if (bFinally4)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " Finally handler # 4 executed before it should be \n");
+ }
+ }
+ PAL_FINALLY
+ {
+ if (!bExcept1 || bExcept2)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " Exceptions handlers hit in wierd ways\n");
+ }
+ if (!bFinally3)
+ {
+ Fail("PAL_EXCEPT_FILTER: ERROR -> Something weird is going on."
+ " Finally handlers hit out of order 3->4)\n");
+ }
+
+ bFinally4 = TRUE;
+ }
+ PAL_ENDTRY;
+
+ if (!bTry1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the outer"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (!bTry2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the inner"
+ " PAL_TRY block was not executed.\n");
+ }
+
+ if (bExcept2)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "inner PAL_EXCEPT_FILTER block was executed.\n");
+ }
+ if (!bExcept1)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "outer PAL_EXCEPT_FILTER block was not executed.\n");
+ }
+
+ if (!bFilterCS)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "search continuing filter"
+ " function was not executed.\n");
+ }
+ if (!bFilterEE)
+ {
+ Trace("PAL_EXCEPT_FILTER: ERROR -> It appears the code in the "
+ "execute handler filter"
+ " function was not executed.\n");
+ }
+
+ /* did we hit all the code blocks? */
+ if (!bFinally1 || !bFinally2 || !bFinally3 || !bFinally4)
+ {
+ Fail("");
+ }
+ if(!bTry1 || !bTry2 || !bExcept1 || bExcept2 || !bFilterEE || !bFilterCS )
+ {
+ Fail("");
+ }
+
+
+ PAL_Terminate();
+ return PASS;
+
+}
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat
new file mode 100644
index 0000000000..5c26243438
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_finally/test1/testinfo.dat
@@ -0,0 +1,19 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = PAL_FINALLY
+Name = Test for nested PAL_FINALLY
+Type = DEFAULT
+EXE1 = pal_finally
+LANG = cpp
+Description
+= Tests the PAL implementation of the PAL_FINALLY in the presence
+= of a call stack. An exception is forced and passed to two nested
+= exception filters for consideration. The first filter returns
+= EXCEPTION_CONTINUE_SEARCH so the second can run and return
+= EXCEPTION_EXECUTE_HANDLER. The initial exception handler should
+= be skipped, and the second executed, and all the PAL_FINALLY
+= blocks handled.
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt
new file mode 100644
index 0000000000..f6aa0cb2d9
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(test1)
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt
new file mode 100644
index 0000000000..b0458db998
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/CMakeLists.txt
@@ -0,0 +1,97 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+ add_compile_options(-fPIC)
+ add_definitions(-DFEATURE_ENABLE_HARDWARE_EXCEPTIONS)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+# Set the RPATH of paltest_pal_sxs_test1 so that it can find dependencies without needing to set LD_LIBRARY
+# For more information: http://www.cmake.org/Wiki/CMake_RPATH_handling.
+if(CORECLR_SET_RPATH)
+ if(CLR_CMAKE_PLATFORM_LINUX)
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN")
+ endif(CLR_CMAKE_PLATFORM_LINUX)
+endif(CORECLR_SET_RPATH)
+
+# Test DLL1
+
+set(DEF_SOURCES1 dlltest1.src)
+convert_to_absolute_path(DEF_SOURCES1 ${DEF_SOURCES1})
+set(EXPORTS_FILE1 ${CMAKE_CURRENT_BINARY_DIR}/dlltest1.exports)
+generate_exports_file(${DEF_SOURCES1} ${EXPORTS_FILE1})
+
+if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+ set(EXPORTS_LINKER_OPTION1 -Wl,--version-script=${EXPORTS_FILE1})
+endif(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+
+if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+ set(EXPORTS_LINKER_OPTION1 -Wl,-exported_symbols_list,${EXPORTS_FILE1})
+endif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+
+set(DLL1SOURCES dlltest1.cpp)
+add_library(paltest_pal_sxs_test1_dll1 SHARED ${DLL1SOURCES})
+add_custom_target(dlltest1_exports DEPENDS ${EXPORTS_FILE1})
+set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION1})
+set_property(TARGET paltest_pal_sxs_test1_dll1 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE1})
+
+add_dependencies(paltest_pal_sxs_test1_dll1
+ dlltest1_exports
+ coreclrpal
+)
+
+target_link_libraries(paltest_pal_sxs_test1_dll1
+ pthread
+ m
+ coreclrpal
+)
+
+# Test DLL2
+
+set(DEF_SOURCES2 dlltest2.src)
+convert_to_absolute_path(DEF_SOURCES2 ${DEF_SOURCES2})
+set(EXPORTS_FILE2 ${CMAKE_CURRENT_BINARY_DIR}/dlltest2.exports)
+generate_exports_file(${DEF_SOURCES2} ${EXPORTS_FILE2})
+
+if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+ set(EXPORTS_LINKER_OPTION2 -Wl,--version-script=${EXPORTS_FILE2})
+endif(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL NetBSD)
+
+if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+ set(EXPORTS_LINKER_OPTION2 -Wl,-exported_symbols_list,${EXPORTS_FILE2})
+endif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
+
+set(DLL2SOURCES dlltest2.cpp)
+add_library(paltest_pal_sxs_test1_dll2 SHARED ${DLL2SOURCES})
+add_custom_target(dlltest2_exports DEPENDS ${EXPORTS_FILE2})
+set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_FLAGS ${EXPORTS_LINKER_OPTION2})
+set_property(TARGET paltest_pal_sxs_test1_dll2 APPEND_STRING PROPERTY LINK_DEPENDS ${EXPORTS_FILE2})
+
+add_dependencies(paltest_pal_sxs_test1_dll2
+ dlltest2_exports
+ coreclrpal
+)
+
+target_link_libraries(paltest_pal_sxs_test1_dll2
+ pthread
+ m
+ coreclrpal
+)
+
+# Main program
+
+set(TESTSOURCES exceptionsxs.cpp)
+
+add_executable(paltest_pal_sxs_test1 ${TESTSOURCES})
+
+add_dependencies(paltest_pal_sxs_test1
+ paltest_pal_sxs_test1_dll1
+ paltest_pal_sxs_test1_dll2
+)
+
+target_link_libraries(paltest_pal_sxs_test1
+ paltest_pal_sxs_test1_dll1
+ paltest_pal_sxs_test1_dll2
+)
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp
new file mode 100644
index 0000000000..614690897a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: dlltest1.c (exception_handling\pal_sxs\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block with
+** multiple PALs in the process.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+extern "C"
+int InitializeDllTest1()
+{
+ return PAL_InitializeDLL();
+}
+
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+extern "C"
+int DllTest1()
+{
+ Trace("Starting pal_sxs test1 DllTest1\n");
+
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ volatile int* p = (volatile int *)0x11; // Invalid pointer
+
+ bTry = TRUE; // Indicate we hit the PAL_TRY block
+ *p = 1; // Causes an access violation exception
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ // Validate that the faulting address is correct; the contents of "p" (0x11).
+ if (ex.GetExceptionRecord()->ExceptionInformation[1] != 0x11)
+ {
+ Fail("ERROR: PAL_EXCEPT ExceptionInformation[1] != 0x11\n");
+ }
+
+ bExcept = TRUE; // Indicate we hit the PAL_EXCEPT block
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ // Did we hit all the code blocks?
+ if(!bTry || !bExcept)
+ {
+ Fail("DllTest1 FAILED\n");
+ }
+
+ Trace("DLLTest1 PASSED\n");
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src
new file mode 100644
index 0000000000..0a0a6ee44a
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.src
@@ -0,0 +1,3 @@
+InitializeDllTest1
+DllTest1
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp
new file mode 100644
index 0000000000..1e85821422
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: dlltest2.c (exception_handling\pal_sxs\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block with
+** multiple PALs in the process.
+**
+**
+**===================================================================*/
+#include <palsuite.h>
+
+extern "C"
+int InitializeDllTest2()
+{
+ return PAL_InitializeDLL();
+}
+
+BOOL bTry = FALSE;
+BOOL bExcept = FALSE;
+
+extern "C"
+int DllTest2()
+{
+ Trace("Starting pal_sxs test1 DllTest2\n");
+
+ PAL_TRY(VOID*, unused, NULL)
+ {
+ volatile int* p = (volatile int *)0x22; // Invalid pointer
+
+ bTry = TRUE; // Indicate we hit the PAL_TRY block
+ *p = 2; // Causes an access violation exception
+
+ Fail("ERROR: code was executed after the access violation.\n");
+ }
+ PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (!bTry)
+ {
+ Fail("ERROR: PAL_EXCEPT was hit without PAL_TRY being hit.\n");
+ }
+
+ // Validate that the faulting address is correct; the contents of "p" (0x22).
+ if (ex.GetExceptionRecord()->ExceptionInformation[1] != 0x22)
+ {
+ Fail("ERROR: PAL_EXCEPT ExceptionInformation[1] != 0x22\n");
+ }
+
+ bExcept = TRUE; // Indicate we hit the PAL_EXCEPT block
+ }
+ PAL_ENDTRY;
+
+ if (!bTry)
+ {
+ Trace("ERROR: the code in the PAL_TRY block was not executed.\n");
+ }
+
+ if (!bExcept)
+ {
+ Trace("ERROR: the code in the PAL_EXCEPT block was not executed.\n");
+ }
+
+ // Did we hit all the code blocks?
+ if(!bTry || !bExcept)
+ {
+ Fail("DllTest2 FAILED\n");
+ }
+
+ Trace("DLLTest2 PASSED\n");
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src
new file mode 100644
index 0000000000..433419bc5b
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.src
@@ -0,0 +1,3 @@
+InitializeDllTest2
+DllTest2
+
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp
new file mode 100644
index 0000000000..97a963c120
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/exceptionsxs.cpp
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=====================================================================
+**
+** Source: exceptionsxs.c (exception_handling\pal_sxs\test1)
+**
+** Purpose: Test to make sure the PAL_EXCEPT block is executed
+** after an exception occurs in the PAL_TRY block with
+** multiple PALs in the process.
+**
+**
+**===================================================================*/
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+enum
+{
+ PASS = 0,
+ FAIL = 1
+};
+
+extern "C" int InitializeDllTest1();
+extern "C" int InitializeDllTest2();
+extern "C" int DllTest1();
+extern "C" int DllTest2();
+
+bool bSignal = false;
+bool bCatch = false;
+bool bHandler = false;
+
+void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
+{
+ printf("pal_sxs test1: signal handler called\n");
+ bHandler = true; // Mark that the signal handler was executed
+
+ if (!bSignal)
+ {
+ printf("ERROR: executed signal handler NOT from try/catch\n");
+ _exit(FAIL);
+ }
+
+ // Validate that the faulting address is correct; the contents of "p" (0x22).
+ if (siginfo->si_addr != (void *)0x33)
+ {
+ printf("ERROR: signal handler faulting address != 0x33\n");
+ _exit(FAIL);
+ }
+
+ // Unmask signal so we can receive it again
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGSEGV);
+ if (-1 == sigprocmask(SIG_UNBLOCK, &signal_set, NULL))
+ {
+ printf("ERROR: sigprocmask failed; error is %d\n", errno);
+ _exit(FAIL);
+ }
+
+ printf("Signal chaining PASSED\n");
+ _exit(PASS);
+}
+
+int main(int argc, char *argv[])
+{
+ struct sigaction newAction;
+ struct sigaction oldAction;
+ newAction.sa_flags = SA_SIGINFO | SA_RESTART;
+ newAction.sa_handler = NULL;
+ newAction.sa_sigaction = sigsegv_handler;
+ sigemptyset(&newAction.sa_mask);
+
+ if (-1 == sigaction(SIGSEGV, &newAction, &oldAction))
+ {
+ printf("ERROR: sigaction failed; error is %d\n", errno);
+ return FAIL;
+ }
+
+ printf("PAL_SXS test1 SIGSEGV handler %p\n", oldAction.sa_sigaction);
+
+ if (0 != InitializeDllTest1())
+ {
+ return FAIL;
+ }
+
+ if (0 != InitializeDllTest2())
+ {
+ return FAIL;
+ }
+
+ // Test catching exceptions in other PAL instances
+ DllTest2();
+ DllTest1();
+ DllTest2();
+
+ if (bHandler)
+ {
+ printf("ERROR: signal handler called by PAL sxs tests\n");
+ return FAIL;
+ }
+
+ printf("Starting PAL_SXS test1 signal chaining\n");
+
+ bSignal = true;
+
+ volatile int* p = (volatile int *)0x33; // Invalid pointer
+ *p = 3; // Causes an access violation exception
+
+ printf("ERROR: code was executed after the access violation.\n");
+ return FAIL;
+}
diff --git a/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat
new file mode 100644
index 0000000000..c0cf1ddfcb
--- /dev/null
+++ b/src/pal/tests/palsuite/exception_handling/pal_sxs/test1/testinfo.dat
@@ -0,0 +1,13 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = exception_handling
+Function = test1
+Name = pal_sxs test #1
+TYPE = DEFAULT
+EXE1 = test1
+LANG = cpp
+Description
+=Tests that exceptions across multiples pals work correctly