From 09d1d97896d4304420fecca6c1e450a228ec6277 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 30 May 2024 16:33:30 +0300 Subject: [PATCH] Update llvm-libunwind to v18 (#102231) * Update llvm-libunwind to v18 * Apply all patches * Update version file --- .../external/llvm-libunwind-version.txt | 7 +- src/native/external/llvm-libunwind.cmake | 7 - .../external/llvm-libunwind/CMakeLists.txt | 79 +++--- .../cmake/Modules/HandleLibunwindFlags.cmake | 181 +------------ .../llvm-libunwind/cmake/config-ix.cmake | 20 +- .../external/llvm-libunwind/docs/conf.py | 134 +++++----- .../include/__libunwind_config.h | 7 +- .../llvm-libunwind/include/libunwind.h | 3 + .../llvm-libunwind/src/AddressSpace.hpp | 28 +- .../llvm-libunwind/src/CMakeLists.txt | 72 ++--- .../llvm-libunwind/src/DwarfInstructions.hpp | 2 +- .../llvm-libunwind/src/EHHeaderParser.hpp | 13 + .../llvm-libunwind/src/FrameHeaderCache.hpp | 6 +- .../external/llvm-libunwind/src/Registers.hpp | 20 +- .../llvm-libunwind/src/Unwind-EHABI.cpp | 9 +- .../llvm-libunwind/src/Unwind-seh.cpp | 19 +- .../external/llvm-libunwind/src/Unwind-sjlj.c | 11 +- .../external/llvm-libunwind/src/Unwind-wasm.c | 123 +++++++++ .../llvm-libunwind/src/UnwindCursor.hpp | 239 +++++++++++++---- .../llvm-libunwind/src/UnwindLevel1-gcc-ext.c | 4 +- .../llvm-libunwind/src/UnwindLevel1.c | 2 +- .../src/UnwindRegistersRestore.S | 4 + .../llvm-libunwind/src/UnwindRegistersSave.S | 44 +++- .../llvm-libunwind/src/Unwind_AppleExtras.cpp | 113 -------- .../external/llvm-libunwind/src/config.h | 26 +- .../external/llvm-libunwind/src/libunwind.cpp | 87 ++++++- .../llvm-libunwind/src/libunwind_ext.h | 65 +++++ .../external/llvm-libunwind/src/unwind_ext.h | 37 --- .../llvm-libunwind/test/CMakeLists.txt | 24 +- .../test/aix_signal_unwind.pass.sh.S | 245 ++++++++++++++++++ .../test/bad_unwind_info.pass.cpp | 2 +- .../apple-libunwind-backdeployment.cfg.in | 8 +- .../configs/armv7m-picolibc-libunwind.cfg.in | 39 +++ .../test/configs/cmake-bridge.cfg.in | 3 +- .../test/configs/ibm-libunwind-shared.cfg.in | 10 +- .../test/configs/llvm-libunwind-merged.cfg.in | 14 +- .../test/configs/llvm-libunwind-mingw.cfg.in | 25 ++ .../test/configs/llvm-libunwind-shared.cfg.in | 14 +- .../test/configs/llvm-libunwind-static.cfg.in | 14 +- .../llvm-libunwind/test/forceunwind.pass.cpp | 2 +- .../llvm-libunwind/test/libunwind_01.pass.cpp | 2 +- .../llvm-libunwind/test/libunwind_02.pass.cpp | 31 ++- .../external/llvm-libunwind/test/lit.cfg.py | 3 +- .../llvm-libunwind/test/signal_frame.pass.cpp | 6 +- .../test/signal_unwind.pass.cpp | 2 +- .../llvm-libunwind/test/unw_resume.pass.cpp | 5 +- .../test/unwind_leaffunction.pass.cpp | 22 +- .../test/unwind_scalable_vectors.pass.cpp | 38 +-- 48 files changed, 1211 insertions(+), 660 deletions(-) create mode 100644 src/native/external/llvm-libunwind/src/Unwind-wasm.c delete mode 100644 src/native/external/llvm-libunwind/src/Unwind_AppleExtras.cpp delete mode 100644 src/native/external/llvm-libunwind/src/unwind_ext.h create mode 100644 src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S create mode 100644 src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in create mode 100644 src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in diff --git a/src/native/external/llvm-libunwind-version.txt b/src/native/external/llvm-libunwind-version.txt index d23999cc453682..f833dd0c83fb59 100644 --- a/src/native/external/llvm-libunwind-version.txt +++ b/src/native/external/llvm-libunwind-version.txt @@ -1,6 +1,5 @@ -v16.0.2 -https://github.com/llvm/llvm-project/releases/tag/llvmorg-16.0.2 +v18.1.5 +https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.5 -Apply https://github.com/dotnet/runtime/commit/1bafb60792b91747d9c2a9dd38461cf090a987a4 -Apply https://github.com/dotnet/runtime/commit/0ee8827547405408b37d1aae2a83629c1632eea8 +Apply https://github.com/dotnet/runtime/commit/a53805790a49f5bf52776dc81c1c83ec7f21ebce diff --git a/src/native/external/llvm-libunwind.cmake b/src/native/external/llvm-libunwind.cmake index 72cecd2a149806..720dc5ae6f890f 100644 --- a/src/native/external/llvm-libunwind.cmake +++ b/src/native/external/llvm-libunwind.cmake @@ -9,13 +9,6 @@ set (LLVM_LIBUNWIND_SOURCES_BASE src/libunwind.cpp ) -if(CLR_CMAKE_TARGET_APPLE) - set(LLVM_LIBUNWIND_SOURCES_BASE - ${LLVM_LIBUNWIND_SOURCES_BASE} - src/Unwind_AppleExtras.cpp - ) -endif() - set(LLVM_LIBUNWIND_ASM_SOURCES_BASE src/UnwindRegistersRestore.S src/UnwindRegistersSave.S diff --git a/src/native/external/llvm-libunwind/CMakeLists.txt b/src/native/external/llvm-libunwind/CMakeLists.txt index 5c547883f99275..806d5a783ec39c 100644 --- a/src/native/external/llvm-libunwind/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/CMakeLists.txt @@ -2,7 +2,7 @@ # Setup Project #=============================================================================== -cmake_minimum_required(VERSION 3.13.4) +cmake_minimum_required(VERSION 3.20.0) set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") @@ -10,6 +10,7 @@ set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + "${CMAKE_CURRENT_SOURCE_DIR}/../runtimes/cmake/Modules" "${LLVM_COMMON_CMAKE_UTILS}" "${LLVM_COMMON_CMAKE_UTILS}/Modules" ) @@ -20,6 +21,7 @@ set(LIBUNWIND_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH "Specify path to libc++ source.") include(GNUInstallDirs) +include(CheckSymbolExists) #=============================================================================== # Setup CMake Options @@ -50,6 +52,7 @@ option(LIBUNWIND_IS_BAREMETAL "Build libunwind for baremetal targets." OFF) option(LIBUNWIND_USE_FRAME_HEADER_CACHE "Cache frame headers for unwinding. Requires locking dl_iterate_phdr." OFF) option(LIBUNWIND_REMEMBER_HEAP_ALLOC "Use heap instead of the stack for .cfi_remember_state." OFF) option(LIBUNWIND_INSTALL_HEADERS "Install the libunwind headers." ON) +option(LIBUNWIND_ENABLE_FRAME_APIS "Include libgcc-compatible frame apis." OFF) set(LIBUNWIND_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING "Define suffix of library directory name (32/64)") @@ -61,12 +64,9 @@ cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY "Install the shared libunwind library." ON "LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF) -# TODO: Remove this after branching for LLVM 15 -if(LIBUNWIND_SYSROOT OR LIBUNWIND_TARGET_TRIPLE OR LIBUNWIND_GCC_TOOLCHAIN) - message(WARNING "LIBUNWIND_SYSROOT, LIBUNWIND_TARGET_TRIPLE and LIBUNWIND_GCC_TOOLCHAIN are not supported anymore, please use the native CMake equivalents instead") -endif() - -if (LIBUNWIND_ENABLE_SHARED) +if(MINGW) + set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-mingw.cfg.in") +elseif (LIBUNWIND_ENABLE_SHARED) set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-shared.cfg.in") else() set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-static.cfg.in") @@ -97,6 +97,20 @@ endif() option(LIBUNWIND_HIDE_SYMBOLS "Do not export any symbols from the static library." ${LIBUNWIND_DEFAULT_HIDE_SYMBOLS}) +# If toolchain is FPXX, we switch to FP64 to save the full FPRs. See: +# https://web.archive.org/web/20180828210612/https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking +check_symbol_exists(__mips_hard_float "" __MIPSHF) +check_symbol_exists(_ABIO32 "" __MIPS_O32) +if (__MIPSHF AND __MIPS_O32) + file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/mips_is_fpxx.c + "#if __mips_fpr != 0\n" + "# error\n" + "#endif\n") + try_compile(MIPS_FPABI_FPXX ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/mips_is_fpxx.c + CMAKE_FLAGS -DCMAKE_C_LINK_EXECUTABLE='echo') +endif() + #=============================================================================== # Configure System #=============================================================================== @@ -106,9 +120,9 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) -set(LIBUNWIND_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH +set(LIBUNWIND_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}" CACHE STRING "Path where built libunwind headers should be installed.") -set(LIBUNWIND_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH +set(LIBUNWIND_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING "Path where built libunwind runtime libraries should be installed.") set(LIBUNWIND_SHARED_OUTPUT_NAME "unwind" CACHE STRING "Output name for the shared libunwind runtime library.") @@ -116,7 +130,7 @@ set(LIBUNWIND_STATIC_OUTPUT_NAME "unwind" CACHE STRING "Output name for the stat if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING "Path where built libunwind libraries should be installed.") if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) @@ -128,7 +142,7 @@ else() else() set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX}) endif() - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX} CACHE PATH + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX} CACHE STRING "Path where built libunwind libraries should be installed.") endif() @@ -140,6 +154,10 @@ set(LIBUNWIND_C_FLAGS "") set(LIBUNWIND_CXX_FLAGS "") set(LIBUNWIND_COMPILE_FLAGS "") set(LIBUNWIND_LINK_FLAGS "") +set(LIBUNWIND_ADDITIONAL_COMPILE_FLAGS "" CACHE STRING + "Additional Compile only flags which can be provided in cache") +set(LIBUNWIND_ADDITIONAL_LIBRARIES "" CACHE STRING + "Additional libraries libunwind is linked to which can be provided in cache") # Include macros for adding and removing libunwind flags. include(HandleLibunwindFlags) @@ -168,28 +186,6 @@ if (LIBUNWIND_ENABLE_CET) endif() endif() -# Get warning flags -add_compile_flags_if_supported(-W) -add_compile_flags_if_supported(-Wall) -add_compile_flags_if_supported(-Wchar-subscripts) -add_compile_flags_if_supported(-Wconversion) -add_compile_flags_if_supported(-Wmismatched-tags) -add_compile_flags_if_supported(-Wmissing-braces) -add_compile_flags_if_supported(-Wnewline-eof) -add_compile_flags_if_supported(-Wno-unused-function) -add_compile_flags_if_supported(-Wshadow) -add_compile_flags_if_supported(-Wshorten-64-to-32) -add_compile_flags_if_supported(-Wsign-compare) -add_compile_flags_if_supported(-Wsign-conversion) -add_compile_flags_if_supported(-Wstrict-aliasing=2) -add_compile_flags_if_supported(-Wstrict-overflow=4) -add_compile_flags_if_supported(-Wunused-parameter) -add_compile_flags_if_supported(-Wunused-variable) -add_compile_flags_if_supported(-Wwrite-strings) -add_compile_flags_if_supported(-Wundef) - -add_compile_flags_if_supported(-Wno-suggest-override) - if (WIN32) # The headers lack matching dllexport attributes (_LIBUNWIND_EXPORT); # silence the warning instead of cluttering the headers (which aren't @@ -198,16 +194,8 @@ if (WIN32) add_compile_flags_if_supported(-Wno-dll-attribute-on-redeclaration) endif() -if (LIBUNWIND_ENABLE_WERROR) - add_compile_flags_if_supported(-Werror) - add_compile_flags_if_supported(-WX) -else() - add_compile_flags_if_supported(-Wno-error) - add_compile_flags_if_supported(-WX-) -endif() - -if (LIBUNWIND_ENABLE_PEDANTIC) - add_compile_flags_if_supported(-pedantic) +if (MIPS_FPABI_FPXX) + add_compile_flags(-mfp64) endif() # Get feature flags. @@ -277,6 +265,11 @@ if (NOT LIBUNWIND_ENABLE_CROSS_UNWINDING) add_compile_flags(-D_LIBUNWIND_IS_NATIVE_ONLY) endif() +# Include stubs for __register_frame_info_bases and related +if (LIBUNWIND_ENABLE_FRAME_APIS) + add_compile_flags(-D_LIBUNWIND_SUPPORT_FRAME_APIS) +endif() + # Threading-support if (NOT LIBUNWIND_ENABLE_THREADS) add_compile_flags(-D_LIBUNWIND_HAS_NO_THREADS) diff --git a/src/native/external/llvm-libunwind/cmake/Modules/HandleLibunwindFlags.cmake b/src/native/external/llvm-libunwind/cmake/Modules/HandleLibunwindFlags.cmake index c5d76034d87099..94c676338821c7 100644 --- a/src/native/external/llvm-libunwind/cmake/Modules/HandleLibunwindFlags.cmake +++ b/src/native/external/llvm-libunwind/cmake/Modules/HandleLibunwindFlags.cmake @@ -6,162 +6,10 @@ include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) +include(HandleFlags) unset(add_flag_if_supported) -# Mangle the name of a compiler flag into a valid CMake identifier. -# Ex: --std=c++11 -> STD_EQ_CXX11 -macro(mangle_name str output) - string(STRIP "${str}" strippedStr) - string(REGEX REPLACE "^/" "" strippedStr "${strippedStr}") - string(REGEX REPLACE "^-+" "" strippedStr "${strippedStr}") - string(REGEX REPLACE "-+$" "" strippedStr "${strippedStr}") - string(REPLACE "-" "_" strippedStr "${strippedStr}") - string(REPLACE "=" "_EQ_" strippedStr "${strippedStr}") - string(REPLACE "+" "X" strippedStr "${strippedStr}") - string(TOUPPER "${strippedStr}" ${output}) -endmacro() - -# Remove a list of flags from all CMake variables that affect compile flags. -# This can be used to remove unwanted flags specified on the command line -# or added in other parts of LLVM's cmake configuration. -macro(remove_flags) - foreach(var ${ARGN}) - string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}") - string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - string(REPLACE "${var}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE "${var}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - string(REPLACE "${var}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") - string(REPLACE "${var}" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - string(REPLACE "${var}" "" CMAKE_SHARED_MODULE_FLAGS "${CMAKE_SHARED_MODULE_FLAGS}") - remove_definitions(${var}) - endforeach() -endmacro(remove_flags) - -macro(check_flag_supported flag) - mangle_name("${flag}" flagname) - check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG") -endmacro() - -macro(append_flags DEST) - foreach(value ${ARGN}) - list(APPEND ${DEST} ${value}) - list(APPEND ${DEST} ${value}) - endforeach() -endmacro() - -# If the specified 'condition' is true then append the specified list of flags to DEST -macro(append_flags_if condition DEST) - if (${condition}) - list(APPEND ${DEST} ${ARGN}) - endif() -endmacro() - -# Add each flag in the list specified by DEST if that flag is supported by the current compiler. -macro(append_flags_if_supported DEST) - foreach(flag ${ARGN}) - mangle_name("${flag}" flagname) - check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG") - append_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${DEST} ${flag}) - endforeach() -endmacro() - -# Add a macro definition if condition is true. -macro(define_if condition def) - if (${condition}) - add_definitions(${def}) - endif() -endmacro() - -# Add a macro definition if condition is not true. -macro(define_if_not condition def) - if (NOT ${condition}) - add_definitions(${def}) - endif() -endmacro() - -# Add a macro definition to the __config_site file if the specified condition -# is 'true'. Note that '-D${def}' is not added. Instead it is expected that -# the build include the '__config_site' header. -macro(config_define_if condition def) - if (${condition}) - set(${def} ON) - set(LIBUNWIND_NEEDS_SITE_CONFIG ON) - endif() -endmacro() - -macro(config_define_if_not condition def) - if (NOT ${condition}) - set(${def} ON) - set(LIBUNWIND_NEEDS_SITE_CONFIG ON) - endif() -endmacro() - -macro(config_define value def) - set(${def} ${value}) - set(LIBUNWIND_NEEDS_SITE_CONFIG ON) -endmacro() - -# Add a list of flags to all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', -# 'LIBUNWIND_COMPILE_FLAGS' and 'LIBUNWIND_LINK_FLAGS'. -macro(add_target_flags) - foreach(value ${ARGN}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}") - list(APPEND LIBUNWIND_COMPILE_FLAGS ${value}) - list(APPEND LIBUNWIND_LINK_FLAGS ${value}) - endforeach() -endmacro() - -# If the specified 'condition' is true then add a list of flags to -# all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBUNWIND_COMPILE_FLAGS' -# and 'LIBUNWIND_LINK_FLAGS'. -macro(add_target_flags_if condition) - if (${condition}) - add_target_flags(${ARGN}) - endif() -endmacro() - -# Add all the flags supported by the compiler to all of -# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBUNWIND_COMPILE_FLAGS' -# and 'LIBUNWIND_LINK_FLAGS'. -macro(add_target_flags_if_supported) - foreach(flag ${ARGN}) - mangle_name("${flag}" flagname) - check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG") - add_target_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag}) - endforeach() -endmacro() - -# Add a specified list of flags to both 'LIBUNWIND_COMPILE_FLAGS' and -# 'LIBUNWIND_LINK_FLAGS'. -macro(add_flags) - foreach(value ${ARGN}) - list(APPEND LIBUNWIND_COMPILE_FLAGS ${value}) - list(APPEND LIBUNWIND_LINK_FLAGS ${value}) - endforeach() -endmacro() - -# If the specified 'condition' is true then add a list of flags to both -# 'LIBUNWIND_COMPILE_FLAGS' and 'LIBUNWIND_LINK_FLAGS'. -macro(add_flags_if condition) - if (${condition}) - add_flags(${ARGN}) - endif() -endmacro() - -# Add each flag in the list to LIBUNWIND_COMPILE_FLAGS and LIBUNWIND_LINK_FLAGS -# if that flag is supported by the current compiler. -macro(add_flags_if_supported) - foreach(flag ${ARGN}) - mangle_name("${flag}" flagname) - check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG") - add_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag}) - endforeach() -endmacro() - # Add a list of flags to 'LIBUNWIND_COMPILE_FLAGS'. macro(add_compile_flags) foreach(f ${ARGN}) @@ -202,16 +50,6 @@ macro(add_c_flags_if condition) endif() endmacro() -# For each specified flag, add that flag to 'LIBUNWIND_C_FLAGS' if the -# flag is supported by the C compiler. -macro(add_c_compile_flags_if_supported) - foreach(flag ${ARGN}) - mangle_name("${flag}" flagname) - check_c_compiler_flag("${flag}" "C_SUPPORTS_${flagname}_FLAG") - add_c_flags_if(C_SUPPORTS_${flagname}_FLAG ${flag}) - endforeach() -endmacro() - # Add a list of flags to 'LIBUNWIND_CXX_FLAGS'. macro(add_cxx_flags) foreach(f ${ARGN}) @@ -276,20 +114,3 @@ macro(add_library_flags_if condition) add_library_flags(${ARGN}) endif() endmacro() - -# Turn a comma separated CMake list into a space separated string. -macro(split_list listname) - string(REPLACE ";" " " ${listname} "${${listname}}") -endmacro() - -# For each specified flag, add that compile flag to the provided target. -# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE. -function(target_add_compile_flags_if_supported target visibility) - foreach(flag ${ARGN}) - mangle_name("${flag}" flagname) - check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG") - if (CXX_SUPPORTS_${flagname}_FLAG) - target_compile_options(${target} ${visibility} ${flag}) - endif() - endforeach() -endfunction() diff --git a/src/native/external/llvm-libunwind/cmake/config-ix.cmake b/src/native/external/llvm-libunwind/cmake/config-ix.cmake index d311477f02c690..126c872f0d4895 100644 --- a/src/native/external/llvm-libunwind/cmake/config-ix.cmake +++ b/src/native/external/llvm-libunwind/cmake/config-ix.cmake @@ -11,7 +11,11 @@ include(CheckCSourceCompiles) # --unwindlib=none is supported, and use that if possible. llvm_check_compiler_linker_flag(C "--unwindlib=none" CXX_SUPPORTS_UNWINDLIB_EQ_NONE_FLAG) -check_library_exists(c fopen "" LIBUNWIND_HAS_C_LIB) +if (HAIKU) + check_library_exists(root fopen "" LIBUNWIND_HAS_ROOT_LIB) +else() + check_library_exists(c fopen "" LIBUNWIND_HAS_C_LIB) +endif() if (NOT LIBUNWIND_USE_COMPILER_RT) if (ANDROID) @@ -41,10 +45,15 @@ else() endif() endif() -if (CXX_SUPPORTS_NOSTDLIBXX_FLAG OR C_SUPPORTS_NODEFAULTLIBS_FLAG) +# Only link against compiler-rt manually if we use -nodefaultlibs, since +# otherwise the compiler will do the right thing on its own. +if (NOT CXX_SUPPORTS_NOSTDLIBXX_FLAG AND C_SUPPORTS_NODEFAULTLIBS_FLAG) if (LIBUNWIND_HAS_C_LIB) list(APPEND CMAKE_REQUIRED_LIBRARIES c) endif () + if (LIBUNWIND_HAS_ROOT_LIB) + list(APPEND CMAKE_REQUIRED_LIBRARIES root) + endif () if (LIBUNWIND_USE_COMPILER_RT) include(HandleCompilerRT) find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY @@ -71,6 +80,9 @@ if (CXX_SUPPORTS_NOSTDLIBXX_FLAG OR C_SUPPORTS_NODEFAULTLIBS_FLAG) moldname mingwex msvcrt) list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES}) endif() +endif() + +if (CXX_SUPPORTS_NOSTDLIBXX_FLAG OR C_SUPPORTS_NODEFAULTLIBS_FLAG) if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all") endif () @@ -111,3 +123,7 @@ else() check_library_exists(dl dladdr "" LIBUNWIND_HAS_DL_LIB) check_library_exists(pthread pthread_once "" LIBUNWIND_HAS_PTHREAD_LIB) endif() + +if(HAIKU) + check_library_exists(bsd dl_iterate_phdr "" LIBUNWIND_HAS_BSD_LIB) +endif() diff --git a/src/native/external/llvm-libunwind/docs/conf.py b/src/native/external/llvm-libunwind/docs/conf.py index 404bcb06857598..29f9c24a7ee261 100644 --- a/src/native/external/llvm-libunwind/docs/conf.py +++ b/src/native/external/llvm-libunwind/docs/conf.py @@ -16,106 +16,106 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo'] +extensions = ["sphinx.ext.intersphinx", "sphinx.ext.todo"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'libunwind' -copyright = u'2011-%d, LLVM Project' % date.today().year +project = "libunwind" +copyright = "2011-%d, LLVM Project" % date.today().year # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '16.0' +version = "17.0" # The full version, including alpha/beta/rc tags. -release = '16.0' +release = "17.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -today_fmt = '%Y-%m-%d' +today_fmt = "%Y-%m-%d" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'friendly' +pygments_style = "friendly" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'haiku' +html_theme = "haiku" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -124,101 +124,95 @@ # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'libunwinddoc' +htmlhelp_basename = "libunwinddoc" # -- Options for LaTeX output -------------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('contents', 'libunwind.tex', u'libunwind Documentation', - u'LLVM project', 'manual'), + ("contents", "libunwind.tex", "libunwind Documentation", "LLVM project", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('contents', 'libunwind', u'libunwind Documentation', - [u'LLVM project'], 1) -] +man_pages = [("contents", "libunwind", "libunwind Documentation", ["LLVM project"], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ @@ -227,19 +221,25 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('contents', 'libunwind', u'libunwind Documentation', - u'LLVM project', 'libunwind', 'LLVM Unwinder', - 'Miscellaneous'), + ( + "contents", + "libunwind", + "libunwind Documentation", + "LLVM project", + "libunwind", + "LLVM Unwinder", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # FIXME: Define intersphinx configuration. diff --git a/src/native/external/llvm-libunwind/include/__libunwind_config.h b/src/native/external/llvm-libunwind/include/__libunwind_config.h index b925489e3e7fe6..ecfe7be0d12f6c 100644 --- a/src/native/external/llvm-libunwind/include/__libunwind_config.h +++ b/src/native/external/llvm-libunwind/include/__libunwind_config.h @@ -36,6 +36,9 @@ # if defined(__linux__) # define _LIBUNWIND_TARGET_LINUX 1 # endif +# if defined(__HAIKU__) +# define _LIBUNWIND_TARGET_HAIKU 1 +# endif # if defined(__i386__) # define _LIBUNWIND_TARGET_I386 # define _LIBUNWIND_CONTEXT_SIZE 13 @@ -201,9 +204,9 @@ # define _LIBUNWIND_TARGET_RISCV 1 # define _LIBUNWIND_TARGET_VE 1 # define _LIBUNWIND_TARGET_S390X 1 -#define _LIBUNWIND_TARGET_LOONGARCH 1 +# define _LIBUNWIND_TARGET_LOONGARCH 1 # define _LIBUNWIND_CONTEXT_SIZE 167 -# define _LIBUNWIND_CURSOR_SIZE 179 +# define _LIBUNWIND_CURSOR_SIZE 204 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 #endif // _LIBUNWIND_IS_NATIVE_ONLY diff --git a/src/native/external/llvm-libunwind/include/libunwind.h b/src/native/external/llvm-libunwind/include/libunwind.h index 1c5320c1aea8b4..7a8fcbcb26745a 100644 --- a/src/native/external/llvm-libunwind/include/libunwind.h +++ b/src/native/external/llvm-libunwind/include/libunwind.h @@ -896,6 +896,9 @@ enum { UNW_MIPS_F29 = 61, UNW_MIPS_F30 = 62, UNW_MIPS_F31 = 63, + // HI,LO have been dropped since r6, we keep them here. + // So, when we add DSP/MSA etc, we can use the same register indexes + // for r6 and pre-r6. UNW_MIPS_HI = 64, UNW_MIPS_LO = 65, }; diff --git a/src/native/external/llvm-libunwind/src/AddressSpace.hpp b/src/native/external/llvm-libunwind/src/AddressSpace.hpp index dff3249bf9bfc5..33f64415298264 100644 --- a/src/native/external/llvm-libunwind/src/AddressSpace.hpp +++ b/src/native/external/llvm-libunwind/src/AddressSpace.hpp @@ -22,6 +22,7 @@ #include "dwarf2.h" #include "EHHeaderParser.hpp" #include "Registers.hpp" +#include "libunwind_ext.h" #ifndef _LIBUNWIND_USE_DLADDR #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX)) @@ -66,6 +67,10 @@ char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, // In 10.7.0 or later, libSystem.dylib implements this function. extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); +namespace libunwind { + bool findDynamicUnwindSections(void *, unw_dynamic_unwind_sections *); +} + #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) // When statically linked on bare-metal, the symbols for the EH table are looked @@ -410,8 +415,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base, cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section_length = phdr->p_memsz; if (EHHeaderParser::decodeEHHdr( - *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, - hdrInfo)) { + *cbdata->addressSpace, eh_frame_hdr_start, + eh_frame_hdr_start + phdr->p_memsz, hdrInfo)) { // .eh_frame_hdr records the start of .eh_frame, but not its size. // Rely on a zero terminator to find the end of the section. cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; @@ -497,6 +502,22 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length; return true; } + + unw_dynamic_unwind_sections dynamicUnwindSectionInfo; + if (findDynamicUnwindSections((void *)targetAddr, + &dynamicUnwindSectionInfo)) { + info.dso_base = dynamicUnwindSectionInfo.dso_base; +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + info.dwarf_section = (uintptr_t)dynamicUnwindSectionInfo.dwarf_section; + info.dwarf_section_length = dynamicUnwindSectionInfo.dwarf_section_length; +#endif + info.compact_unwind_section = + (uintptr_t)dynamicUnwindSectionInfo.compact_unwind_section; + info.compact_unwind_section_length = + dynamicUnwindSectionInfo.compact_unwind_section_length; + return true; + } + #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) info.dso_base = 0; // Bare metal is statically linked, so no need to ask the dynamic loader @@ -614,7 +635,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, info.dwarf_index_section_length = SIZE_MAX; EHHeaderParser::EHHeaderInfo hdrInfo; if (!EHHeaderParser::decodeEHHdr( - *this, info.dwarf_index_section, info.dwarf_index_section_length, + *this, info.dwarf_index_section, + info.dwarf_index_section + info.dwarf_index_section_length, hdrInfo)) { return false; } diff --git a/src/native/external/llvm-libunwind/src/CMakeLists.txt b/src/native/external/llvm-libunwind/src/CMakeLists.txt index df32e53d69e6e8..780430ba70ba60 100644 --- a/src/native/external/llvm-libunwind/src/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/src/CMakeLists.txt @@ -5,11 +5,6 @@ set(LIBUNWIND_CXX_SOURCES Unwind-EHABI.cpp Unwind-seh.cpp ) -if(APPLE) - list(APPEND LIBUNWIND_CXX_SOURCES - Unwind_AppleExtras.cpp - ) -endif() if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") list(APPEND LIBUNWIND_CXX_SOURCES @@ -21,6 +16,7 @@ set(LIBUNWIND_C_SOURCES UnwindLevel1.c UnwindLevel1-gcc-ext.c Unwind-sjlj.c + Unwind-wasm.c ) set_source_files_properties(${LIBUNWIND_C_SOURCES} PROPERTIES @@ -31,15 +27,6 @@ set(LIBUNWIND_ASM_SOURCES UnwindRegistersSave.S ) -# See add_asm_sources() in compiler-rt for explanation of this workaround. -# CMake doesn't work correctly with assembly on AIX. Workaround by compiling -# as C files as well. -if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR - (MINGW AND CMAKE_VERSION VERSION_LESS 3.17) OR - (${CMAKE_SYSTEM_NAME} MATCHES "AIX")) - set_source_files_properties(${LIBUNWIND_ASM_SOURCES} PROPERTIES LANGUAGE C) -endif() - set(LIBUNWIND_HEADERS AddressSpace.hpp assembly.h @@ -79,26 +66,32 @@ set(LIBUNWIND_SOURCES ${LIBUNWIND_ASM_SOURCES}) # Generate library list. -add_library_flags_if(LIBUNWIND_HAS_C_LIB c) -if (LIBUNWIND_USE_COMPILER_RT) - add_library_flags("${LIBUNWIND_BUILTINS_LIBRARY}") +if (CXX_SUPPORTS_NOSTDLIBXX_FLAG) + add_link_flags_if_supported(-nostdlib++) else() - add_library_flags_if(LIBUNWIND_HAS_GCC_S_LIB gcc_s) - add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc) + if (LIBUNWIND_USE_COMPILER_RT) + add_library_flags("${LIBUNWIND_BUILTINS_LIBRARY}") + else() + add_library_flags_if(LIBUNWIND_HAS_GCC_S_LIB gcc_s) + add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc) + endif() + add_library_flags_if(LIBUNWIND_HAS_C_LIB c) +endif() + +if (NOT APPLE) + add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl) +endif() + +if (LIBUNWIND_ENABLE_THREADS AND NOT APPLE) + add_library_flags_if(LIBUNWIND_HAS_PTHREAD_LIB pthread) endif() -add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl) + if (LIBUNWIND_ENABLE_THREADS) - add_library_flags_if(LIBUNWIND_HAS_PTHREAD_LIB pthread) add_compile_flags_if(LIBUNWIND_WEAK_PTHREAD_LIB -DLIBUNWIND_USE_WEAK_PTHREAD=1) endif() # Setup flags. add_link_flags_if(CXX_SUPPORTS_UNWINDLIB_EQ_NONE_FLAG --unwindlib=none) -if (CXX_SUPPORTS_NOSTDLIBXX_FLAG) - add_link_flags_if_supported(-nostdlib++) -else() - add_link_flags_if_supported(-nodefaultlibs) -endif() # MINGW_LIBRARIES is defined in config-ix.cmake add_library_flags_if(MINGW "${MINGW_LIBRARIES}") @@ -121,6 +114,16 @@ if (APPLE) endif () endif () +if (HAIKU) + add_library_flags_if(LIBUNWIND_HAS_ROOT_LIB root) + + add_library_flags_if(LIBUNWIND_HAS_BSD_LIB bsd) + add_compile_flags_if(LIBUNWIND_HAS_BSD_LIB -D_LIBUNWIND_USE_HAIKU_BSD_LIB=1) + + add_compile_flags("-D_DEFAULT_SOURCE") + add_compile_flags("-DPT_GNU_EH_FRAME=PT_EH_FRAME") +endif () + string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}") string(REPLACE ";" " " LIBUNWIND_CXX_FLAGS "${LIBUNWIND_CXX_FLAGS}") string(REPLACE ";" " " LIBUNWIND_C_FLAGS "${LIBUNWIND_C_FLAGS}") @@ -135,18 +138,23 @@ set_property(SOURCE ${LIBUNWIND_C_SOURCES} # ease, but does not rely on C++ at runtime. set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") +include(WarningFlags) + # Build the shared library. add_library(unwind_shared_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) +cxx_add_warning_flags(unwind_shared_objects ${LIBUNWIND_ENABLE_WERROR} ${LIBUNWIND_ENABLE_PEDANTIC}) if(CMAKE_C_COMPILER_ID STREQUAL MSVC) target_compile_options(unwind_shared_objects PRIVATE /GR-) else() target_compile_options(unwind_shared_objects PRIVATE -fno-rtti) endif() target_link_libraries(unwind_shared_objects PRIVATE unwind-headers ${LIBUNWIND_LIBRARIES}) +target_compile_options(unwind_shared_objects PUBLIC "${LIBUNWIND_ADDITIONAL_COMPILE_FLAGS}") +target_link_libraries(unwind_shared_objects PUBLIC "${LIBUNWIND_ADDITIONAL_LIBRARIES}") set_target_properties(unwind_shared_objects PROPERTIES CXX_EXTENSIONS OFF - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}" ) @@ -174,23 +182,29 @@ endif() # Build the static library. add_library(unwind_static_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) +cxx_add_warning_flags(unwind_static_objects ${LIBUNWIND_ENABLE_WERROR} ${LIBUNWIND_ENABLE_PEDANTIC}) if(CMAKE_C_COMPILER_ID STREQUAL MSVC) target_compile_options(unwind_static_objects PRIVATE /GR-) else() target_compile_options(unwind_static_objects PRIVATE -fno-rtti) endif() target_link_libraries(unwind_static_objects PRIVATE unwind-headers ${LIBUNWIND_LIBRARIES}) +target_compile_options(unwind_static_objects PUBLIC "${LIBUNWIND_ADDITIONAL_COMPILE_FLAGS}") +target_link_libraries(unwind_static_objects PUBLIC "${LIBUNWIND_ADDITIONAL_LIBRARIES}") set_target_properties(unwind_static_objects PROPERTIES CXX_EXTENSIONS OFF - CXX_STANDARD 11 + CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}" ) if(LIBUNWIND_HIDE_SYMBOLS) target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility=hidden) - target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + endif() target_compile_definitions(unwind_static_objects PRIVATE _LIBUNWIND_HIDE_SYMBOLS) endif() diff --git a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp index d242a549e5b47d..a4e75755e5b4d2 100644 --- a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp @@ -69,7 +69,7 @@ class DwarfInstructions { return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + prolog.cfaRegisterOffset); if (prolog.cfaExpression != 0) - return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, + return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, registers, 0); assert(0 && "getCFA(): unknown location"); __builtin_unreachable(); diff --git a/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp b/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp index ed4317c89055c9..0662a1321e2c75 100644 --- a/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp +++ b/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp @@ -55,6 +55,19 @@ template bool EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { pint_t p = ehHdrStart; + + // Ensure that we don't read data beyond the end of .eh_frame_hdr + if (ehHdrEnd - ehHdrStart < 4) { + // Don't print a message for an empty .eh_frame_hdr (this can happen if + // the linker script defines symbols for it even in the empty case). + if (ehHdrEnd == ehHdrStart) + return false; + _LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64 + ": need at least 4 bytes of data but only got %zd", + static_cast(ehHdrStart), + static_cast(ehHdrEnd - ehHdrStart)); + return false; + } uint8_t version = addressSpace.get8(p++); if (version != 1) { _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64, diff --git a/src/native/external/llvm-libunwind/src/FrameHeaderCache.hpp b/src/native/external/llvm-libunwind/src/FrameHeaderCache.hpp index 54d5d33c3cd7ed..296064d8e2e675 100644 --- a/src/native/external/llvm-libunwind/src/FrameHeaderCache.hpp +++ b/src/native/external/llvm-libunwind/src/FrameHeaderCache.hpp @@ -31,8 +31,8 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache { struct CacheEntry { - uintptr_t LowPC() { return Info.dso_base; }; - uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }; + uintptr_t LowPC() { return Info.dso_base; } + uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; } UnwindInfoSections Info; CacheEntry *Next; }; @@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache { // Can't depend on the C++ standard library in libunwind, so use an array to // allocate the entries, and two linked lists for ordering unused and recently - // used entries. FIXME: Would the the extra memory for a doubly-linked list + // used entries. FIXME: Would the extra memory for a doubly-linked list // be better than the runtime cost of traversing a very short singly-linked // list on a cache miss? The entries themselves are all small and consecutive, // so unlikely to cause page faults when following the pointers. The memory diff --git a/src/native/external/llvm-libunwind/src/Registers.hpp b/src/native/external/llvm-libunwind/src/Registers.hpp index 4a0c8d83bb40c7..4e1d75519ef35d 100644 --- a/src/native/external/llvm-libunwind/src/Registers.hpp +++ b/src/native/external/llvm-libunwind/src/Registers.hpp @@ -753,6 +753,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc { void setIP(uint32_t value) { _registers.__srr0 = value; } uint64_t getCR() const { return _registers.__cr; } void setCR(uint32_t value) { _registers.__cr = value; } + uint64_t getLR() const { return _registers.__lr; } + void setLR(uint32_t value) { _registers.__lr = value; } private: struct ppc_thread_state_t { @@ -1324,6 +1326,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc64 { void setIP(uint64_t value) { _registers.__srr0 = value; } uint64_t getCR() const { return _registers.__cr; } void setCR(uint64_t value) { _registers.__cr = value; } + uint64_t getLR() const { return _registers.__lr; } + void setLR(uint64_t value) { _registers.__lr = value; } private: struct ppc64_thread_state_t { @@ -3070,7 +3074,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const { return false; if (regNum <= UNW_MIPS_R31) return true; -#if __mips_isa_rev != 6 +#if __mips_isa_rev < 6 if (regNum == UNW_MIPS_HI) return true; if (regNum == UNW_MIPS_LO) @@ -3104,10 +3108,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const { return _registers.__pc; case UNW_REG_SP: return _registers.__r[29]; +#if __mips_isa_rev < 6 case UNW_MIPS_HI: return _registers.__hi; case UNW_MIPS_LO: return _registers.__lo; +#endif } _LIBUNWIND_ABORT("unsupported mips_o32 register"); } @@ -3137,11 +3143,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { case UNW_REG_SP: _registers.__r[29] = value; return; +#if __mips_isa_rev < 6 case UNW_MIPS_HI: _registers.__hi = value; return; case UNW_MIPS_LO: _registers.__lo = value; +#endif return; } _LIBUNWIND_ABORT("unsupported mips_o32 register"); @@ -3321,10 +3329,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) { return "$f30"; case UNW_MIPS_F31: return "$f31"; +#if __mips_isa_rev < 6 case UNW_MIPS_HI: return "$hi"; case UNW_MIPS_LO: return "$lo"; +#endif default: return "unknown register"; } @@ -3394,7 +3404,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const { return false; if (regNum <= UNW_MIPS_R31) return true; -#if __mips_isa_rev != 6 +#if __mips_isa_rev < 6 if (regNum == UNW_MIPS_HI) return true; if (regNum == UNW_MIPS_LO) @@ -3413,10 +3423,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const { return _registers.__pc; case UNW_REG_SP: return _registers.__r[29]; +#if __mips_isa_rev < 6 case UNW_MIPS_HI: return _registers.__hi; case UNW_MIPS_LO: return _registers.__lo; +#endif } _LIBUNWIND_ABORT("unsupported mips_newabi register"); } @@ -3434,12 +3446,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) { case UNW_REG_SP: _registers.__r[29] = value; return; +#if __mips_isa_rev < 6 case UNW_MIPS_HI: _registers.__hi = value; return; case UNW_MIPS_LO: _registers.__lo = value; return; +#endif } _LIBUNWIND_ABORT("unsupported mips_newabi register"); } @@ -3618,10 +3632,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) { return "$f30"; case UNW_MIPS_F31: return "$f31"; +#if __mips_isa_rev < 6 case UNW_MIPS_HI: return "$hi"; case UNW_MIPS_LO: return "$lo"; +#endif default: return "unknown register"; } diff --git a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp index 63d01aaf9cef4e..338c853bca780e 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp @@ -709,7 +709,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, // Update info about this frame. unw_proc_info_t frameInfo; if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info " "failed => _URC_END_OF_STACK", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; @@ -885,8 +885,11 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { return result; } -static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, - void* valuep) { +// Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are +// disabled. +[[gnu::unused]] static uint64_t +ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, + const void *valuep) { uint64_t value = 0; switch (representation) { case _UVRSD_UINT32: diff --git a/src/native/external/llvm-libunwind/src/Unwind-seh.cpp b/src/native/external/llvm-libunwind/src/Unwind-seh.cpp index d08c29c21383b1..b2bb119ed6d299 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-seh.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-seh.cpp @@ -212,11 +212,20 @@ __libunwind_seh_personality(int version, _Unwind_Action state, ms_exc.ExceptionInformation[2] = state; DISPATCHER_CONTEXT *disp_ctx = __unw_seh_get_disp_ctx((unw_cursor_t *)context); + _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling " + "LanguageHandler %p(%p, %p, %p, %p)", + (void *)disp_ctx->LanguageHandler, (void *)&ms_exc, + (void *)disp_ctx->EstablisherFrame, + (void *)disp_ctx->ContextRecord, (void *)disp_ctx); EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc, (PVOID)disp_ctx->EstablisherFrame, disp_ctx->ContextRecord, disp_ctx); + _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler " + "returned %d", + (int)ms_act); switch (ms_act) { + case ExceptionContinueExecution: return _URC_END_OF_STACK; case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND; case 4 /*ExceptionExecuteHandler*/: return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND; @@ -238,7 +247,7 @@ unwind_phase2_forced(unw_context_t *uc, // Update info about this frame. unw_proc_info_t frameInfo; if (__unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info " "failed => _URC_END_OF_STACK", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; @@ -304,6 +313,12 @@ unwind_phase2_forced(unw_context_t *uc, // We may get control back if landing pad calls _Unwind_Resume(). __unw_resume(&cursor2); break; + case _URC_END_OF_STACK: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_END_OF_STACK", + (void *)exception_object); + break; default: // Personality routine returned an unknown result code. _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " @@ -312,6 +327,8 @@ unwind_phase2_forced(unw_context_t *uc, (void *)exception_object, personalityResult); return _URC_FATAL_PHASE2_ERROR; } + if (personalityResult == _URC_END_OF_STACK) + break; } } diff --git a/src/native/external/llvm-libunwind/src/Unwind-sjlj.c b/src/native/external/llvm-libunwind/src/Unwind-sjlj.c index 90a55fd29db1fa..7e8faf098fe14b 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-sjlj.c +++ b/src/native/external/llvm-libunwind/src/Unwind-sjlj.c @@ -82,7 +82,8 @@ struct _Unwind_FunctionContext { static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; #endif -static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() { +static struct _Unwind_FunctionContext * +__Unwind_SjLj_GetTopOfFunctionStack(void) { #if defined(__APPLE__) return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key); #else @@ -426,7 +427,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, /// Called by personality handler during phase 2 to alter register values. _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIxPTR ")", (void *)context, index, new_value); _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; @@ -437,7 +438,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, /// Called by personality handler during phase 2 to get instruction pointer. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32, + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, (void *)context, ufc->resumeLocation + 1); return ufc->resumeLocation + 1; } @@ -450,7 +451,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *ipBefore) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; *ipBefore = 0; - _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32, + _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIxPTR, (void *)context, (void *)ipBefore, ufc->resumeLocation + 1); return ufc->resumeLocation + 1; @@ -460,7 +461,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, /// Called by personality handler during phase 2 to alter instruction pointer. _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")", + _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIxPTR ")", (void *)context, new_value); _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; ufc->resumeLocation = new_value - 1; diff --git a/src/native/external/llvm-libunwind/src/Unwind-wasm.c b/src/native/external/llvm-libunwind/src/Unwind-wasm.c new file mode 100644 index 00000000000000..f7f39d38b59c18 --- /dev/null +++ b/src/native/external/llvm-libunwind/src/Unwind-wasm.c @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// +// Implements Wasm exception handling proposal +// (https://github.com/WebAssembly/exception-handling) based C++ exceptions +// +//===----------------------------------------------------------------------===// + +#include + +#include "config.h" + +#ifdef __USING_WASM_EXCEPTIONS__ + +#include "unwind.h" +#include + +_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions, + uint64_t exceptionClass, + _Unwind_Exception *unwind_exception, + _Unwind_Context *context); + +struct _Unwind_LandingPadContext { + // Input information to personality function + uintptr_t lpad_index; // landing pad index + uintptr_t lsda; // LSDA address + + // Output information computed by personality function + uintptr_t selector; // selector value +}; + +// Communication channel between compiler-generated user code and personality +// function +thread_local struct _Unwind_LandingPadContext __wasm_lpad_context; + +/// Calls to this function is in landing pads in compiler-generated user code. +/// In other EH schemes, stack unwinding is done by libunwind library, which +/// calls the personality function for each each frame it lands. On the other +/// hand, WebAssembly stack unwinding process is performed by a VM, and the +/// personality function cannot be called from there. So the compiler inserts +/// a call to this function in landing pads in the user code, which in turn +/// calls the personality function. +_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { + struct _Unwind_Exception *exception_object = + (struct _Unwind_Exception *)exception_ptr; + _LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)", + (void *)exception_object); + + // Reset the selector. + __wasm_lpad_context.selector = 0; + + // Call personality function. Wasm does not have two-phase unwinding, so we + // only do the cleanup phase. + return __gxx_personality_wasm0( + 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)&__wasm_lpad_context); +} + +/// Called by __cxa_throw. +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_RaiseException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)", + (void *)exception_object); + // Use Wasm EH's 'throw' instruction. + __builtin_wasm_throw(0, exception_object); +} + +/// Called by __cxa_end_catch. +_LIBUNWIND_EXPORT void +_Unwind_DeleteException(_Unwind_Exception *exception_object) { + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", + (void *)(exception_object)); + if (exception_object->exception_cleanup != NULL) + (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, + exception_object); +} + +/// Called by personality handler to alter register values. +_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t value) { + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)", + (void *)context, index, value); + // We only use this function to set __wasm_lpad_context.selector field, which + // is index 1 in the personality function. + if (index == 1) + ((struct _Unwind_LandingPadContext *)context)->selector = value; +} + +/// Called by personality handler to get instruction pointer. +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { + // The result will be used as an 1-based index after decrementing 1, so we + // increment 2 here + uintptr_t result = + ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2; + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context, + result); + return result; +} + +/// Not used in Wasm. +_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, + uintptr_t value) {} + +/// Called by personality handler to get LSDA for current frame. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { + uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda; + _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx", + (void *)context, result); + return result; +} + +/// Not used in Wasm. +_LIBUNWIND_EXPORT uintptr_t +_Unwind_GetRegionStart(struct _Unwind_Context *context) { + return 0; +} + +#endif // defined(__USING_WASM_EXCEPTIONS__) diff --git a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp index 67f4d16ef14d32..606ba0b0a8d31b 100644 --- a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp +++ b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp @@ -31,7 +31,10 @@ #endif #if defined(_LIBUNWIND_TARGET_LINUX) && \ - (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X)) + (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \ + defined(_LIBUNWIND_TARGET_S390X)) +#include +#include #include #include #include @@ -509,7 +512,14 @@ class UnwindCursor : public AbstractUnwindCursor { #endif DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; } - void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } + void setDispatcherContext(DISPATCHER_CONTEXT *disp) { + _dispContext = *disp; + _info.lsda = reinterpret_cast(_dispContext.HandlerData); + if (_dispContext.LanguageHandler) { + _info.handler = reinterpret_cast(__libunwind_seh_personality); + } else + _info.handler = 0; + } // libunwind does not and should not depend on C++ library which means that we // need our own definition of inline placement new. @@ -571,10 +581,12 @@ UnwindCursor::UnwindCursor(unw_context_t *context, A &as) "UnwindCursor<> requires more alignment than unw_cursor_t"); memset(&_info, 0, sizeof(_info)); memset(&_histTable, 0, sizeof(_histTable)); + memset(&_dispContext, 0, sizeof(_dispContext)); _dispContext.ContextRecord = &_msContext; _dispContext.HistoryTable = &_histTable; // Initialize MS context from ours. R r(context); + RtlCaptureContext(&_msContext); _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT; #if defined(_LIBUNWIND_TARGET_X86_64) _msContext.Rax = r.getRegister(UNW_X86_64_RAX); @@ -672,6 +684,7 @@ UnwindCursor::UnwindCursor(CONTEXT *context, A &as) "UnwindCursor<> does not fit in unw_cursor_t"); memset(&_info, 0, sizeof(_info)); memset(&_histTable, 0, sizeof(_histTable)); + memset(&_dispContext, 0, sizeof(_dispContext)); _dispContext.ContextRecord = &_msContext; _dispContext.HistoryTable = &_histTable; _msContext = *context; @@ -682,7 +695,7 @@ template bool UnwindCursor::validReg(int regNum) { if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true; #if defined(_LIBUNWIND_TARGET_X86_64) - if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true; + if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true; #elif defined(_LIBUNWIND_TARGET_ARM) if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) || regNum == UNW_ARM_RA_AUTH_CODE) @@ -697,6 +710,7 @@ template unw_word_t UnwindCursor::getReg(int regNum) { switch (regNum) { #if defined(_LIBUNWIND_TARGET_X86_64) + case UNW_X86_64_RIP: case UNW_REG_IP: return _msContext.Rip; case UNW_X86_64_RAX: return _msContext.Rax; case UNW_X86_64_RDX: return _msContext.Rdx; @@ -747,6 +761,7 @@ template void UnwindCursor::setReg(int regNum, unw_word_t value) { switch (regNum) { #if defined(_LIBUNWIND_TARGET_X86_64) + case UNW_X86_64_RIP: case UNW_REG_IP: _msContext.Rip = value; break; case UNW_X86_64_RAX: _msContext.Rax = value; break; case UNW_X86_64_RDX: _msContext.Rdx = value; break; @@ -983,10 +998,15 @@ class UnwindCursor : public AbstractUnwindCursor{ R dummy; return stepThroughSigReturn(dummy); } + bool isReadableAddr(const pint_t addr) const; #if defined(_LIBUNWIND_TARGET_AARCH64) bool setInfoForSigReturn(Registers_arm64 &); int stepThroughSigReturn(Registers_arm64 &); #endif +#if defined(_LIBUNWIND_TARGET_RISCV) + bool setInfoForSigReturn(Registers_riscv &); + int stepThroughSigReturn(Registers_riscv &); +#endif #if defined(_LIBUNWIND_TARGET_S390X) bool setInfoForSigReturn(Registers_s390x &); int stepThroughSigReturn(Registers_s390x &); @@ -2003,6 +2023,9 @@ bool UnwindCursor::getInfoFromSEH(pint_t pc) { uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1; const uint32_t *handler = reinterpret_cast(&xdata->UnwindCodes[lastcode]); _info.lsda = reinterpret_cast(handler+1); + _dispContext.HandlerData = reinterpret_cast(_info.lsda); + _dispContext.LanguageHandler = + reinterpret_cast(base + *handler); if (*handler) { _info.handler = reinterpret_cast(__libunwind_seh_personality); } else @@ -2306,27 +2329,39 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) { functionName = ".anonymous."; } - _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p", - __func__, functionName, - reinterpret_cast(TBTable)); + _LIBUNWIND_TRACE_UNWINDING( + "%s: Look up traceback table of func=%s at %p, pc=%p, " + "SP=%p, saves_lr=%d, stores_bc=%d", + __func__, functionName, reinterpret_cast(TBTable), + reinterpret_cast(pc), + reinterpret_cast(registers.getSP()), TBTable->tb.saves_lr, + TBTable->tb.stores_bc); } #if defined(__powerpc64__) - // Instruction to reload TOC register "l r2,40(r1)" + // Instruction to reload TOC register "ld r2,40(r1)" const uint32_t loadTOCRegInst = 0xe8410028; const int32_t unwPPCF0Index = UNW_PPC64_F0; const int32_t unwPPCV0Index = UNW_PPC64_V0; #else - // Instruction to reload TOC register "l r2,20(r1)" + // Instruction to reload TOC register "lwz r2,20(r1)" const uint32_t loadTOCRegInst = 0x80410014; const int32_t unwPPCF0Index = UNW_PPC_F0; const int32_t unwPPCV0Index = UNW_PPC_V0; #endif + // lastStack points to the stack frame of the next routine up. + pint_t curStack = static_cast(registers.getSP()); + pint_t lastStack = *reinterpret_cast(curStack); + + if (lastStack == 0) + return UNW_STEP_END; + R newRegisters = registers; - // lastStack points to the stack frame of the next routine up. - pint_t lastStack = *(reinterpret_cast(registers.getSP())); + // If backchain is not stored, use the current stack frame. + if (!TBTable->tb.stores_bc) + lastStack = curStack; // Return address is the address after call site instruction. pint_t returnAddress; @@ -2336,33 +2371,41 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, reinterpret_cast(lastStack)); sigcontext *sigContext = reinterpret_cast( - reinterpret_cast(lastStack) + STKMIN); + reinterpret_cast(lastStack) + STKMINALIGN); returnAddress = sigContext->sc_jmpbuf.jmp_context.iar; - _LIBUNWIND_TRACE_UNWINDING("From sigContext=%p, returnAddress=%p\n", - reinterpret_cast(sigContext), - reinterpret_cast(returnAddress)); - + bool useSTKMIN = false; if (returnAddress < 0x10000000) { - // Try again using STKMINALIGN + // Try again using STKMIN. sigContext = reinterpret_cast( - reinterpret_cast(lastStack) + STKMINALIGN); + reinterpret_cast(lastStack) + STKMIN); returnAddress = sigContext->sc_jmpbuf.jmp_context.iar; if (returnAddress < 0x10000000) { - _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p\n", - reinterpret_cast(returnAddress)); + _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p", + reinterpret_cast(returnAddress), + reinterpret_cast(sigContext)); return UNW_EBADFRAME; - } else { - _LIBUNWIND_TRACE_UNWINDING("Tried again using STKMINALIGN: " - "sigContext=%p, returnAddress=%p. " - "Seems to be a valid address\n", - reinterpret_cast(sigContext), - reinterpret_cast(returnAddress)); } + useSTKMIN = true; } + _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: " + "sigContext=%p, returnAddress=%p. " + "Seems to be a valid address", + useSTKMIN ? "STKMIN" : "STKMINALIGN", + reinterpret_cast(sigContext), + reinterpret_cast(returnAddress)); + // Restore the condition register from sigcontext. newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr); + // Save the LR in sigcontext for stepping up when the function that + // raised the signal is a leaf function. This LR has the return address + // to the caller of the leaf function. + newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr); + _LIBUNWIND_TRACE_UNWINDING( + "Save LR=%p from sigcontext", + reinterpret_cast(sigContext->sc_jmpbuf.jmp_context.lr)); + // Restore GPRs from sigcontext. for (int i = 0; i < 32; ++i) newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]); @@ -2385,13 +2428,26 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, } } else { // Step up a normal frame. - returnAddress = reinterpret_cast(lastStack)[2]; - _LIBUNWIND_TRACE_UNWINDING("Extract info from lastStack=%p, " - "returnAddress=%p\n", - reinterpret_cast(lastStack), - reinterpret_cast(returnAddress)); - _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d\n", + if (!TBTable->tb.saves_lr && registers.getLR()) { + // This case should only occur if we were called from a signal handler + // and the signal occurred in a function that doesn't save the LR. + returnAddress = static_cast(registers.getLR()); + _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p", + reinterpret_cast(returnAddress)); + } else { + // Otherwise, use the LR value in the stack link area. + returnAddress = reinterpret_cast(lastStack)[2]; + } + + // Reset LR in the current context. + newRegisters.setLR(NULL); + + _LIBUNWIND_TRACE_UNWINDING( + "Extract info from lastStack=%p, returnAddress=%p", + reinterpret_cast(lastStack), + reinterpret_cast(returnAddress)); + _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d", TBTable->tb.fpr_saved, TBTable->tb.gpr_saved, TBTable->tb.saves_cr); @@ -2455,7 +2511,7 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, struct vec_ext *vec_ext = reinterpret_cast(charPtr); - _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d\n", vec_ext->vr_saved); + _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved); // Restore vector register(s) if saved on the stack. if (vec_ext->vr_saved) { @@ -2485,11 +2541,11 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, // Do we need to set the TOC register? _LIBUNWIND_TRACE_UNWINDING( - "Current gpr2=%p\n", + "Current gpr2=%p", reinterpret_cast(newRegisters.getRegister(2))); if (firstInstruction == loadTOCRegInst) { _LIBUNWIND_TRACE_UNWINDING( - "Set gpr2=%p from frame\n", + "Set gpr2=%p from frame", reinterpret_cast(reinterpret_cast(lastStack)[5])); newRegisters.setRegister(2, reinterpret_cast(lastStack)[5]); } @@ -2521,7 +2577,6 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, } else { isSignalFrame = false; } - return UNW_STEP_SUCCESS; } #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) @@ -2673,20 +2728,12 @@ bool UnwindCursor::setInfoForSigReturn(Registers_arm64 &) { // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); // The PC might contain an invalid address if the unwind info is bad, so - // directly accessing it could cause a segfault. Use process_vm_readv to read - // the memory safely instead. process_vm_readv was added in Linux 3.2, and - // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to - // be present. Unfortunately, there are Linux AArch64 environments where the - // libc wrapper for the syscall might not be present (e.g. Android 5), so call - // the syscall directly instead. - uint32_t instructions[2]; - struct iovec local_iov = {&instructions, sizeof instructions}; - struct iovec remote_iov = {reinterpret_cast(pc), sizeof instructions}; - long bytesRead = - syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0); + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + auto *instructions = reinterpret_cast(pc); // Look for instructions: mov x8, #0x8b; svc #0x0 - if (bytesRead != sizeof instructions || instructions[0] != 0xd2801168 || - instructions[1] != 0xd4000001) + if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001) return false; _info = {}; @@ -2730,6 +2777,59 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) { #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && // defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ + defined(_LIBUNWIND_TARGET_RISCV) +template +bool UnwindCursor::setInfoForSigReturn(Registers_riscv &) { + const pint_t pc = static_cast(getReg(UNW_REG_IP)); + // The PC might contain an invalid address if the unwind info is bad, so + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + const auto *instructions = reinterpret_cast(pc); + // Look for the two instructions used in the sigreturn trampoline + // __vdso_rt_sigreturn: + // + // 0x08b00893 li a7,0x8b + // 0x00000073 ecall + if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073) + return false; + + _info = {}; + _info.start_ip = pc; + _info.end_ip = pc + 4; + _isSigReturn = true; + return true; +} + +template +int UnwindCursor::stepThroughSigReturn(Registers_riscv &) { + // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: + // - 128-byte siginfo struct + // - ucontext_t struct: + // - 8-byte long (__uc_flags) + // - 8-byte pointer (*uc_link) + // - 24-byte uc_stack + // - 8-byte uc_sigmask + // - 120-byte of padding to allow sigset_t to be expanded in the future + // - 8 bytes of padding because sigcontext has 16-byte alignment + // - struct sigcontext uc_mcontext + // [1] + // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c + const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128; + + const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext; + _registers.setIP(_addressSpace.get64(sigctx)); + for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) { + uint64_t value = _addressSpace.get64(sigctx + static_cast(i * 8)); + _registers.setRegister(i, value); + } + _isSignalFrame = true; + return UNW_STEP_SUCCESS; +} +#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && + // defined(_LIBUNWIND_TARGET_RISCV) + #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ defined(_LIBUNWIND_TARGET_S390X) template @@ -2741,13 +2841,11 @@ bool UnwindCursor::setInfoForSigReturn(Registers_s390x &) { // onto the stack. const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); // The PC might contain an invalid address if the unwind info is bad, so - // directly accessing it could cause a segfault. Use process_vm_readv to - // read the memory safely instead. - uint16_t inst; - struct iovec local_iov = {&inst, sizeof inst}; - struct iovec remote_iov = {reinterpret_cast(pc), sizeof inst}; - long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0); - if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) { + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + const auto inst = *reinterpret_cast(pc); + if (inst == 0x0a77 || inst == 0x0aad) { _info = {}; _info.start_ip = pc; _info.end_ip = pc + 2; @@ -2893,6 +2991,37 @@ bool UnwindCursor::getFunctionName(char *buf, size_t bufLen, buf, bufLen, offset); } +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +template +bool UnwindCursor::isReadableAddr(const pint_t addr) const { + // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable. + + const auto sigsetAddr = reinterpret_cast(addr); + // We have to check that addr is nullptr because sigprocmask allows that + // as an argument without failure. + if (!sigsetAddr) + return false; + const auto saveErrno = errno; + // We MUST use a raw syscall here, as wrappers may try to access + // sigsetAddr which may cause a SIGSEGV. A raw syscall however is + // safe. Additionally, we need to pass the kernel_sigset_size, which is + // different from libc sizeof(sigset_t). For the majority of architectures, + // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1. + const auto kernelSigsetSize = NSIG / 8; + [[maybe_unused]] const int Result = syscall( + SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize); + // Because our "how" is invalid, this syscall should always fail, and our + // errno should always be EINVAL or an EFAULT. This relies on the Linux + // kernel to check copy_from_user before checking if the "how" argument is + // invalid. + assert(Result == -1); + assert(errno == EFAULT || errno == EINVAL); + const auto readable = errno != EFAULT; + errno = saveErrno; + return readable; +} +#endif + #if defined(_LIBUNWIND_USE_CET) extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; diff --git a/src/native/external/llvm-libunwind/src/UnwindLevel1-gcc-ext.c b/src/native/external/llvm-libunwind/src/UnwindLevel1-gcc-ext.c index efb872bbe59eb2..32c872ffade1fd 100644 --- a/src/native/external/llvm-libunwind/src/UnwindLevel1-gcc-ext.c +++ b/src/native/external/llvm-libunwind/src/UnwindLevel1-gcc-ext.c @@ -143,7 +143,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { // Create a mock exception object for force unwinding. _Unwind_Exception ex; memset(&ex, '\0', sizeof(ex)); - strcpy((char *)&ex.exception_class, "CLNGUNW"); + memcpy(&ex.exception_class, "CLNGUNW", sizeof(ex.exception_class)); #endif // walk each frame @@ -167,7 +167,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { } // Update the pr_cache in the mock exception object. - const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info; + uint32_t *unwindInfo = (uint32_t *)frameInfo.unwind_info; ex.pr_cache.fnstart = frameInfo.start_ip; ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; ex.pr_cache.additional= frameInfo.flags; diff --git a/src/native/external/llvm-libunwind/src/UnwindLevel1.c b/src/native/external/llvm-libunwind/src/UnwindLevel1.c index 7e9adf64246dff..05d0f2cb0a0a7a 100644 --- a/src/native/external/llvm-libunwind/src/UnwindLevel1.c +++ b/src/native/external/llvm-libunwind/src/UnwindLevel1.c @@ -321,7 +321,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, unw_proc_info_t frameInfo; if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_obj=%p): __unw_step_stage2 " + "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info " "failed => _URC_END_OF_STACK", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; diff --git a/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S b/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S index 5d9607ad798dd2..60cb3bfbba0826 100644 --- a/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S +++ b/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S @@ -988,11 +988,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) ldc1 $f31, (4 * 36 + 8 * 31)($4) #endif #endif +#if __mips_isa_rev < 6 // restore hi and lo lw $8, (4 * 33)($4) mthi $8 lw $8, (4 * 34)($4) mtlo $8 +#endif // r0 is zero lw $1, (4 * 1)($4) lw $2, (4 * 2)($4) @@ -1049,11 +1051,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) ldc1 $f\i, (280+8*\i)($4) .endr #endif +#if __mips_isa_rev < 6 // restore hi and lo ld $8, (8 * 33)($4) mthi $8 ld $8, (8 * 34)($4) mtlo $8 +#endif // r0 is zero ld $1, (8 * 1)($4) ld $2, (8 * 2)($4) diff --git a/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S b/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S index 79f5696a9888f5..19a0e87d683cee 100644 --- a/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S +++ b/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S @@ -174,11 +174,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) sw $31, (4 * 31)($4) # Store return address to pc sw $31, (4 * 32)($4) +#if __mips_isa_rev < 6 # hi and lo mfhi $8 sw $8, (4 * 33)($4) mflo $8 sw $8, (4 * 34)($4) +#endif #ifdef __mips_hard_float #if __mips_fpr != 64 sdc1 $f0, (4 * 36 + 8 * 0)($4) @@ -255,11 +257,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .endr # Store return address to pc sd $31, (8 * 32)($4) +#if __mips_isa_rev < 6 # hi and lo mfhi $8 sd $8, (8 * 33)($4) mflo $8 sd $8, (8 * 34)($4) +#endif #ifdef __mips_hard_float .irp i,FROM_0_TO_31 sdc1 $f\i, (280+8*\i)($4) @@ -301,9 +305,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) mflr 0 std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0 PPC64_STR(1) + PPC64_STR(4) // Save r4 first since it will be used for fixing r2. +#if defined(_AIX) + // The TOC register (r2) was changed by the glue code if unw_getcontext + // is called from a different module. Save the original TOC register + // in the context if this is the case. + mflr 4 + lwz 4, 0(4) // Get the first instruction at the return address. + xoris 0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"? + cmplwi 0, 0x28 + bne 0, LnoR2Fix // No need to fix up r2 if it is not. + ld 2, 40(1) // Use the saved TOC register in the stack. +LnoR2Fix: +#endif PPC64_STR(2) PPC64_STR(3) - PPC64_STR(4) PPC64_STR(5) PPC64_STR(6) PPC64_STR(7) @@ -336,7 +352,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) std 0, PPC64_OFFS_CR(3) mfxer 0 std 0, PPC64_OFFS_XER(3) +#if defined(_AIX) + // LR value saved from the register is not used, initialize it to 0. + li 0, 0 +#else mflr 0 +#endif std 0, PPC64_OFFS_LR(3) mfctr 0 std 0, PPC64_OFFS_CTR(3) @@ -543,9 +564,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) mflr 0 stw 0, 0(3) // store lr as ssr0 stw 1, 12(3) + stw 4, 24(3) // Save r4 first since it will be used for fixing r2. +#if defined(_AIX) + // The TOC register (r2) was changed by the glue code if unw_getcontext + // is called from a different module. Save the original TOC register + // in the context if this is the case. + mflr 4 + lwz 4, 0(4) // Get the instruction at the return address. + xoris 0, 4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"? + cmplwi 0, 0x14 + bne 0, LnoR2Fix // No need to fix up r2 if it is not. + lwz 2, 20(1) // Use the saved TOC register in the stack. +LnoR2Fix: +#endif stw 2, 16(3) stw 3, 20(3) - stw 4, 24(3) stw 5, 28(3) stw 6, 32(3) stw 7, 36(3) @@ -582,6 +615,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) // save CR registers mfcr 0 stw 0, 136(3) +#if defined(_AIX) + // LR value from the register is not used, initialize it to 0. + li 0, 0 + stw 0, 144(3) +#endif // save CTR register mfctr 0 stw 0, 148(3) @@ -742,7 +780,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) @ @ On entry: @ thread_state pointer is in r0 -@ +@ @ Per EHABI #4.7 this only saves the core integer registers. @ EHABI #7.4.5 notes that in general all VRS registers should be restored @ however this is very hard to do for VFP registers because it is unknown diff --git a/src/native/external/llvm-libunwind/src/Unwind_AppleExtras.cpp b/src/native/external/llvm-libunwind/src/Unwind_AppleExtras.cpp deleted file mode 100644 index ffb49a89e54f3f..00000000000000 --- a/src/native/external/llvm-libunwind/src/Unwind_AppleExtras.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// -//===----------------------------------------------------------------------===// - -#include "config.h" - - -// static linker symbols to prevent wrong two level namespace for _Unwind symbols -#if defined(__arm__) - #define NOT_HERE_BEFORE_5_0(sym) \ - extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \ - extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \ - extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\ - __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \ - extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \ - extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \ - extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ - extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp43 = 0; -#elif defined(__aarch64__) - #define NOT_HERE_BEFORE_10_6(sym) - #define NEVER_HERE(sym) -#else - #define NOT_HERE_BEFORE_10_6(sym) \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp5 = 0; - #define NEVER_HERE(sym) \ - extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ - extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \ - extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \ - __attribute__((visibility("default"))) const char sym##_tmp6 = 0; -#endif - - -#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) - -// -// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in -// earlier versions -// -NOT_HERE_BEFORE_10_6(_Unwind_DeleteException) -NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE) -NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind) -NOT_HERE_BEFORE_10_6(_Unwind_GetGR) -NOT_HERE_BEFORE_10_6(_Unwind_GetIP) -NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData) -NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart) -NOT_HERE_BEFORE_10_6(_Unwind_RaiseException) -NOT_HERE_BEFORE_10_6(_Unwind_Resume) -NOT_HERE_BEFORE_10_6(_Unwind_SetGR) -NOT_HERE_BEFORE_10_6(_Unwind_SetIP) -NOT_HERE_BEFORE_10_6(_Unwind_Backtrace) -NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction) -NOT_HERE_BEFORE_10_6(_Unwind_GetCFA) -NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase) -NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase) -NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow) -NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo) -NOT_HERE_BEFORE_10_6(__register_frame) -NOT_HERE_BEFORE_10_6(__deregister_frame) - -// -// symbols in libSystem.dylib for compatibility, but we don't want any new code -// using them -// -NEVER_HERE(__register_frame_info_bases) -NEVER_HERE(__register_frame_info) -NEVER_HERE(__register_frame_info_table_bases) -NEVER_HERE(__register_frame_info_table) -NEVER_HERE(__register_frame_table) -NEVER_HERE(__deregister_frame_info) -NEVER_HERE(__deregister_frame_info_bases) - -#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) - - - - -#if defined(_LIBUNWIND_BUILD_SJLJ_APIS) -// -// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in -// earlier versions -// -NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData) -NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart) -NOT_HERE_BEFORE_5_0(_Unwind_GetIP) -NOT_HERE_BEFORE_5_0(_Unwind_SetGR) -NOT_HERE_BEFORE_5_0(_Unwind_SetIP) -NOT_HERE_BEFORE_5_0(_Unwind_DeleteException) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register) -NOT_HERE_BEFORE_5_0(_Unwind_GetGR) -NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo) -NOT_HERE_BEFORE_5_0(_Unwind_GetCFA) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow) -NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister) - -#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) diff --git a/src/native/external/llvm-libunwind/src/config.h b/src/native/external/llvm-libunwind/src/config.h index 4bbac951624f9e..deb5a4d4d73d46 100644 --- a/src/native/external/llvm-libunwind/src/config.h +++ b/src/native/external/llvm-libunwind/src/config.h @@ -46,6 +46,12 @@ #elif defined(_AIX) // The traceback table at the end of each function is used for unwinding. #define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1 +#elif defined(__HAIKU__) + #if defined(_LIBUNWIND_USE_HAIKU_BSD_LIB) + #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 + #endif + #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 + #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 #else // Assume an ELF system with a dl_iterate_phdr function. #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 @@ -83,7 +89,7 @@ __asm__(".globl " SYMBOL_NAME(aliasname)); \ __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname)) -#elif defined(__ELF__) || defined(_AIX) +#elif defined(__ELF__) || defined(_AIX) || defined(__wasm__) #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ __attribute__((weak, alias(#name))); @@ -108,10 +114,6 @@ #define _LIBUNWIND_BUILD_SJLJ_APIS #endif -#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) -#define _LIBUNWIND_SUPPORT_FRAME_APIS -#endif - #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \ defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \ @@ -125,7 +127,7 @@ #if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \ defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \ defined(_LIBUNWIND_IS_BAREMETAL) -#define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size) +#define _LIBUNWIND_REMEMBER_ALLOC(_size) __builtin_alloca(_size) #define _LIBUNWIND_REMEMBER_FREE(_ptr) \ do { \ } while (0) @@ -162,10 +164,14 @@ #define _LIBUNWIND_LOG0(msg) #define _LIBUNWIND_LOG(msg, ...) #else -#define _LIBUNWIND_LOG0(msg) \ - fprintf(stderr, "libunwind: " msg "\n") -#define _LIBUNWIND_LOG(msg, ...) \ - fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__) +#define _LIBUNWIND_LOG0(msg) do { \ + fprintf(stderr, "libunwind: " msg "\n"); \ + fflush(stderr); \ + } while (0) +#define _LIBUNWIND_LOG(msg, ...) do { \ + fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__); \ + fflush(stderr); \ + } while (0) #endif #if defined(NDEBUG) diff --git a/src/native/external/llvm-libunwind/src/libunwind.cpp b/src/native/external/llvm-libunwind/src/libunwind.cpp index f350655b869fe6..96e4343a2cc67a 100644 --- a/src/native/external/llvm-libunwind/src/libunwind.cpp +++ b/src/native/external/llvm-libunwind/src/libunwind.cpp @@ -26,7 +26,7 @@ #include #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__) #include "AddressSpace.hpp" #include "UnwindCursor.hpp" @@ -339,7 +339,7 @@ void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) { CFI_Parser::CIE_Info cieInfo; CFI_Parser::FDE_Info fdeInfo; auto p = (LocalAddressSpace::pint_t)eh_frame_start; - while (true) { + while (LocalAddressSpace::sThisAddressSpace.get32(p)) { if (CFI_Parser::decodeFDE( LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo, true) == NULL) { @@ -362,9 +362,90 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#endif // !defined(__USING_SJLJ_EXCEPTIONS__) +#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && + // !defined(__USING_WASM_EXCEPTIONS__) +#ifdef __APPLE__ +namespace libunwind { + +static constexpr size_t MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS = 8; + +static RWMutex findDynamicUnwindSectionsLock; +static size_t numDynamicUnwindSectionsFinders = 0; +static unw_find_dynamic_unwind_sections + dynamicUnwindSectionsFinders[MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS] = {0}; + +bool findDynamicUnwindSections(void *addr, unw_dynamic_unwind_sections *info) { + bool found = false; + findDynamicUnwindSectionsLock.lock_shared(); + for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) { + if (dynamicUnwindSectionsFinders[i]((unw_word_t)addr, info)) { + found = true; + break; + } + } + findDynamicUnwindSectionsLock.unlock_shared(); + return found; +} + +} // namespace libunwind + +int __unw_add_find_dynamic_unwind_sections( + unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) { + findDynamicUnwindSectionsLock.lock(); + + // Check that we have enough space... + if (numDynamicUnwindSectionsFinders == MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS) { + findDynamicUnwindSectionsLock.unlock(); + return UNW_ENOMEM; + } + + // Check for value already present... + for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) { + if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) { + findDynamicUnwindSectionsLock.unlock(); + return UNW_EINVAL; + } + } + + // Success -- add callback entry. + dynamicUnwindSectionsFinders[numDynamicUnwindSectionsFinders++] = + find_dynamic_unwind_sections; + findDynamicUnwindSectionsLock.unlock(); + + return UNW_ESUCCESS; +} + +int __unw_remove_find_dynamic_unwind_sections( + unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) { + findDynamicUnwindSectionsLock.lock(); + + // Find index to remove. + size_t finderIdx = numDynamicUnwindSectionsFinders; + for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) { + if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) { + finderIdx = i; + break; + } + } + + // If no such registration is present then error out. + if (finderIdx == numDynamicUnwindSectionsFinders) { + findDynamicUnwindSectionsLock.unlock(); + return UNW_EINVAL; + } + + // Remove entry. + for (size_t i = finderIdx; i != numDynamicUnwindSectionsFinders - 1; ++i) + dynamicUnwindSectionsFinders[i] = dynamicUnwindSectionsFinders[i + 1]; + dynamicUnwindSectionsFinders[--numDynamicUnwindSectionsFinders] = nullptr; + + findDynamicUnwindSectionsLock.unlock(); + return UNW_ESUCCESS; +} + +#endif // __APPLE__ // Add logging hooks in Debug builds only #ifndef NDEBUG diff --git a/src/native/external/llvm-libunwind/src/libunwind_ext.h b/src/native/external/llvm-libunwind/src/libunwind_ext.h index 5385821ce2c129..db55939971264e 100644 --- a/src/native/external/llvm-libunwind/src/libunwind_ext.h +++ b/src/native/external/llvm-libunwind/src/libunwind_ext.h @@ -59,6 +59,71 @@ extern void __unw_remove_dynamic_fde(unw_word_t fde); extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start); extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start); +#ifdef __APPLE__ + +// Holds a description of the object-format-header (if any) and unwind info +// sections for a given address: +// +// * dso_base should point to a header for the JIT'd object containing the +// given address. The header's type should match the format type that +// libunwind was compiled for (so a mach_header or mach_header_64 on Darwin). +// A value of zero indicates that no such header exists. +// +// * dwarf_section and dwarf_section_length hold the address range of a DWARF +// eh-frame section associated with the given address, if any. If the +// dwarf_section_length field is zero it indicates that no such section +// exists (and in this case dwarf_section should also be set to zero). +// +// * compact_unwind_section and compact_unwind_section_length hold the address +// range of a compact-unwind info section associated with the given address, +// if any. If the compact_unwind_section_length field is zero it indicates +// that no such section exists (and in this case compact_unwind_section +// should also be set to zero). +// +// See the unw_find_dynamic_unwind_sections type below for more details. +struct unw_dynamic_unwind_sections { + unw_word_t dso_base; + unw_word_t dwarf_section; + size_t dwarf_section_length; + unw_word_t compact_unwind_section; + size_t compact_unwind_section_length; +}; + +// Typedef for unwind-info lookup callbacks. Functions of this type can be +// registered and deregistered using __unw_add_find_dynamic_unwind_sections +// and __unw_remove_find_dynamic_unwind_sections respectively. +// +// An unwind-info lookup callback should return 1 to indicate that it found +// unwind-info for the given address, or 0 to indicate that it did not find +// unwind-info for the given address. If found, the callback should populate +// some or all of the fields of the info argument (which is guaranteed to be +// non-null with all fields zero-initialized): +typedef int (*unw_find_dynamic_unwind_sections)( + unw_word_t addr, struct unw_dynamic_unwind_sections *info); + +// Register a dynamic unwind-info lookup callback. If libunwind does not find +// unwind info for a given frame in the executable program or normal dynamic +// shared objects then it will call all registered dynamic lookup functions +// in registration order until either one of them returns true, or the end +// of the list is reached. This lookup will happen before libunwind searches +// any eh-frames registered via __register_frame or +// __unw_add_dynamic_eh_frame_section. +// +// Returns UNW_ESUCCESS for successful registrations. If the given callback +// has already been registered then UNW_EINVAL will be returned. If all +// available callback entries are in use then UNW_ENOMEM will be returned. +extern int __unw_add_find_dynamic_unwind_sections( + unw_find_dynamic_unwind_sections find_dynamic_unwind_sections); + +// Deregister a dynacim unwind-info lookup callback. +// +// Returns UNW_ESUCCESS for successful deregistrations. If the given callback +// has already been registered then UNW_EINVAL will be returned. +extern int __unw_remove_find_dynamic_unwind_sections( + unw_find_dynamic_unwind_sections find_dynamic_unwind_sections); + +#endif + #if defined(_LIBUNWIND_ARM_EHABI) extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*); extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context, diff --git a/src/native/external/llvm-libunwind/src/unwind_ext.h b/src/native/external/llvm-libunwind/src/unwind_ext.h deleted file mode 100644 index c40ce6a1610f4f..00000000000000 --- a/src/native/external/llvm-libunwind/src/unwind_ext.h +++ /dev/null @@ -1,37 +0,0 @@ -//===-------------------------- unwind_ext.h ------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Extensions to unwind API. -// -//===----------------------------------------------------------------------===// - -#ifndef __UNWIND_EXT__ -#define __UNWIND_EXT__ - -#include "unwind.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// These platform specific functions to get and set the top context are -// implemented elsewhere. - -extern struct _Unwind_FunctionContext * -__Unwind_SjLj_GetTopOfFunctionStack(); - -extern void -__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc); - -#ifdef __cplusplus -} -#endif - -#endif // __UNWIND_EXT__ - - diff --git a/src/native/external/llvm-libunwind/test/CMakeLists.txt b/src/native/external/llvm-libunwind/test/CMakeLists.txt index 0a09553e692da6..21dfbb0a84f0a8 100644 --- a/src/native/external/llvm-libunwind/test/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/test/CMakeLists.txt @@ -1,4 +1,5 @@ include(AddLLVM) # for add_lit_testsuite +include(HandleLitArguments) macro(pythonize_bool var) if (${var}) set(${var} True) @@ -10,33 +11,28 @@ endmacro() pythonize_bool(LIBUNWIND_ENABLE_CET) pythonize_bool(LIBUNWIND_ENABLE_THREADS) pythonize_bool(LIBUNWIND_USES_ARM_EHABI) -set(LIBUNWIND_EXECUTOR "${Python3_EXECUTABLE} ${LIBUNWIND_LIBCXX_PATH}/utils/run.py" CACHE STRING - "Executor to use when running tests.") set(AUTO_GEN_COMMENT "## Autogenerated by libunwind configuration.\n# Do not edit!") set(SERIALIZED_LIT_PARAMS "# Lit parameters serialized here for llvm-lit to pick them up\n") -macro(serialize_lit_param param value) - string(APPEND SERIALIZED_LIT_PARAMS "config.${param} = ${value}\n") -endmacro() +if (LIBUNWIND_EXECUTOR) + message(DEPRECATION "LIBUNWIND_EXECUTOR is deprecated, please add executor=... to LIBUNWIND_TEST_PARAMS") + serialize_lit_string_param(SERIALIZED_LIT_PARAMS executor "${LIBUNWIND_EXECUTOR}") +endif() -serialize_lit_param(enable_experimental False) +serialize_lit_param(SERIALIZED_LIT_PARAMS enable_experimental False) if (LLVM_USE_SANITIZER) - serialize_lit_param(use_sanitizer "\"${LLVM_USE_SANITIZER}\"") + serialize_lit_string_param(SERIALIZED_LIT_PARAMS use_sanitizer "${LLVM_USE_SANITIZER}") endif() if (CMAKE_CXX_COMPILER_TARGET) - serialize_lit_param(target_triple "\"${CMAKE_CXX_COMPILER_TARGET}\"") + serialize_lit_string_param(SERIALIZED_LIT_PARAMS target_triple "${CMAKE_CXX_COMPILER_TARGET}") else() - serialize_lit_param(target_triple "\"${LLVM_DEFAULT_TARGET_TRIPLE}\"") + serialize_lit_string_param(SERIALIZED_LIT_PARAMS target_triple "${LLVM_DEFAULT_TARGET_TRIPLE}") endif() -foreach(param IN LISTS LIBUNWIND_TEST_PARAMS) - string(REGEX REPLACE "(.+)=(.+)" "\\1" name "${param}") - string(REGEX REPLACE "(.+)=(.+)" "\\2" value "${param}") - serialize_lit_param("${name}" "\"${value}\"") -endforeach() +serialize_lit_params_list(SERIALIZED_LIT_PARAMS LIBUNWIND_TEST_PARAMS) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/configs/cmake-bridge.cfg.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake-bridge.cfg" diff --git a/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S b/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S new file mode 100644 index 00000000000000..9ca18e9481f4fc --- /dev/null +++ b/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S @@ -0,0 +1,245 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Test that _Unwind_Backtrace() walks up from a signal handler and produces +// a correct traceback when the function raising the signal does not save +// the link register or does not store the stack back chain. + +// REQUIRES: target=powerpc{{(64)?}}-ibm-aix + +// Test when the function raising the signal does not save the link register +// RUN: %{cxx} -x c++ %s -o %t.exe -DCXX_CODE %{flags} %{compile_flags} +// RUN: %{exec} %t.exe + +// Test when the function raising the signal does not store stack back chain. +// RUN: %{cxx} -x c++ -c %s -o %t1.o -DCXX_CODE -DNOBACKCHAIN %{flags} \ +// RUN: %{compile_flags} +// RUN: %{cxx} -c %s -o %t2.o %{flags} %{compile_flags} +// RUN: %{cxx} -o %t1.exe %t1.o %t2.o %{flags} %{link_flags} +// RUN: %{exec} %t1.exe + +#ifdef CXX_CODE + +#undef NDEBUG +#include +#include +#include +#include +#include +#include +#include + +#define NAME_ARRAY_SIZE 10 +#define NAMES_EXPECTED 6 + +const char* namesExpected[] = {"handler", "abc", "bar", "foo", "main", + "__start"}; +char *namesObtained[NAME_ARRAY_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +int funcIndex = 0; + +// Get the function name from traceback table. +char *getFuncName(uintptr_t pc, uint16_t *nameLen) { + uint32_t *p = reinterpret_cast(pc); + + // Keep looking forward until a word of 0 is found. The traceback + // table starts at the following word. + while (*p) + ++p; + tbtable *TBTable = reinterpret_cast(p + 1); + + if (!TBTable->tb.name_present) + return NULL; + + // Get to the optional portion of the traceback table. + p = reinterpret_cast(&TBTable->tb_ext); + + // Skip field parminfo if it exists. + if (TBTable->tb.fixedparms || TBTable->tb.floatparms) + ++p; + + // Skip field tb_offset if it exists. + if (TBTable->tb.has_tboff) + ++p; + + // Skip field hand_mask if it exists. + if (TBTable->tb.int_hndl) + ++p; + + // Skip fields ctl_info and ctl_info_disp if they exist. + if (TBTable->tb.has_ctl) + p += 1 + *p; + + *nameLen = *reinterpret_cast(p); + return reinterpret_cast(p) + sizeof(uint16_t); +} + +_Unwind_Reason_Code callBack(struct _Unwind_Context *uc, void *arg) { + (void)arg; + uint16_t nameLen; + uintptr_t ip = _Unwind_GetIP(uc); + if (funcIndex < NAME_ARRAY_SIZE) + namesObtained[funcIndex++] = strndup(getFuncName(ip, &nameLen), nameLen); + return _URC_NO_REASON; +} + +extern "C" void handler(int signum) { + (void)signum; + // Walk stack frames for traceback. + _Unwind_Backtrace(callBack, NULL); + + // Verify the traceback. + assert(funcIndex <= NAMES_EXPECTED && "Obtained names more than expected"); + for (int i = 0; i < funcIndex; ++i) { + assert(!strcmp(namesExpected[i], namesObtained[i]) && + "Function names do not match"); + free(namesObtained[i]); + } + exit(0); +} + +#ifdef NOBACKCHAIN +// abc() is in assembly. It raises signal SIGSEGV and does not store +// the stack back chain. +extern "C" void abc(); + +#else +volatile int *null = 0; + +// abc() raises signal SIGSEGV and does not save the link register. +extern "C" __attribute__((noinline)) void abc() { + // Produce a SIGSEGV. + *null = 0; +} +#endif + +extern "C" __attribute__((noinline)) void bar() { + abc(); +} + +extern "C" __attribute__((noinline)) void foo() { + bar(); +} + +int main() { + // Set signal handler for SIGSEGV. + signal(SIGSEGV, handler); + foo(); +} + +#else // Assembly code for abc(). +// This assembly code is similar to the following C code but it saves the +// link register. +// +// int *badp = 0; +// void abc() { +// *badp = 0; +// } + +#ifdef __64BIT__ + .csect [PR],5 + .file "abc.c" + .globl abc[DS] # -- Begin function abc + .globl .abc + .align 4 + .csect abc[DS],3 + .vbyte 8, .abc # @abc + .vbyte 8, TOC[TC0] + .vbyte 8, 0 + .csect [PR],5 +.abc: +# %bb.0: # %entry + mflr 0 + std 0, 16(1) + ld 3, L..C0(2) # @badp + bl $+4 + ld 4, 0(3) + li 3, 0 + stw 3, 0(4) + ld 0, 16(1) + mtlr 0 + blr +L..abc0: + .vbyte 4, 0x00000000 # Traceback table begin + .byte 0x00 # Version = 0 + .byte 0x09 # Language = CPlusPlus + .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue + # +HasTraceBackTableOffset, -IsInternalProcedure + # -HasControlledStorage, -IsTOCless + # -IsFloatingPointPresent + # -IsFloatingPointOperationLogOrAbortEnabled + .byte 0x61 # -IsInterruptHandler, +IsFunctionNamePresent, +IsAllocaUsed + # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved + .byte 0x00 # -IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 + .byte 0x01 # -HasExtensionTable, -HasVectorInfo, NumOfGPRsSaved = 1 + .byte 0x00 # NumberOfFixedParms = 0 + .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack + .vbyte 4, L..abc0-.abc # Function size + .vbyte 2, 0x0003 # Function name len = 3 + .byte "abc" # Function Name + .byte 0x1f # AllocaUsed + # -- End function + .csect badp[RW],3 + .globl badp[RW] # @badp + .align 3 + .vbyte 8, 0 + .toc +L..C0: + .tc badp[TC],badp[RW] +#else + .csect [PR],5 + .file "abc.c" + .globl abc[DS] # -- Begin function abc + .globl .abc + .align 4 + .csect abc[DS],2 + .vbyte 4, .abc # @abc + .vbyte 4, TOC[TC0] + .vbyte 4, 0 + .csect [PR],5 +.abc: +# %bb.0: # %entry + mflr 0 + stw 0, 8(1) + lwz 3, L..C0(2) # @badp + bl $+4 + lwz 4, 0(3) + li 3, 0 + stw 3, 0(4) + lwz 0, 8(1) + mtlr 0 + blr +L..abc0: + .vbyte 4, 0x00000000 # Traceback table begin + .byte 0x00 # Version = 0 + .byte 0x09 # Language = CPlusPlus + .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue + # +HasTraceBackTableOffset, -IsInternalProcedure + # -HasControlledStorage, -IsTOCless + # -IsFloatingPointPresent + # -IsFloatingPointOperationLogOrAbortEnabled + .byte 0x61 # -IsInterruptHandler, +IsFunctionNamePresent, +IsAllocaUsed + # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved + .byte 0x00 # -IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 + .byte 0x01 # -HasExtensionTable, -HasVectorInfo, NumOfGPRsSaved = 1 + .byte 0x00 # NumberOfFixedParms = 0 + .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack + .vbyte 4, L..abc0-.abc # Function size + .vbyte 2, 0x0003 # Function name len = 3 + .byte "abc" # Function Name + .byte 0x1f # AllocaUsed + # -- End function + .csect badp[RW],2 + .globl badp[RW] # @badp + .align 2 + .vbyte 4, 0 + .toc +L..C0: + .tc badp[TC],badp[RW] +#endif // __64BIT__ +#endif // CXX_CODE diff --git a/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp b/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp index 06017d17ab5744..b3284e8daed71f 100644 --- a/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp +++ b/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp @@ -10,7 +10,7 @@ // Ensure that libunwind doesn't crash on invalid info; the Linux aarch64 // sigreturn frame check would previously attempt to access invalid memory in // this scenario. -// REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}}) +// REQUIRES: target={{(aarch64|s390x|x86_64)-.+linux.*}} // GCC doesn't support __attribute__((naked)) on AArch64. // UNSUPPORTED: gcc diff --git a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in index d4777e2f6917a7..4484573801bd2b 100644 --- a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-backdeployment.cfg.in @@ -7,7 +7,7 @@ import os, site site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) -import libcxx.test.params, libcxx.test.newconfig, libcxx.test.dsl +import libcxx.test.params, libcxx.test.config, libcxx.test.dsl lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') @@ -54,9 +54,11 @@ config.substitutions.append(('%{exec}', '%{executor} --execdir %T --env DYLD_LIBRARY_PATH="%{cxx-runtime-root}:%{abi-runtime-root}:%{unwind-runtime-root}" -- ' )) +config.stdlib = 'apple-libc++' + import os, site -import libcxx.test.params, libcxx.test.newconfig, libcxx.test.newconfig -libcxx.test.newconfig.configure( +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( libcxx.test.params.DEFAULT_PARAMETERS + BACKDEPLOYMENT_PARAMETERS, libcxx.test.features.DEFAULT_FEATURES, config, diff --git a/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in b/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in new file mode 100644 index 00000000000000..e8f68a51fc53f8 --- /dev/null +++ b/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in @@ -0,0 +1,39 @@ +lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') + +libc_linker_script = '@CMAKE_INSTALL_PREFIX@/lib/picolibcpp.ld' + +config.substitutions.append(('%{flags}', '--sysroot=@CMAKE_INSTALL_PREFIX@')) + +config.substitutions.append(('%{compile_flags}', + '-nostdinc++ -I %{include}' +)) +config.substitutions.append(('%{link_flags}', + '-nostdlib -nostdlib++ -L %{lib} -lunwind' + ' -lc -lm -lclang_rt.builtins -lsemihost -lcrt0-semihost' + + ' -T {}'.format(libc_linker_script) + + ' -Wl,--defsym=__flash=0x0' + ' -Wl,--defsym=__flash_size=0x400000' + ' -Wl,--defsym=__ram=0x21000000' + ' -Wl,--defsym=__ram_size=0x1000000' + ' -Wl,--defsym=__stack_size=0x1000' +)) + +config.executor = ( + '@LIBUNWIND_LIBCXX_PATH@/utils/qemu_baremetal.py' + ' --qemu @QEMU_SYSTEM_ARM@' + ' --machine mps2-an385' + ' --cpu cortex-m3') +config.substitutions.append(('%{exec}', + '%{executor}' + ' --execdir %T' +)) + +import os, site +site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( + libcxx.test.params.DEFAULT_PARAMETERS, + libcxx.test.features.DEFAULT_FEATURES, + config, + lit_config +) diff --git a/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in b/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in index 109602db8a0fb6..c5f34c87abb92a 100644 --- a/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in @@ -20,7 +20,7 @@ config.name = os.path.basename('@LIBUNWIND_TEST_CONFIG@') config.test_source_root = os.path.join('@LIBUNWIND_SOURCE_DIR@', 'test') config.test_format = libcxx.test.format.CxxStandardLibraryTest() config.recursiveExpansionLimit = 10 -config.test_exec_root = '@CMAKE_BINARY_DIR@' +config.test_exec_root = os.path.join('@CMAKE_BINARY_DIR@', 'test') # Add a few features that are common to all the configurations if @LIBUNWIND_USES_ARM_EHABI@: @@ -31,6 +31,5 @@ if not @LIBUNWIND_ENABLE_THREADS@: # Add substitutions for bootstrapping the test suite configuration import shlex config.substitutions.append(('%{cxx}', shlex.quote('@CMAKE_CXX_COMPILER@'))) -config.substitutions.append(('%{executor}', '@LIBUNWIND_EXECUTOR@')) config.substitutions.append(('%{include}', '@LIBUNWIND_SOURCE_DIR@/include')) config.substitutions.append(('%{lib}', '@LIBUNWIND_LIBRARY_DIR@')) diff --git a/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in b/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in index 599de72b1399d1..2221e0cf499ff2 100644 --- a/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in @@ -3,6 +3,12 @@ lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') +import lit.util +if lit.util.isAIXTriple(config.target_triple): + # Add the AIX version to the triple here because there currently isn't a good + # way to retrieve the AIX version in the driver. + config.target_triple = lit.util.addAIXVersion(config.target_triple) + config.substitutions.append(('%{flags}', '')) config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{include}' @@ -16,8 +22,8 @@ config.substitutions.append(('%{exec}', import os, site site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) -import libcxx.test.params, libcxx.test.newconfig, libcxx.test.newconfig -libcxx.test.newconfig.configure( +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( libcxx.test.params.DEFAULT_PARAMETERS, libcxx.test.features.DEFAULT_FEATURES, config, diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in index d01ee7470de7bb..38b79840c9fe28 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in @@ -11,8 +11,12 @@ link_flags = [] if @LIBUNWIND_ENABLE_CET@: compile_flags.append('-fcf-protection=full') -if '@CMAKE_SYSTEM_NAME@' == 'Linux': - link_flags.append('-Wl,--export-dynamic') +# On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker. +if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'): + link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@') + +if '@CMAKE_DL_LIBS@': + link_flags.append('-l@CMAKE_DL_LIBS@') # Stack unwinding tests need unwinding tables and these are not generated by default on all targets. compile_flags.append('-funwind-tables') @@ -25,7 +29,7 @@ config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags)) )) config.substitutions.append(('%{link_flags}', - '-L %{{lib}} -Wl,-rpath,%{{lib}} -lc++ -ldl {}'.format(' '.join(link_flags)) + '-L %{{lib}} -Wl,-rpath,%{{lib}} -lc++ {}'.format(' '.join(link_flags)) )) config.substitutions.append(('%{exec}', '%{executor} --execdir %T -- ' @@ -33,8 +37,8 @@ config.substitutions.append(('%{exec}', import os, site site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) -import libcxx.test.params, libcxx.test.newconfig, libcxx.test.newconfig -libcxx.test.newconfig.configure( +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( libcxx.test.params.DEFAULT_PARAMETERS, libcxx.test.features.DEFAULT_FEATURES, config, diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in new file mode 100644 index 00000000000000..33d061a3efc6fc --- /dev/null +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-mingw.cfg.in @@ -0,0 +1,25 @@ +# This testing configuration handles running the test suite against LLVM's libunwind +# using either a DLL or a static library, with MinGW/Clang on Windows. + +lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') + +config.substitutions.append(('%{flags}', '')) +config.substitutions.append(('%{compile_flags}', + '-nostdinc++ -I %{include} -funwind-tables' +)) +config.substitutions.append(('%{link_flags}', + '-L %{lib} -lunwind' +)) +config.substitutions.append(('%{exec}', + '%{executor} --execdir %T --prepend_env PATH=%{lib} -- ' +)) + +import os, site +site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( + libcxx.test.params.DEFAULT_PARAMETERS, + libcxx.test.features.DEFAULT_FEATURES, + config, + lit_config +) diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in index b82eec71b02ff0..13896aeb13bc4a 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in @@ -10,8 +10,12 @@ link_flags = [] if @LIBUNWIND_ENABLE_CET@: compile_flags.append('-fcf-protection=full') -if '@CMAKE_SYSTEM_NAME@' == 'Linux': - link_flags.append('-Wl,--export-dynamic') +# On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker. +if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'): + link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@') + +if '@CMAKE_DL_LIBS@': + link_flags.append('-l@CMAKE_DL_LIBS@') # Stack unwinding tests need unwinding tables and these are not generated by default on all targets. compile_flags.append('-funwind-tables') @@ -24,7 +28,7 @@ config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags)) )) config.substitutions.append(('%{link_flags}', - '-L %{{lib}} -Wl,-rpath,%{{lib}} -lunwind -ldl {}'.format(' '.join(link_flags)) + '-L %{{lib}} -Wl,-rpath,%{{lib}} -lunwind {}'.format(' '.join(link_flags)) )) config.substitutions.append(('%{exec}', '%{executor} --execdir %T -- ' @@ -32,8 +36,8 @@ config.substitutions.append(('%{exec}', import os, site site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) -import libcxx.test.params, libcxx.test.newconfig, libcxx.test.newconfig -libcxx.test.newconfig.configure( +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( libcxx.test.params.DEFAULT_PARAMETERS, libcxx.test.features.DEFAULT_FEATURES, config, diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in index a947a5d08f58bb..50b64dc665a5af 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in @@ -13,8 +13,12 @@ if @LIBUNWIND_ENABLE_THREADS@: if @LIBUNWIND_ENABLE_CET@: compile_flags.append('-fcf-protection=full') -if '@CMAKE_SYSTEM_NAME@' == 'Linux': - link_flags.append('-Wl,--export-dynamic') +# On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker. +if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'): + link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@') + +if '@CMAKE_DL_LIBS@': + link_flags.append('-l@CMAKE_DL_LIBS@') # Stack unwinding tests need unwinding tables and these are not generated by default on all targets. compile_flags.append('-funwind-tables') @@ -27,7 +31,7 @@ config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags)) )) config.substitutions.append(('%{link_flags}', - '%{{lib}}/libunwind.a -ldl {}'.format(' '.join(link_flags)) + '%{{lib}}/libunwind.a {}'.format(' '.join(link_flags)) )) config.substitutions.append(('%{exec}', '%{executor} --execdir %T -- ' @@ -35,8 +39,8 @@ config.substitutions.append(('%{exec}', import os, site site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) -import libcxx.test.params, libcxx.test.newconfig, libcxx.test.newconfig -libcxx.test.newconfig.configure( +import libcxx.test.params, libcxx.test.config +libcxx.test.config.configure( libcxx.test.params.DEFAULT_PARAMETERS, libcxx.test.features.DEFAULT_FEATURES, config, diff --git a/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp b/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp index 8c26551b6d0b67..db499d8bc30894 100644 --- a/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp +++ b/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp @@ -61,7 +61,7 @@ __attribute__((noinline)) void foo() { #if defined(_LIBUNWIND_ARM_EHABI) // Create a mock exception object. memset(e, '\0', sizeof(*e)); - strcpy(reinterpret_cast(&e->exception_class), "CLNGUNW"); + memcpy(&e->exception_class, "CLNGUNW", sizeof(e->exception_class)); #endif _Unwind_ForcedUnwind(e, stop, (void *)&foo); } diff --git a/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp b/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp index 4661ac9df8219e..96f12d1fc39374 100644 --- a/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp +++ b/src/native/external/llvm-libunwind/test/libunwind_01.pass.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // TODO: Investigate this failure on x86_64 macOS back deployment -// XFAIL: use_system_cxx_lib && target=x86_64-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// XFAIL: stdlib=apple-libc++ && target=x86_64-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan diff --git a/src/native/external/llvm-libunwind/test/libunwind_02.pass.cpp b/src/native/external/llvm-libunwind/test/libunwind_02.pass.cpp index fc034378781a2f..9fd8e5d7159c96 100644 --- a/src/native/external/llvm-libunwind/test/libunwind_02.pass.cpp +++ b/src/native/external/llvm-libunwind/test/libunwind_02.pass.cpp @@ -10,6 +10,9 @@ // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan +// This test fails on older llvm, when built with picolibc. +// XFAIL: clang-16 && LIBCXX-PICOLIBC-FIXME + #undef NDEBUG #include #include @@ -18,7 +21,8 @@ #define EXPECTED_NUM_FRAMES 50 #define NUM_FRAMES_UPPER_BOUND 100 -_Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) { +__attribute__((noinline)) _Unwind_Reason_Code callback(_Unwind_Context *context, + void *cnt) { (void)context; int *i = (int *)cnt; ++*i; @@ -28,7 +32,7 @@ _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) { return _URC_NO_REASON; } -void test_backtrace() { +__attribute__((noinline)) void test_backtrace() { int n = 0; _Unwind_Backtrace(&callback, &n); if (n < EXPECTED_NUM_FRAMES) { @@ -36,17 +40,34 @@ void test_backtrace() { } } -int test(int i) { +// These functions are effectively the same, but we have to be careful to avoid +// unwanted optimizations that would mess with the number of frames we expect. +// Surprisingly, slapping `noinline` is not sufficient -- we also have to avoid +// writing the function in a way that the compiler can easily spot tail +// recursion. +__attribute__((noinline)) int test1(int i); +__attribute__((noinline)) int test2(int i); + +__attribute__((noinline)) int test1(int i) { + if (i == 0) { + test_backtrace(); + return 0; + } else { + return i + test2(i - 1); + } +} + +__attribute__((noinline)) int test2(int i) { if (i == 0) { test_backtrace(); return 0; } else { - return i + test(i - 1); + return i + test1(i - 1); } } int main(int, char**) { - int total = test(50); + int total = test1(50); assert(total == 1275); return 0; } diff --git a/src/native/external/llvm-libunwind/test/lit.cfg.py b/src/native/external/llvm-libunwind/test/lit.cfg.py index 647464abe22d9c..ea4a9a75b4fdb8 100644 --- a/src/native/external/llvm-libunwind/test/lit.cfg.py +++ b/src/native/external/llvm-libunwind/test/lit.cfg.py @@ -7,4 +7,5 @@ lit_config.fatal( "You seem to be running Lit directly -- you should be running Lit through " "/bin/llvm-lit, which will ensure that the right Lit configuration " - "file is used.") + "file is used." +) diff --git a/src/native/external/llvm-libunwind/test/signal_frame.pass.cpp b/src/native/external/llvm-libunwind/test/signal_frame.pass.cpp index 482481d9d96bad..004029cfe1e90b 100644 --- a/src/native/external/llvm-libunwind/test/signal_frame.pass.cpp +++ b/src/native/external/llvm-libunwind/test/signal_frame.pass.cpp @@ -19,7 +19,11 @@ // The AIX assembler does not support CFI directives, which // are necessary to run this test. -// UNSUPPORTED: target=powerpc{{(64)?}}-ibm-aix +// UNSUPPORTED: target={{.*}}-aix{{.*}} + +// Windows doesn't generally use CFI directives. However, i686 +// mingw targets do use DWARF (where CFI directives are supported). +// UNSUPPORTED: target={{x86_64|arm.*|aarch64}}-{{.*}}-windows-{{.*}} #undef NDEBUG #include diff --git a/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp b/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp index e6a53ab9ff9529..954a5d4ba3db10 100644 --- a/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp +++ b/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // Ensure that the unwinder can cope with the signal handler. -// REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}}) +// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan diff --git a/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp b/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp index 76273e4a8ef0a7..2b7470b5cad0eb 100644 --- a/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp @@ -10,15 +10,12 @@ // Ensure that unw_resume() resumes execution at the stack frame identified by // cursor. -// TODO: Investigate this failure on AIX system. -// XFAIL: target={{.*}}-aix{{.*}} - // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan #include -void test_unw_resume() { +__attribute__((noinline)) void test_unw_resume() { unw_context_t context; unw_cursor_t cursor; diff --git a/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp b/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp index bdeb44ab62ae85..112a5968247a42 100644 --- a/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // Ensure that leaf function can be unwund. -// REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}}) +// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan @@ -28,7 +28,7 @@ _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) { (void)arg; Dl_info info = { 0, 0, 0, 0 }; - // Unwind until the main is reached, above frames deeped on the platform and + // Unwind until the main is reached, above frames depend on the platform and // architecture. if (dladdr(reinterpret_cast(_Unwind_GetIP(ctx)), &info) && info.dli_sname && !strcmp("main", info.dli_sname)) { @@ -43,18 +43,22 @@ void signal_handler(int signum) { _Exit(-1); } -__attribute__((noinline)) void crashing_leaf_func(void) { +__attribute__((noinline)) void crashing_leaf_func(int do_trap) { // libunwind searches for the address before the return address which points - // to the trap instruction. NOP guarantees the trap instruction is not the - // first instruction of the function. - // We should keep this here for other unwinders that also decrement pc. - __asm__ __volatile__("nop"); - __builtin_trap(); + // to the trap instruction. We make the trap conditional and prevent inlining + // of the function to ensure that the compiler doesn't remove the `ret` + // instruction altogether. + // + // It's also important that the trap instruction isn't the first instruction + // in the function (which it isn't because of the branch) for other unwinders + // that also decrement pc. + if (do_trap) + __builtin_trap(); } int main(int, char**) { signal(SIGTRAP, signal_handler); signal(SIGILL, signal_handler); - crashing_leaf_func(); + crashing_leaf_func(1); return -2; } diff --git a/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp b/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp index 250e2c8fc7b1e6..a5c5947c870fd1 100644 --- a/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp @@ -13,30 +13,8 @@ #include #include -// Check correct unwinding of frame with VLENB-sized objects (vector registers): -// 1. Save return address (ra) in temporary register. -// 2. Load VLENB (vector length in bytes) and substract it from current stack -// pointer (sp) - equivalent to one vector register on stack frame. -// 3. Set DWARF cannonical frame address (CFA) to "sp + vlenb" expresssion so it -// can be correctly unwinded. -// 4. Call stepper() function and check that 2 unwind steps are successful - -// from stepper() into foo() and from foo() into main(). -// 5. Restore stack pointer and return address. -__attribute__((naked)) static void foo() { - __asm__(".cfi_startproc\n" - "mv s0, ra\n" - "csrr s1, vlenb\n" - "sub sp, sp, s1\n" - "# .cfi_def_cfa_expression sp + vlenb\n" - ".cfi_escape 0x0f, 0x07, 0x72, 0x00, 0x92, 0xa2, 0x38, 0x00, 0x22\n" - "call stepper\n" - "add sp, sp, s1\n" - "mv ra, s0\n" - "ret\n" - ".cfi_endproc\n"); -} - -extern "C" void stepper() { +#ifdef __riscv_vector +__attribute__((noinline)) extern "C" void stepper() { unw_cursor_t cursor; unw_context_t uc; unw_getcontext(&uc); @@ -47,4 +25,16 @@ extern "C" void stepper() { assert(unw_step(&cursor) > 0); } +// Check correct unwinding of frame with VLENB-sized objects (vector registers). +__attribute__((noinline)) static void foo() { + __rvv_int32m1_t v; + asm volatile("" : "=vr"(v)); // Dummy inline asm to def v. + stepper(); // def-use of v has cross the function, so that + // will triger spill/reload to/from the stack. + asm volatile("" ::"vr"(v)); // Dummy inline asm to use v. +} + int main() { foo(); } +#else +int main() { return 0; } +#endif