diff options
Diffstat (limited to 'src/pal/tests/palsuite/exception_handling/pal_sxs')
8 files changed, 387 insertions, 0 deletions
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 |