-if (NOT IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../libcxx")
- message(FATAL_ERROR "libunwind requires being built in a monorepo layout with libcxx available")
-endif()
-
#===============================================================================
# Setup Project
#===============================================================================
cmake_minimum_required(VERSION 3.13.4)
+set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
+
# Add path for custom modules
-set(CMAKE_MODULE_PATH
+list(INSERT CMAKE_MODULE_PATH 0
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
- ${CMAKE_MODULE_PATH}
+ "${LLVM_COMMON_CMAKE_UTILS}"
+ "${LLVM_COMMON_CMAKE_UTILS}/Modules"
)
set(LIBUNWIND_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBUNWIND_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
"Specify path to libc++ source.")
-if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_BUILD)
- project(libunwind LANGUAGES C CXX ASM)
-
- set(PACKAGE_NAME libunwind)
- set(PACKAGE_VERSION 13.0.0git)
- set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
- set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
-
- # Add the CMake module path of libcxx so we can reuse HandleOutOfTreeLLVM.cmake
- set(LIBUNWIND_LIBCXX_CMAKE_PATH "${LIBUNWIND_LIBCXX_PATH}/cmake/Modules")
- list(APPEND CMAKE_MODULE_PATH "${LIBUNWIND_LIBCXX_CMAKE_PATH}")
-
- # In a standalone build, we don't have llvm to automatically generate the
- # llvm-lit script for us. So we need to provide an explicit directory that
- # the configurator should write the script into.
- set(LIBUNWIND_STANDALONE_BUILD 1)
- set(LLVM_LIT_OUTPUT_DIR "${LIBUNWIND_BINARY_DIR}/bin")
-
- # Find the LLVM sources and simulate LLVM CMake options.
- include(HandleOutOfTreeLLVM)
-else()
- set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
-endif()
+include(GNUInstallDirs)
#===============================================================================
# Setup CMake Options
include(HandleCompilerRT)
# Define options.
-option(LIBUNWIND_BUILD_32_BITS "Build 32 bit libunwind" ${LLVM_BUILD_32_BITS})
+option(LIBUNWIND_BUILD_32_BITS "Build 32 bit multilib libunwind. This option is not supported anymore when building the runtimes. Please specify a full triple instead." ${LLVM_BUILD_32_BITS})
+if (LIBUNWIND_BUILD_32_BITS)
+ message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS is not supported anymore when building the runtimes, please specify a full triple instead.")
+endif()
+
+option(LIBUNWIND_ENABLE_CET "Build libunwind with CET enabled." OFF)
option(LIBUNWIND_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
option(LIBUNWIND_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
option(LIBUNWIND_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
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)
set(LIBUNWIND_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
"Define suffix of library directory name (32/64)")
cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY
"Install the shared libunwind library." ON
"LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF)
-set(LIBUNWIND_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" CACHE STRING "Target triple for cross compiling.")
-set(LIBUNWIND_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.")
-set(LIBUNWIND_SYSROOT "" CACHE PATH "Sysroot for cross compiling.")
-set(LIBUNWIND_TEST_LINKER_FLAGS "" CACHE STRING
- "Additional linker flags for test programs.")
-set(LIBUNWIND_TEST_COMPILER_FLAGS "" CACHE STRING
- "Additional compiler flags for test programs.")
-set(LIBUNWIND_TEST_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test/lit.site.cfg.in" CACHE STRING
- "The Lit testing configuration to use when running the tests.")
+
+# 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)
+ set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-shared.cfg.in")
+else()
+ set(LIBUNWIND_DEFAULT_TEST_CONFIG "llvm-libunwind-static.cfg.in")
+endif()
+set(LIBUNWIND_TEST_CONFIG "${LIBUNWIND_DEFAULT_TEST_CONFIG}" CACHE STRING
+ "The path to the Lit testing configuration to use when running the tests.
+ If a relative path is provided, it is assumed to be relative to '<monorepo>/libunwind/test/configs'.")
+if (NOT IS_ABSOLUTE "${LIBUNWIND_TEST_CONFIG}")
+ set(LIBUNWIND_TEST_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test/configs/${LIBUNWIND_TEST_CONFIG}")
+endif()
+message(STATUS "Using libunwind testing configuration: ${LIBUNWIND_TEST_CONFIG}")
set(LIBUNWIND_TEST_PARAMS "" CACHE STRING
"A list of parameters to run the Lit test suite with.")
message(FATAL_ERROR "libunwind must be built as either a shared or static library.")
endif()
-# Check that we can build with 32 bits if requested.
-if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
- if (LIBUNWIND_BUILD_32_BITS AND NOT LLVM_BUILD_32_BITS) # Don't duplicate the output from LLVM
- message(STATUS "Building 32 bits executables and libraries.")
- endif()
-elseif(LIBUNWIND_BUILD_32_BITS)
- message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS=ON is not supported on this platform.")
+if (LIBUNWIND_ENABLE_CET AND MSVC)
+ message(FATAL_ERROR "libunwind CET support is not available for MSVC!")
endif()
+if (WIN32)
+ set(LIBUNWIND_DEFAULT_HIDE_SYMBOLS TRUE)
+else()
+ set(LIBUNWIND_DEFAULT_HIDE_SYMBOLS FALSE)
+endif()
option(LIBUNWIND_HIDE_SYMBOLS
- "Do not export any symbols from the static library." OFF)
+ "Do not export any symbols from the static library." ${LIBUNWIND_DEFAULT_HIDE_SYMBOLS})
#===============================================================================
# Configure System
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
${CMAKE_MODULE_PATH})
+set(LIBUNWIND_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH
+ "Path where built libunwind headers should be installed.")
+set(LIBUNWIND_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
+ "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.")
+set(LIBUNWIND_STATIC_OUTPUT_NAME "unwind" CACHE STRING "Output name for the static libunwind runtime library.")
+
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
string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR})
string(APPEND LIBUNWIND_INSTALL_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR})
endif()
-elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
- set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
- set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX} CACHE PATH
- "Path where built libunwind libraries should be installed.")
else()
- set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX})
+ if(LLVM_LIBRARY_OUTPUT_INTDIR)
+ set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
+ else()
+ set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX})
+ endif()
set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX} CACHE PATH
"Path where built libunwind libraries should be installed.")
endif()
# Setup Compiler Flags
#===============================================================================
-# Get required flags.
-add_target_flags_if(LIBUNWIND_BUILD_32_BITS "-m32")
-
-if(LIBUNWIND_TARGET_TRIPLE)
- add_target_flags_if_supported("--target=${LIBUNWIND_TARGET_TRIPLE}")
-elseif(CMAKE_CXX_COMPILER_TARGET)
- set(LIBUNWIND_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}")
-endif()
-if(LIBUNWIND_GCC_TOOLCHAIN)
- add_target_flags_if_supported("--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}")
-elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN)
- set(LIBUNWIND_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}")
-endif()
-if(LIBUNWIND_SYSROOT)
- add_target_flags_if_supported("--sysroot=${LIBUNWIND_SYSROOT}")
-elseif(CMAKE_SYSROOT)
- set(LIBUNWIND_SYSROOT "${CMAKE_SYSROOT}")
-endif()
-
# Configure compiler.
include(config-ix)
add_compile_flags_if_supported(-Werror=return-type)
+if (LIBUNWIND_ENABLE_CET)
+ add_compile_flags_if_supported(-fcf-protection=full)
+ add_compile_flags_if_supported(-mshstk)
+ if (NOT CXX_SUPPORTS_FCF_PROTECTION_EQ_FULL_FLAG)
+ message(SEND_ERROR "Compiler doesn't support CET -fcf-protection option!")
+ endif()
+ if (NOT CXX_SUPPORTS_MSHSTK_FLAG)
+ message(SEND_ERROR "Compiler doesn't support CET -mshstk option!")
+ endif()
+endif()
+
# Get warning flags
add_compile_flags_if_supported(-W)
add_compile_flags_if_supported(-Wall)
add_compile_flags_if_supported(-funwind-tables)
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_previous_CMAKE_TRY_COMPILE_TARGET_TYPE})
-if (LIBUNWIND_USES_ARM_EHABI AND NOT LIBUNWIND_SUPPORTS_FUNWIND_TABLES_FLAG)
+if (LIBUNWIND_USES_ARM_EHABI AND NOT CXX_SUPPORTS_FUNWIND_TABLES_FLAG)
message(SEND_ERROR "The -funwind-tables flag must be supported "
"because this target uses ARM Exception Handling ABI")
endif()
add_cxx_compile_flags_if_supported(-fno-rtti)
# Ensure that we don't depend on C++ standard library.
-if (LIBUNWIND_HAS_NOSTDINCXX_FLAG)
+if (CXX_SUPPORTS_NOSTDINCXX_FLAG)
list(APPEND LIBUNWIND_COMPILE_FLAGS -nostdinc++)
# Remove -stdlib flags to prevent them from causing an unused flag warning.
string(REPLACE "--stdlib=libc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# On Release builds cmake automatically defines NDEBUG, so we
# explicitly undefine it:
- if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
+ if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
add_compile_flags(-UNDEBUG)
endif()
else()
- if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
+ if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
add_compile_flags(-DNDEBUG)
endif()
endif()
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
-# Disable DLL annotations on Windows for static builds.
-if (WIN32 AND LIBUNWIND_ENABLE_STATIC AND NOT LIBUNWIND_ENABLE_SHARED)
- add_definitions(-D_LIBUNWIND_HIDE_SYMBOLS)
-endif()
-
-if (LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
+if (C_SUPPORTS_COMMENT_LIB_PRAGMA)
if (LIBUNWIND_HAS_DL_LIB)
add_definitions(-D_LIBUNWIND_LINK_DL_LIB)
endif()
# Setup Source Code
#===============================================================================
-include_directories(include)
+add_subdirectory(include)
add_subdirectory(src)
add_subdirectory(docs)
endif()
-if (LIBUNWIND_INCLUDE_TESTS AND EXISTS ${LLVM_CMAKE_PATH})
+if (LIBUNWIND_INCLUDE_TESTS AND EXISTS ${LLVM_CMAKE_DIR})
add_subdirectory(test)
endif()
macro(check_flag_supported flag)
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
endmacro()
macro(append_flags DEST)
macro(append_flags_if_supported DEST)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- append_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${DEST} ${flag})
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
+ append_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${DEST} ${flag})
endforeach()
endmacro()
macro(add_target_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- add_target_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
+ add_target_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
macro(add_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- add_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
+ add_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
macro(add_compile_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- add_compile_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
+ add_compile_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
macro(add_c_compile_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_c_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- add_c_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
+ check_c_compiler_flag("${flag}" "C_SUPPORTS_${flagname}_FLAG")
+ add_c_flags_if(C_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
macro(add_cxx_compile_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- add_cxx_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
+ add_cxx_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
macro(add_link_flags_if_supported)
foreach(flag ${ARGN})
mangle_name("${flag}" flagname)
- check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG")
- add_link_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag})
+ check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
+ add_link_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
endforeach()
endmacro()
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()
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
+include(LLVMCheckCompilerLinkerFlag)
include(CheckSymbolExists)
include(CheckCSourceCompiles)
+# The compiler driver may be implicitly trying to link against libunwind, which
+# might not work if libunwind doesn't exist yet. Try to check if
+# --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 (NOT LIBUNWIND_USE_COMPILER_RT)
# required for the link to go through. We remove sanitizers from the
# configuration checks to avoid spurious link errors.
-check_c_compiler_flag(-nostdlib++ LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG)
-if (LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG)
+llvm_check_compiler_linker_flag(CXX "-nostdlib++" CXX_SUPPORTS_NOSTDLIBXX_FLAG)
+if (CXX_SUPPORTS_NOSTDLIBXX_FLAG)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nostdlib++")
else()
- check_c_compiler_flag(-nodefaultlibs LIBUNWIND_SUPPORTS_NODEFAULTLIBS_FLAG)
- if (LIBUNWIND_SUPPORTS_NODEFAULTLIBS_FLAG)
+ llvm_check_compiler_linker_flag(C "-nodefaultlibs" C_SUPPORTS_NODEFAULTLIBS_FLAG)
+ if (C_SUPPORTS_NODEFAULTLIBS_FLAG)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
endif()
endif()
-if (LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG OR LIBUNWIND_SUPPORTS_NODEFAULTLIBS_FLAG)
+if (CXX_SUPPORTS_NOSTDLIBXX_FLAG OR C_SUPPORTS_NODEFAULTLIBS_FLAG)
if (LIBUNWIND_HAS_C_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
endif ()
if (LIBUNWIND_USE_COMPILER_RT)
- find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY)
+ include(HandleCompilerRT)
+ find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY
+ FLAGS ${LIBUNWIND_COMPILE_FLAGS})
list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBUNWIND_BUILTINS_LIBRARY}")
else ()
if (LIBUNWIND_HAS_GCC_S_LIB)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all")
endif ()
if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage)
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fsanitize-coverage=0")
endif ()
endif ()
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas")
check_c_source_compiles("
#pragma comment(lib, \"c\")
-int main() { return 0; }
-" LIBUNWIND_HAS_COMMENT_LIB_PRAGMA)
+int main(void) { return 0; }
+" C_SUPPORTS_COMMENT_LIB_PRAGMA)
cmake_pop_check_state()
endif()
# Check compiler flags
-check_cxx_compiler_flag(-nostdinc++ LIBUNWIND_HAS_NOSTDINCXX_FLAG)
+check_cxx_compiler_flag(-nostdinc++ CXX_SUPPORTS_NOSTDINCXX_FLAG)
# Check symbols
check_symbol_exists(__arm__ "" LIBUNWIND_TARGET_ARM)
--- /dev/null
+set(files
+ __libunwind_config.h
+ libunwind.h
+ libunwind.modulemap
+ mach-o/compact_unwind_encoding.h
+ mach-o/compact_unwind_encoding.modulemap
+ unwind_arm_ehabi.h
+ unwind_itanium.h
+ unwind.h
+ )
+
+add_library(unwind-headers INTERFACE)
+target_include_directories(unwind-headers INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+
+if(LIBUNWIND_INSTALL_HEADERS)
+ foreach(file ${files})
+ get_filename_component(dir ${file} DIRECTORY)
+ install(FILES ${file}
+ DESTINATION "${LIBUNWIND_INSTALL_INCLUDE_DIR}/${dir}"
+ COMPONENT unwind-headers
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+ )
+ endforeach()
+
+ if(NOT CMAKE_CONFIGURATION_TYPES)
+ add_custom_target(install-unwind-headers
+ DEPENDS unwind-headers
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=unwind-headers
+ -P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake")
+ add_custom_target(install-unwind-headers-stripped DEPENDS install-unwind-headers)
+ endif()
+endif()
-//===---------------------------- libunwind.h -----------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
typedef int unw_regnum_t;
typedef uintptr_t unw_word_t;
-#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
typedef uint64_t unw_fpreg_t;
#else
typedef double unw_fpreg_t;
extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;
#endif
+#ifdef _AIX
+extern uintptr_t unw_get_data_rel_base(unw_cursor_t *) LIBUNWIND_AVAIL;
+#endif
extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;
// 64-bit ARM64 registers
enum {
- UNW_ARM64_X0 = 0,
- UNW_ARM64_X1 = 1,
- UNW_ARM64_X2 = 2,
- UNW_ARM64_X3 = 3,
- UNW_ARM64_X4 = 4,
- UNW_ARM64_X5 = 5,
- UNW_ARM64_X6 = 6,
- UNW_ARM64_X7 = 7,
- UNW_ARM64_X8 = 8,
- UNW_ARM64_X9 = 9,
- UNW_ARM64_X10 = 10,
- UNW_ARM64_X11 = 11,
- UNW_ARM64_X12 = 12,
- UNW_ARM64_X13 = 13,
- UNW_ARM64_X14 = 14,
- UNW_ARM64_X15 = 15,
- UNW_ARM64_X16 = 16,
- UNW_ARM64_X17 = 17,
- UNW_ARM64_X18 = 18,
- UNW_ARM64_X19 = 19,
- UNW_ARM64_X20 = 20,
- UNW_ARM64_X21 = 21,
- UNW_ARM64_X22 = 22,
- UNW_ARM64_X23 = 23,
- UNW_ARM64_X24 = 24,
- UNW_ARM64_X25 = 25,
- UNW_ARM64_X26 = 26,
- UNW_ARM64_X27 = 27,
- UNW_ARM64_X28 = 28,
- UNW_ARM64_X29 = 29,
- UNW_ARM64_FP = 29,
- UNW_ARM64_X30 = 30,
- UNW_ARM64_LR = 30,
- UNW_ARM64_X31 = 31,
- UNW_ARM64_SP = 31,
- UNW_ARM64_PC = 32,
- // reserved block
- UNW_ARM64_RA_SIGN_STATE = 34,
+ UNW_AARCH64_X0 = 0,
+ UNW_AARCH64_X1 = 1,
+ UNW_AARCH64_X2 = 2,
+ UNW_AARCH64_X3 = 3,
+ UNW_AARCH64_X4 = 4,
+ UNW_AARCH64_X5 = 5,
+ UNW_AARCH64_X6 = 6,
+ UNW_AARCH64_X7 = 7,
+ UNW_AARCH64_X8 = 8,
+ UNW_AARCH64_X9 = 9,
+ UNW_AARCH64_X10 = 10,
+ UNW_AARCH64_X11 = 11,
+ UNW_AARCH64_X12 = 12,
+ UNW_AARCH64_X13 = 13,
+ UNW_AARCH64_X14 = 14,
+ UNW_AARCH64_X15 = 15,
+ UNW_AARCH64_X16 = 16,
+ UNW_AARCH64_X17 = 17,
+ UNW_AARCH64_X18 = 18,
+ UNW_AARCH64_X19 = 19,
+ UNW_AARCH64_X20 = 20,
+ UNW_AARCH64_X21 = 21,
+ UNW_AARCH64_X22 = 22,
+ UNW_AARCH64_X23 = 23,
+ UNW_AARCH64_X24 = 24,
+ UNW_AARCH64_X25 = 25,
+ UNW_AARCH64_X26 = 26,
+ UNW_AARCH64_X27 = 27,
+ UNW_AARCH64_X28 = 28,
+ UNW_AARCH64_X29 = 29,
+ UNW_AARCH64_FP = 29,
+ UNW_AARCH64_X30 = 30,
+ UNW_AARCH64_LR = 30,
+ UNW_AARCH64_X31 = 31,
+ UNW_AARCH64_SP = 31,
+ UNW_AARCH64_PC = 32,
+
// reserved block
- UNW_ARM64_D0 = 64,
- UNW_ARM64_D1 = 65,
- UNW_ARM64_D2 = 66,
- UNW_ARM64_D3 = 67,
- UNW_ARM64_D4 = 68,
- UNW_ARM64_D5 = 69,
- UNW_ARM64_D6 = 70,
- UNW_ARM64_D7 = 71,
- UNW_ARM64_D8 = 72,
- UNW_ARM64_D9 = 73,
- UNW_ARM64_D10 = 74,
- UNW_ARM64_D11 = 75,
- UNW_ARM64_D12 = 76,
- UNW_ARM64_D13 = 77,
- UNW_ARM64_D14 = 78,
- UNW_ARM64_D15 = 79,
- UNW_ARM64_D16 = 80,
- UNW_ARM64_D17 = 81,
- UNW_ARM64_D18 = 82,
- UNW_ARM64_D19 = 83,
- UNW_ARM64_D20 = 84,
- UNW_ARM64_D21 = 85,
- UNW_ARM64_D22 = 86,
- UNW_ARM64_D23 = 87,
- UNW_ARM64_D24 = 88,
- UNW_ARM64_D25 = 89,
- UNW_ARM64_D26 = 90,
- UNW_ARM64_D27 = 91,
- UNW_ARM64_D28 = 92,
- UNW_ARM64_D29 = 93,
- UNW_ARM64_D30 = 94,
- UNW_ARM64_D31 = 95,
+ UNW_AARCH64_RA_SIGN_STATE = 34,
+
+ // FP/vector registers
+ UNW_AARCH64_V0 = 64,
+ UNW_AARCH64_V1 = 65,
+ UNW_AARCH64_V2 = 66,
+ UNW_AARCH64_V3 = 67,
+ UNW_AARCH64_V4 = 68,
+ UNW_AARCH64_V5 = 69,
+ UNW_AARCH64_V6 = 70,
+ UNW_AARCH64_V7 = 71,
+ UNW_AARCH64_V8 = 72,
+ UNW_AARCH64_V9 = 73,
+ UNW_AARCH64_V10 = 74,
+ UNW_AARCH64_V11 = 75,
+ UNW_AARCH64_V12 = 76,
+ UNW_AARCH64_V13 = 77,
+ UNW_AARCH64_V14 = 78,
+ UNW_AARCH64_V15 = 79,
+ UNW_AARCH64_V16 = 80,
+ UNW_AARCH64_V17 = 81,
+ UNW_AARCH64_V18 = 82,
+ UNW_AARCH64_V19 = 83,
+ UNW_AARCH64_V20 = 84,
+ UNW_AARCH64_V21 = 85,
+ UNW_AARCH64_V22 = 86,
+ UNW_AARCH64_V23 = 87,
+ UNW_AARCH64_V24 = 88,
+ UNW_AARCH64_V25 = 89,
+ UNW_AARCH64_V26 = 90,
+ UNW_AARCH64_V27 = 91,
+ UNW_AARCH64_V28 = 92,
+ UNW_AARCH64_V29 = 93,
+ UNW_AARCH64_V30 = 94,
+ UNW_AARCH64_V31 = 95,
+
+ // Compatibility aliases
+ UNW_ARM64_X0 = UNW_AARCH64_X0,
+ UNW_ARM64_X1 = UNW_AARCH64_X1,
+ UNW_ARM64_X2 = UNW_AARCH64_X2,
+ UNW_ARM64_X3 = UNW_AARCH64_X3,
+ UNW_ARM64_X4 = UNW_AARCH64_X4,
+ UNW_ARM64_X5 = UNW_AARCH64_X5,
+ UNW_ARM64_X6 = UNW_AARCH64_X6,
+ UNW_ARM64_X7 = UNW_AARCH64_X7,
+ UNW_ARM64_X8 = UNW_AARCH64_X8,
+ UNW_ARM64_X9 = UNW_AARCH64_X9,
+ UNW_ARM64_X10 = UNW_AARCH64_X10,
+ UNW_ARM64_X11 = UNW_AARCH64_X11,
+ UNW_ARM64_X12 = UNW_AARCH64_X12,
+ UNW_ARM64_X13 = UNW_AARCH64_X13,
+ UNW_ARM64_X14 = UNW_AARCH64_X14,
+ UNW_ARM64_X15 = UNW_AARCH64_X15,
+ UNW_ARM64_X16 = UNW_AARCH64_X16,
+ UNW_ARM64_X17 = UNW_AARCH64_X17,
+ UNW_ARM64_X18 = UNW_AARCH64_X18,
+ UNW_ARM64_X19 = UNW_AARCH64_X19,
+ UNW_ARM64_X20 = UNW_AARCH64_X20,
+ UNW_ARM64_X21 = UNW_AARCH64_X21,
+ UNW_ARM64_X22 = UNW_AARCH64_X22,
+ UNW_ARM64_X23 = UNW_AARCH64_X23,
+ UNW_ARM64_X24 = UNW_AARCH64_X24,
+ UNW_ARM64_X25 = UNW_AARCH64_X25,
+ UNW_ARM64_X26 = UNW_AARCH64_X26,
+ UNW_ARM64_X27 = UNW_AARCH64_X27,
+ UNW_ARM64_X28 = UNW_AARCH64_X28,
+ UNW_ARM64_X29 = UNW_AARCH64_X29,
+ UNW_ARM64_FP = UNW_AARCH64_FP,
+ UNW_ARM64_X30 = UNW_AARCH64_X30,
+ UNW_ARM64_LR = UNW_AARCH64_LR,
+ UNW_ARM64_X31 = UNW_AARCH64_X31,
+ UNW_ARM64_SP = UNW_AARCH64_SP,
+ UNW_ARM64_PC = UNW_AARCH64_PC,
+ UNW_ARM64_RA_SIGN_STATE = UNW_AARCH64_RA_SIGN_STATE,
+ UNW_ARM64_D0 = UNW_AARCH64_V0,
+ UNW_ARM64_D1 = UNW_AARCH64_V1,
+ UNW_ARM64_D2 = UNW_AARCH64_V2,
+ UNW_ARM64_D3 = UNW_AARCH64_V3,
+ UNW_ARM64_D4 = UNW_AARCH64_V4,
+ UNW_ARM64_D5 = UNW_AARCH64_V5,
+ UNW_ARM64_D6 = UNW_AARCH64_V6,
+ UNW_ARM64_D7 = UNW_AARCH64_V7,
+ UNW_ARM64_D8 = UNW_AARCH64_V8,
+ UNW_ARM64_D9 = UNW_AARCH64_V9,
+ UNW_ARM64_D10 = UNW_AARCH64_V10,
+ UNW_ARM64_D11 = UNW_AARCH64_V11,
+ UNW_ARM64_D12 = UNW_AARCH64_V12,
+ UNW_ARM64_D13 = UNW_AARCH64_V13,
+ UNW_ARM64_D14 = UNW_AARCH64_V14,
+ UNW_ARM64_D15 = UNW_AARCH64_V15,
+ UNW_ARM64_D16 = UNW_AARCH64_V16,
+ UNW_ARM64_D17 = UNW_AARCH64_V17,
+ UNW_ARM64_D18 = UNW_AARCH64_V18,
+ UNW_ARM64_D19 = UNW_AARCH64_V19,
+ UNW_ARM64_D20 = UNW_AARCH64_V20,
+ UNW_ARM64_D21 = UNW_AARCH64_V21,
+ UNW_ARM64_D22 = UNW_AARCH64_V22,
+ UNW_ARM64_D23 = UNW_AARCH64_V23,
+ UNW_ARM64_D24 = UNW_AARCH64_V24,
+ UNW_ARM64_D25 = UNW_AARCH64_V25,
+ UNW_ARM64_D26 = UNW_AARCH64_V26,
+ UNW_ARM64_D27 = UNW_AARCH64_V27,
+ UNW_ARM64_D28 = UNW_AARCH64_V28,
+ UNW_ARM64_D29 = UNW_AARCH64_V29,
+ UNW_ARM64_D30 = UNW_AARCH64_V30,
+ UNW_ARM64_D31 = UNW_AARCH64_V31,
};
// 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1.
UNW_ARM_WR14 = 126,
UNW_ARM_WR15 = 127,
// 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC}
- // 134-143 -- Reserved
+ // 134-142 -- Reserved
+ UNW_ARM_RA_AUTH_CODE = 143,
// 144-150 -- R8_USR-R14_USR
// 151-157 -- R8_FIQ-R14_FIQ
// 158-159 -- R13_IRQ-R14_IRQ
UNW_RISCV_F29 = 61,
UNW_RISCV_F30 = 62,
UNW_RISCV_F31 = 63,
+ // 65-95 -- Reserved for future standard extensions
+ // 96-127 -- v0-v31 (Vector registers)
+ // 128-3071 -- Reserved for future standard extensions
+ // 3072-4095 -- Reserved for custom extensions
+ // 4096-8191 -- CSRs
+ //
+ // VLENB CSR number: 0xC22 -- defined by section 3 of v-spec:
+ // https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#3-vector-extension-programmers-model
+ // VLENB DWARF number: 0x1000 + 0xC22
+ UNW_RISCV_VLENB = 0x1C22,
};
// VE register numbers
UNW_VE_VL = 145,
};
+// s390x register numbers
+enum {
+ UNW_S390X_R0 = 0,
+ UNW_S390X_R1 = 1,
+ UNW_S390X_R2 = 2,
+ UNW_S390X_R3 = 3,
+ UNW_S390X_R4 = 4,
+ UNW_S390X_R5 = 5,
+ UNW_S390X_R6 = 6,
+ UNW_S390X_R7 = 7,
+ UNW_S390X_R8 = 8,
+ UNW_S390X_R9 = 9,
+ UNW_S390X_R10 = 10,
+ UNW_S390X_R11 = 11,
+ UNW_S390X_R12 = 12,
+ UNW_S390X_R13 = 13,
+ UNW_S390X_R14 = 14,
+ UNW_S390X_R15 = 15,
+ UNW_S390X_F0 = 16,
+ UNW_S390X_F2 = 17,
+ UNW_S390X_F4 = 18,
+ UNW_S390X_F6 = 19,
+ UNW_S390X_F1 = 20,
+ UNW_S390X_F3 = 21,
+ UNW_S390X_F5 = 22,
+ UNW_S390X_F7 = 23,
+ UNW_S390X_F8 = 24,
+ UNW_S390X_F10 = 25,
+ UNW_S390X_F12 = 26,
+ UNW_S390X_F14 = 27,
+ UNW_S390X_F9 = 28,
+ UNW_S390X_F11 = 29,
+ UNW_S390X_F13 = 30,
+ UNW_S390X_F15 = 31,
+ // 32-47 Control Registers
+ // 48-63 Access Registers
+ UNW_S390X_PSWM = 64,
+ UNW_S390X_PSWA = 65,
+ // 66-67 Reserved
+ // 68-83 Vector Registers %v16-%v31
+};
+
+// LoongArch registers.
+enum {
+ UNW_LOONGARCH_R0 = 0,
+ UNW_LOONGARCH_R1 = 1,
+ UNW_LOONGARCH_R2 = 2,
+ UNW_LOONGARCH_R3 = 3,
+ UNW_LOONGARCH_R4 = 4,
+ UNW_LOONGARCH_R5 = 5,
+ UNW_LOONGARCH_R6 = 6,
+ UNW_LOONGARCH_R7 = 7,
+ UNW_LOONGARCH_R8 = 8,
+ UNW_LOONGARCH_R9 = 9,
+ UNW_LOONGARCH_R10 = 10,
+ UNW_LOONGARCH_R11 = 11,
+ UNW_LOONGARCH_R12 = 12,
+ UNW_LOONGARCH_R13 = 13,
+ UNW_LOONGARCH_R14 = 14,
+ UNW_LOONGARCH_R15 = 15,
+ UNW_LOONGARCH_R16 = 16,
+ UNW_LOONGARCH_R17 = 17,
+ UNW_LOONGARCH_R18 = 18,
+ UNW_LOONGARCH_R19 = 19,
+ UNW_LOONGARCH_R20 = 20,
+ UNW_LOONGARCH_R21 = 21,
+ UNW_LOONGARCH_R22 = 22,
+ UNW_LOONGARCH_R23 = 23,
+ UNW_LOONGARCH_R24 = 24,
+ UNW_LOONGARCH_R25 = 25,
+ UNW_LOONGARCH_R26 = 26,
+ UNW_LOONGARCH_R27 = 27,
+ UNW_LOONGARCH_R28 = 28,
+ UNW_LOONGARCH_R29 = 29,
+ UNW_LOONGARCH_R30 = 30,
+ UNW_LOONGARCH_R31 = 31,
+ UNW_LOONGARCH_F0 = 32,
+ UNW_LOONGARCH_F1 = 33,
+ UNW_LOONGARCH_F2 = 34,
+ UNW_LOONGARCH_F3 = 35,
+ UNW_LOONGARCH_F4 = 36,
+ UNW_LOONGARCH_F5 = 37,
+ UNW_LOONGARCH_F6 = 38,
+ UNW_LOONGARCH_F7 = 39,
+ UNW_LOONGARCH_F8 = 40,
+ UNW_LOONGARCH_F9 = 41,
+ UNW_LOONGARCH_F10 = 42,
+ UNW_LOONGARCH_F11 = 43,
+ UNW_LOONGARCH_F12 = 44,
+ UNW_LOONGARCH_F13 = 45,
+ UNW_LOONGARCH_F14 = 46,
+ UNW_LOONGARCH_F15 = 47,
+ UNW_LOONGARCH_F16 = 48,
+ UNW_LOONGARCH_F17 = 49,
+ UNW_LOONGARCH_F18 = 50,
+ UNW_LOONGARCH_F19 = 51,
+ UNW_LOONGARCH_F20 = 52,
+ UNW_LOONGARCH_F21 = 53,
+ UNW_LOONGARCH_F22 = 54,
+ UNW_LOONGARCH_F23 = 55,
+ UNW_LOONGARCH_F24 = 56,
+ UNW_LOONGARCH_F25 = 57,
+ UNW_LOONGARCH_F26 = 58,
+ UNW_LOONGARCH_F27 = 59,
+ UNW_LOONGARCH_F28 = 60,
+ UNW_LOONGARCH_F29 = 61,
+ UNW_LOONGARCH_F30 = 62,
+ UNW_LOONGARCH_F31 = 63,
+};
+
#endif
--- /dev/null
+module libunwind [system] {
+ header "libunwind.h"
+ export *
+}
+
+module unwind [system] {
+ header "__libunwind_config.h"
+ header "unwind.h"
+ private textual header "unwind_arm_ehabi.h"
+ private textual header "unwind_itanium.h"
+
+ export *
+}
-//===------------------ mach-o/compact_unwind_encoding.h ------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
-// The compact unwind endoding is a 32-bit value which encoded in an
+// The compact unwind encoding is a 32-bit value which encoded in an
// architecture specific way, which registers to restore from where, and how
// to unwind out of the function.
//
// on the stack immediately after the return address. The stack_size/4 is
// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
-// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
+// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
// saved and their order.
// UNWIND_X86_MODE_STACK_IND:
// A "frameless" (EBP not used as frame pointer) function large constant
// on the stack immediately after the return address. The stack_size/8 is
// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
-// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
+// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
// saved and their order.
// UNWIND_X86_64_MODE_STACK_IND:
// A "frameless" (RBP not used as frame pointer) function large constant
--- /dev/null
+module MachO.compact_unwind_encoding [system] {
+ header "compact_unwind_encoding.h"
+ export *
+}
-//===------------------------------- unwind.h -----------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
typedef struct _Unwind_Context _Unwind_Context; // opaque
#if defined(_LIBUNWIND_ARM_EHABI)
-typedef uint32_t _Unwind_State;
-
-static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
-static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
-static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
-static const _Unwind_State _US_ACTION_MASK = 3;
-/* Undocumented flag for force unwinding. */
-static const _Unwind_State _US_FORCE_UNWIND = 8;
-
-typedef uint32_t _Unwind_EHT_Header;
-
-struct _Unwind_Control_Block;
-typedef struct _Unwind_Control_Block _Unwind_Control_Block;
-typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
-
-struct _Unwind_Control_Block {
- uint64_t exception_class;
- void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*);
-
- /* Unwinder cache, private fields for the unwinder's use */
- struct {
- uint32_t reserved1; /* init reserved1 to 0, then don't touch */
- uint32_t reserved2;
- uint32_t reserved3;
- uint32_t reserved4;
- uint32_t reserved5;
- } unwinder_cache;
-
- /* Propagation barrier cache (valid after phase 1): */
- struct {
- uint32_t sp;
- uint32_t bitpattern[5];
- } barrier_cache;
-
- /* Cleanup cache (preserved over cleanup): */
- struct {
- uint32_t bitpattern[4];
- } cleanup_cache;
-
- /* Pr cache (for pr's benefit): */
- struct {
- uint32_t fnstart; /* function start address */
- _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */
- uint32_t additional;
- uint32_t reserved1;
- } pr_cache;
-
- long long int :0; /* Enforce the 8-byte alignment */
-} __attribute__((__aligned__(8)));
-
-typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
- (_Unwind_State state,
- _Unwind_Exception* exceptionObject,
- struct _Unwind_Context* context);
-
-typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
- _Unwind_State state, _Unwind_Exception *exceptionObject,
- struct _Unwind_Context *context);
+#include <unwind_arm_ehabi.h>
#else
-struct _Unwind_Context; // opaque
-struct _Unwind_Exception; // forward declaration
-typedef struct _Unwind_Exception _Unwind_Exception;
-
-struct _Unwind_Exception {
- uint64_t exception_class;
- void (*exception_cleanup)(_Unwind_Reason_Code reason,
- _Unwind_Exception *exc);
-#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
- uintptr_t private_[6];
-#else
- uintptr_t private_1; // non-zero means forced unwind
- uintptr_t private_2; // holds sp that phase1 found for phase2 to use
+#include <unwind_itanium.h>
#endif
-#if __SIZEOF_POINTER__ == 4
- // The implementation of _Unwind_Exception uses an attribute mode on the
- // above fields which has the side effect of causing this whole struct to
- // round up to 32 bytes in size (48 with SEH). To be more explicit, we add
- // pad fields added for binary compatibility.
- uint32_t reserved[3];
-#endif
- // The Itanium ABI requires that _Unwind_Exception objects are "double-word
- // aligned". GCC has interpreted this to mean "use the maximum useful
- // alignment for the target"; so do we.
-} __attribute__((__aligned__));
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int version,
_Unwind_Action actions,
- uint64_t exceptionClass,
+ _Unwind_Exception_Class exceptionClass,
_Unwind_Exception* exceptionObject,
struct _Unwind_Context* context,
- void* stop_parameter );
-
-typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
- int version, _Unwind_Action actions, uint64_t exceptionClass,
- _Unwind_Exception *exceptionObject, struct _Unwind_Context *context);
-#endif
+ void* stop_parameter);
#ifdef __cplusplus
extern "C" {
#endif
-//
-// The following are the base functions documented by the C++ ABI
-//
-#ifdef __USING_SJLJ_EXCEPTIONS__
-extern _Unwind_Reason_Code
- _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
-extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
-#else
-extern _Unwind_Reason_Code
- _Unwind_RaiseException(_Unwind_Exception *exception_object);
-extern void _Unwind_Resume(_Unwind_Exception *exception_object);
-#endif
-extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
-
-#if defined(_LIBUNWIND_ARM_EHABI)
-typedef enum {
- _UVRSC_CORE = 0, /* integer register */
- _UVRSC_VFP = 1, /* vfp */
- _UVRSC_WMMXD = 3, /* Intel WMMX data register */
- _UVRSC_WMMXC = 4 /* Intel WMMX control register */
-} _Unwind_VRS_RegClass;
-
-typedef enum {
- _UVRSD_UINT32 = 0,
- _UVRSD_VFPX = 1,
- _UVRSD_UINT64 = 3,
- _UVRSD_FLOAT = 4,
- _UVRSD_DOUBLE = 5
-} _Unwind_VRS_DataRepresentation;
-
-typedef enum {
- _UVRSR_OK = 0,
- _UVRSR_NOT_IMPLEMENTED = 1,
- _UVRSR_FAILED = 2
-} _Unwind_VRS_Result;
-
-extern void _Unwind_Complete(_Unwind_Exception* exception_object);
-
-extern _Unwind_VRS_Result
-_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
- uint32_t regno, _Unwind_VRS_DataRepresentation representation,
- void *valuep);
-
-extern _Unwind_VRS_Result
-_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
- uint32_t regno, _Unwind_VRS_DataRepresentation representation,
- void *valuep);
-
-extern _Unwind_VRS_Result
-_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
- uint32_t discriminator,
- _Unwind_VRS_DataRepresentation representation);
-#endif
-
-#if !defined(_LIBUNWIND_ARM_EHABI)
-
-extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
-extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t new_value);
-extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
-extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
-
-#else // defined(_LIBUNWIND_ARM_EHABI)
-
-#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
-#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
-#else
-#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
-#endif
-
-// These are de facto helper functions for ARM, which delegate the function
-// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI
-// specification, thus these function MUST be inlined. Please don't replace
-// these with the "extern" function declaration; otherwise, the program
-// including this <unwind.h> header won't be ABI compatible and will result in
-// link error when we are linking the program with libgcc.
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
- uintptr_t value = 0;
- _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
- return value;
-}
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t value) {
- _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
-}
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
- // remove the thumb-bit before returning
- return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
-}
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
- uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
- _Unwind_SetGR(context, 15, value | thumb_bit);
-}
-#endif // defined(_LIBUNWIND_ARM_EHABI)
-
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
extern uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
#endif
//
-// The following are semi-suppoted extensions to the C++ ABI
+// The following are semi-supported extensions to the C++ ABI
//
//
extern void *_Unwind_FindEnclosingFunction(void *pc);
// Mac OS X does not support text-rel and data-rel addressing so these functions
-// are unimplemented
+// are unimplemented.
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
LIBUNWIND_UNAVAIL;
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//
+// C++ ABI Level 1 ABI documented at:
+// https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __ARM_EHABI_UNWIND_H__
+#define __ARM_EHABI_UNWIND_H__
+
+typedef uint32_t _Unwind_State;
+
+static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
+static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
+static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
+static const _Unwind_State _US_ACTION_MASK = 3;
+/* Undocumented flag for force unwinding. */
+static const _Unwind_State _US_FORCE_UNWIND = 8;
+
+typedef uint32_t _Unwind_EHT_Header;
+
+struct _Unwind_Control_Block;
+typedef struct _Unwind_Control_Block _Unwind_Control_Block;
+#define _Unwind_Exception _Unwind_Control_Block /* Alias */
+typedef uint8_t _Unwind_Exception_Class[8];
+
+struct _Unwind_Control_Block {
+ _Unwind_Exception_Class exception_class;
+ void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*);
+
+ /* Unwinder cache, private fields for the unwinder's use */
+ struct {
+ uint32_t reserved1; /* init reserved1 to 0, then don't touch */
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t reserved4;
+ uint32_t reserved5;
+ } unwinder_cache;
+
+ /* Propagation barrier cache (valid after phase 1): */
+ struct {
+ uint32_t sp;
+ uint32_t bitpattern[5];
+ } barrier_cache;
+
+ /* Cleanup cache (preserved over cleanup): */
+ struct {
+ uint32_t bitpattern[4];
+ } cleanup_cache;
+
+ /* Pr cache (for pr's benefit): */
+ struct {
+ uint32_t fnstart; /* function start address */
+ _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */
+ uint32_t additional;
+ uint32_t reserved1;
+ } pr_cache;
+
+ long long int :0; /* Enforce the 8-byte alignment */
+} __attribute__((__aligned__(8)));
+
+typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
+ _Unwind_State state, _Unwind_Exception *exceptionObject,
+ struct _Unwind_Context *context);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// The following are the base functions documented by the C++ ABI
+//
+#ifdef __USING_SJLJ_EXCEPTIONS__
+extern _Unwind_Reason_Code
+ _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
+extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
+#else
+extern _Unwind_Reason_Code
+ _Unwind_RaiseException(_Unwind_Exception *exception_object);
+extern void _Unwind_Resume(_Unwind_Exception *exception_object);
+#endif
+extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
+
+typedef enum {
+ _UVRSC_CORE = 0, /* integer register */
+ _UVRSC_VFP = 1, /* vfp */
+ _UVRSC_WMMXD = 3, /* Intel WMMX data register */
+ _UVRSC_WMMXC = 4, /* Intel WMMX control register */
+ _UVRSC_PSEUDO = 5 /* Special purpose pseudo register */
+} _Unwind_VRS_RegClass;
+
+typedef enum {
+ _UVRSD_UINT32 = 0,
+ _UVRSD_VFPX = 1,
+ _UVRSD_UINT64 = 3,
+ _UVRSD_FLOAT = 4,
+ _UVRSD_DOUBLE = 5
+} _Unwind_VRS_DataRepresentation;
+
+typedef enum {
+ _UVRSR_OK = 0,
+ _UVRSR_NOT_IMPLEMENTED = 1,
+ _UVRSR_FAILED = 2
+} _Unwind_VRS_Result;
+
+extern void _Unwind_Complete(_Unwind_Exception* exception_object);
+
+extern _Unwind_VRS_Result
+_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t regno, _Unwind_VRS_DataRepresentation representation,
+ void *valuep);
+
+extern _Unwind_VRS_Result
+_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t regno, _Unwind_VRS_DataRepresentation representation,
+ void *valuep);
+
+extern _Unwind_VRS_Result
+_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t discriminator,
+ _Unwind_VRS_DataRepresentation representation);
+
+#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
+#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
+#else
+#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
+#endif
+
+// These are de facto helper functions for ARM, which delegate the function
+// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI
+// specification, thus these function MUST be inlined. Please don't replace
+// these with the "extern" function declaration; otherwise, the program
+// including this <unwind.h> header won't be ABI compatible and will result in
+// link error when we are linking the program with libgcc.
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
+ uintptr_t value = 0;
+ _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
+ return value;
+}
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+void _Unwind_SetGR(struct _Unwind_Context *context, int index,
+ uintptr_t value) {
+ _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
+}
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
+ // remove the thumb-bit before returning
+ return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
+}
+
+_LIBUNWIND_EXPORT_UNWIND_LEVEL1
+void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
+ uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
+ _Unwind_SetGR(context, 15, value | thumb_bit);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __ARM_EHABI_UNWIND_H__
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//
+// C++ ABI Level 1 ABI documented at:
+// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __ITANIUM_UNWIND_H__
+#define __ITANIUM_UNWIND_H__
+
+struct _Unwind_Context; // opaque
+struct _Unwind_Exception; // forward declaration
+typedef struct _Unwind_Exception _Unwind_Exception;
+typedef uint64_t _Unwind_Exception_Class;
+
+struct _Unwind_Exception {
+ _Unwind_Exception_Class exception_class;
+ void (*exception_cleanup)(_Unwind_Reason_Code reason,
+ _Unwind_Exception *exc);
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+ uintptr_t private_[6];
+#else
+ uintptr_t private_1; // non-zero means forced unwind
+ uintptr_t private_2; // holds sp that phase1 found for phase2 to use
+#endif
+#if __SIZEOF_POINTER__ == 4
+ // The implementation of _Unwind_Exception uses an attribute mode on the
+ // above fields which has the side effect of causing this whole struct to
+ // round up to 32 bytes in size (48 with SEH). To be more explicit, we add
+ // pad fields added for binary compatibility.
+ uint32_t reserved[3];
+#endif
+ // The Itanium ABI requires that _Unwind_Exception objects are "double-word
+ // aligned". GCC has interpreted this to mean "use the maximum useful
+ // alignment for the target"; so do we.
+} __attribute__((__aligned__));
+
+typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(
+ int version, _Unwind_Action actions, uint64_t exceptionClass,
+ _Unwind_Exception *exceptionObject, struct _Unwind_Context *context);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// The following are the base functions documented by the C++ ABI
+//
+#ifdef __USING_SJLJ_EXCEPTIONS__
+extern _Unwind_Reason_Code
+ _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
+extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
+#else
+extern _Unwind_Reason_Code
+ _Unwind_RaiseException(_Unwind_Exception *exception_object);
+extern void _Unwind_Resume(_Unwind_Exception *exception_object);
+#endif
+extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
+
+
+extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
+extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
+ uintptr_t new_value);
+extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
+extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __ITANIUM_UNWIND_H__
)
endif()
+if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
+ list(APPEND LIBUNWIND_CXX_SOURCES
+ Unwind_AIXExtras.cpp
+ )
+endif()
+
set(LIBUNWIND_C_SOURCES
UnwindLevel1.c
UnwindLevel1-gcc-ext.c
)
# See add_asm_sources() in compiler-rt for explanation of this workaround.
-if((APPLE AND CMAKE_VERSION VERSION_LESS 3.19) OR (MINGW AND CMAKE_VERSION VERSION_LESS 3.17))
+# 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()
AddressSpace.hpp
assembly.h
CompactUnwinder.hpp
+ cet_unwind.h
config.h
dwarf2.h
DwarfInstructions.hpp
UnwindCursor.hpp
../include/libunwind.h
../include/unwind.h
+ ../include/unwind_itanium.h
+ ../include/unwind_arm_ehabi.h
)
if(APPLE)
list(APPEND LIBUNWIND_HEADERS
endif()
# Setup flags.
-if (LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG)
+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)
add_library_flags_if(MINGW "${MINGW_LIBRARIES}")
if (LIBUNWIND_ENABLE_SHARED AND
- NOT (LIBUNWIND_SUPPORTS_FNO_EXCEPTIONS_FLAG AND
- LIBUNWIND_SUPPORTS_FUNWIND_TABLES_FLAG))
+ NOT (CXX_SUPPORTS_FNO_EXCEPTIONS_FLAG AND
+ CXX_SUPPORTS_FUNWIND_TABLES_FLAG))
message(FATAL_ERROR
"Compiler doesn't support generation of unwind tables if exception "
"support is disabled. Building libunwind DSO with runtime dependency "
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
# Build the shared library.
+add_library(unwind_shared_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
+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})
+set_target_properties(unwind_shared_objects
+ PROPERTIES
+ CXX_EXTENSIONS OFF
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED ON
+ COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
+)
+if (CMAKE_POSITION_INDEPENDENT_CODE OR NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
+ set_target_properties(unwind_shared_objects PROPERTIES POSITION_INDEPENDENT_CODE ON) # must set manually because it's an object library
+endif()
+
if (LIBUNWIND_ENABLE_SHARED)
- add_library(unwind_shared SHARED ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
- if(CMAKE_C_COMPILER_ID STREQUAL MSVC)
- target_compile_options(unwind_shared PRIVATE /GR-)
- else()
- target_compile_options(unwind_shared PRIVATE -fno-rtti)
- endif()
- target_link_libraries(unwind_shared PRIVATE ${LIBUNWIND_LIBRARIES})
+ add_library(unwind_shared SHARED)
+ target_link_libraries(unwind_shared PUBLIC unwind_shared_objects)
set_target_properties(unwind_shared
PROPERTIES
- CXX_EXTENSIONS OFF
- CXX_STANDARD 11
- CXX_STANDARD_REQUIRED ON
- COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
LINKER_LANGUAGE C
- OUTPUT_NAME "unwind"
+ OUTPUT_NAME "${LIBUNWIND_SHARED_OUTPUT_NAME}"
VERSION "1.0"
SOVERSION "1"
- POSITION_INDEPENDENT_CODE ON
)
+
list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared")
if (LIBUNWIND_INSTALL_SHARED_LIBRARY)
list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared")
endif()
# Build the static library.
+add_library(unwind_static_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
+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})
+set_target_properties(unwind_static_objects
+ PROPERTIES
+ CXX_EXTENSIONS OFF
+ CXX_STANDARD 11
+ 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_compile_definitions(unwind_static_objects PRIVATE _LIBUNWIND_HIDE_SYMBOLS)
+endif()
+
if (LIBUNWIND_ENABLE_STATIC)
- add_library(unwind_static STATIC ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
- if(CMAKE_C_COMPILER_ID STREQUAL MSVC)
- target_compile_options(unwind_static PRIVATE /GR-)
- else()
- target_compile_options(unwind_static PRIVATE -fno-rtti)
- endif()
- target_link_libraries(unwind_static PRIVATE ${LIBUNWIND_LIBRARIES})
+ add_library(unwind_static STATIC)
+ target_link_libraries(unwind_static PUBLIC unwind_static_objects)
set_target_properties(unwind_static
PROPERTIES
- CXX_EXTENSIONS OFF
- CXX_STANDARD 11
- CXX_STANDARD_REQUIRED ON
- COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
LINKER_LANGUAGE C
- OUTPUT_NAME "unwind"
- POSITION_INDEPENDENT_CODE ON
+ OUTPUT_NAME "${LIBUNWIND_STATIC_OUTPUT_NAME}"
)
- if(LIBUNWIND_HIDE_SYMBOLS)
- append_flags_if_supported(UNWIND_STATIC_LIBRARY_FLAGS -fvisibility=hidden)
- append_flags_if_supported(UNWIND_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden)
- target_compile_options(unwind_static PRIVATE ${UNWIND_STATIC_LIBRARY_FLAGS})
- target_compile_definitions(unwind_static PRIVATE _LIBUNWIND_HIDE_SYMBOLS)
- endif()
-
list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static")
if (LIBUNWIND_INSTALL_STATIC_LIBRARY)
list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static")
install(TARGETS ${LIBUNWIND_INSTALL_TARGETS}
LIBRARY DESTINATION ${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind
ARCHIVE DESTINATION ${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind
- RUNTIME DESTINATION bin COMPONENT unwind)
+ RUNTIME DESTINATION ${LIBUNWIND_INSTALL_RUNTIME_DIR} COMPONENT unwind)
endif()
if (NOT CMAKE_CONFIGURATION_TYPES AND LIBUNWIND_INSTALL_LIBRARY)
-DCMAKE_INSTALL_COMPONENT=unwind
-DCMAKE_INSTALL_DO_STRIP=1
-P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake")
+ if(LIBUNWIND_INSTALL_HEADERS)
+ add_dependencies(install-unwind install-unwind-headers)
+ add_dependencies(install-unwind-stripped install-unwind-headers-stripped)
+ endif()
endif()
-//===-------------------------- CompactUnwinder.hpp -----------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
#include <mach-o/compact_unwind_encoding.h>
#include "Registers.hpp"
+#include "libunwind_ext.h"
#define EXTRACT_BITS(value, mask) \
((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1))
uint64_t savedRegisterLoc = registers.getSP() + stackSize;
if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
- registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
- registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
- registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
- registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
- registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D8,
+ registers.setFloatRegister(UNW_AARCH64_V8,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D9,
+ registers.setFloatRegister(UNW_AARCH64_V9,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D10,
+ registers.setFloatRegister(UNW_AARCH64_V10,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D11,
+ registers.setFloatRegister(UNW_AARCH64_V11,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D12,
+ registers.setFloatRegister(UNW_AARCH64_V12,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D13,
+ registers.setFloatRegister(UNW_AARCH64_V13,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D14,
+ registers.setFloatRegister(UNW_AARCH64_V14,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D15,
+ registers.setFloatRegister(UNW_AARCH64_V15,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
registers.setSP(savedRegisterLoc);
// set pc to be value in lr
- registers.setIP(registers.getRegister(UNW_ARM64_LR));
+ registers.setIP(registers.getRegister(UNW_AARCH64_LR));
return UNW_STEP_SUCCESS;
}
uint64_t savedRegisterLoc = registers.getFP() - 8;
if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
- registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
- registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
- registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
- registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
- registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc));
+ registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D8,
+ registers.setFloatRegister(UNW_AARCH64_V8,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D9,
+ registers.setFloatRegister(UNW_AARCH64_V9,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D10,
+ registers.setFloatRegister(UNW_AARCH64_V10,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D11,
+ registers.setFloatRegister(UNW_AARCH64_V11,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D12,
+ registers.setFloatRegister(UNW_AARCH64_V12,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D13,
+ registers.setFloatRegister(UNW_AARCH64_V13,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
- registers.setFloatRegister(UNW_ARM64_D14,
+ registers.setFloatRegister(UNW_AARCH64_V14,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
- registers.setFloatRegister(UNW_ARM64_D15,
+ registers.setFloatRegister(UNW_AARCH64_V15,
addressSpace.getDouble(savedRegisterLoc));
savedRegisterLoc -= 8;
}
-//===----------------------------- Registers.hpp --------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
-//===--------------------------- Unwind-EHABI.cpp -------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
if (result != _URC_CONTINUE_UNWIND)
return result;
- if (__unw_step(reinterpret_cast<unw_cursor_t *>(context)) != UNW_STEP_SUCCESS)
+ switch (__unw_step(reinterpret_cast<unw_cursor_t *>(context))) {
+ case UNW_STEP_SUCCESS:
+ return _URC_CONTINUE_UNWIND;
+ case UNW_STEP_END:
+ return _URC_END_OF_STACK;
+ default:
return _URC_FAILURE;
- return _URC_CONTINUE_UNWIND;
+ }
}
// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /
} else {
// 6.3: ARM Compact Model
//
- // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded
+ // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeed
// by format:
Descriptor::Format format =
static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);
size_t offset, size_t len) {
bool wrotePC = false;
bool finish = false;
+ bool hasReturnAddrAuthCode = false;
while (offset < len && !finish) {
uint8_t byte = getByte(data, offset++);
if ((byte & 0x80) == 0) {
break;
}
case 0xb4:
+ hasReturnAddrAuthCode = true;
+ _Unwind_VRS_Pop(context, _UVRSC_PSEUDO,
+ 0 /* Return Address Auth Code */, _UVRSD_UINT32);
+ break;
case 0xb5:
case 0xb6:
case 0xb7:
if (!wrotePC) {
uint32_t lr;
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr);
+#ifdef __ARM_FEATURE_PAUTH
+ if (hasReturnAddrAuthCode) {
+ uint32_t sp;
+ uint32_t pac;
+ _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
+ _Unwind_VRS_Get(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
+ __asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
+ }
+#else
+ (void)hasReturnAddrAuthCode;
+#endif
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
}
return _URC_CONTINUE_UNWIND;
return _URC_FATAL_PHASE1_ERROR;
}
+#ifndef NDEBUG
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
+#endif
// If there is a personality routine, ask it if it will want to stop at
// this frame.
return _URC_FATAL_PHASE2_ERROR;
}
+#ifndef NDEBUG
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
functionName, sp, frameInfo.lsda,
frameInfo.handler);
}
+#endif
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
_Unwind_Personality_Fn p =
- (_Unwind_Personality_Fn)(long)(frameInfo.handler);
+ (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
// EHABI #7.2
exception_object->pr_cache.fnstart = frameInfo.start_ip;
return _URC_FATAL_PHASE2_ERROR;
}
+static _Unwind_Reason_Code
+unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
+ _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
+ void *stop_parameter) {
+ bool endOfStack = false;
+ // See comment at the start of unwind_phase1 regarding VRS integrity.
+ __unw_init_local(cursor, uc);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_force(ex_ojb=%p)",
+ static_cast<void *>(exception_object));
+ // Walk each frame until we reach where search phase said to stop
+ while (!endOfStack) {
+ // 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 "
+ "failed => _URC_END_OF_STACK",
+ (void *)exception_object);
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+
+#ifndef NDEBUG
+ // When tracing, print state information.
+ if (_LIBUNWIND_TRACING_UNWINDING) {
+ char functionBuf[512];
+ const char *functionName = functionBuf;
+ unw_word_t offset;
+ if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
+ &offset) != UNW_ESUCCESS) ||
+ (frameInfo.start_ip + offset > frameInfo.end_ip))
+ functionName = ".anonymous.";
+ _LIBUNWIND_TRACE_UNWINDING(
+ "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
+ (void *)exception_object, frameInfo.start_ip, functionName,
+ frameInfo.lsda, frameInfo.handler);
+ }
+#endif
+
+ // Call stop function at each frame.
+ _Unwind_Action action =
+ (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
+ _Unwind_Reason_Code stopResult =
+ (*stop)(1, action, exception_object->exception_class, exception_object,
+ (_Unwind_Context *)(cursor), stop_parameter);
+ _LIBUNWIND_TRACE_UNWINDING(
+ "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
+ (void *)exception_object, stopResult);
+ if (stopResult != _URC_NO_REASON) {
+ _LIBUNWIND_TRACE_UNWINDING(
+ "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
+ (void *)exception_object);
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+
+ // If there is a personality routine, tell it we are unwinding.
+ if (frameInfo.handler != 0) {
+ _Unwind_Personality_Fn p =
+ (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
+ struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
+ // EHABI #7.2
+ exception_object->pr_cache.fnstart = frameInfo.start_ip;
+ exception_object->pr_cache.ehtp =
+ (_Unwind_EHT_Header *)frameInfo.unwind_info;
+ exception_object->pr_cache.additional = frameInfo.flags;
+ _Unwind_Reason_Code personalityResult =
+ (*p)(_US_FORCE_UNWIND | _US_UNWIND_FRAME_STARTING, exception_object,
+ context);
+ switch (personalityResult) {
+ case _URC_CONTINUE_UNWIND:
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ "personality returned "
+ "_URC_CONTINUE_UNWIND",
+ (void *)exception_object);
+ // Destructors called, continue unwinding
+ break;
+ case _URC_INSTALL_CONTEXT:
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ "personality returned "
+ "_URC_INSTALL_CONTEXT",
+ (void *)exception_object);
+ // We may get control back if landing pad calls _Unwind_Resume().
+ __unw_resume(cursor);
+ break;
+ case _URC_END_OF_STACK:
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ "personality returned "
+ "_URC_END_OF_STACK",
+ (void *)exception_object);
+ // Personalty routine did the step and it can't step forward.
+ endOfStack = true;
+ break;
+ default:
+ // Personality routine returned an unknown result code.
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ "personality returned %d, "
+ "_URC_FATAL_PHASE2_ERROR",
+ (void *)exception_object, personalityResult);
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+ }
+ }
+
+ // Call stop function one last time and tell it we've reached the end
+ // of the stack.
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
+ "function with _UA_END_OF_STACK",
+ (void *)exception_object);
+ _Unwind_Action lastAction =
+ (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
+ (*stop)(1, lastAction, exception_object->exception_class, exception_object,
+ (struct _Unwind_Context *)(cursor), stop_parameter);
+
+ // Clean up phase did not resume at the frame that the search phase said it
+ // would.
+ return _URC_FATAL_PHASE2_ERROR;
+}
+
/// Called by __cxa_throw. Only returns if there is a fatal error.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
-/// geneated user code. All other _Unwind_* routines are called
+/// generated user code. All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
unw_cursor_t cursor;
__unw_getcontext(&uc);
- // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
- // which is in the same position as private_1 below.
- // TODO(ajwong): Who wronte the above? Why is it true?
- unwind_phase2(&uc, &cursor, exception_object, true);
+ if (exception_object->unwinder_cache.reserved1)
+ unwind_phase2_forced(
+ &uc, &cursor, exception_object,
+ (_Unwind_Stop_Fn)exception_object->unwinder_cache.reserved1,
+ (void *)exception_object->unwinder_cache.reserved3);
+ else
+ unwind_phase2(&uc, &cursor, exception_object, true);
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
case _UVRSC_WMMXD:
break;
#endif
+ case _UVRSC_PSEUDO:
+ // There's only one pseudo-register, PAC, with regno == 0.
+ if (representation != _UVRSD_UINT32 || regno != 0)
+ return _UVRSR_FAILED;
+ return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE),
+ *(unw_word_t *)valuep) == UNW_ESUCCESS
+ ? _UVRSR_OK
+ : _UVRSR_FAILED;
+ break;
}
_LIBUNWIND_ABORT("unsupported register class");
}
case _UVRSC_WMMXD:
break;
#endif
+ case _UVRSC_PSEUDO:
+ // There's only one pseudo-register, PAC, with regno == 0.
+ if (representation != _UVRSD_UINT32 || regno != 0)
+ return _UVRSR_FAILED;
+ return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE),
+ (unw_word_t *)valuep) == UNW_ESUCCESS
+ ? _UVRSR_OK
+ : _UVRSR_FAILED;
+ break;
}
_LIBUNWIND_ABORT("unsupported register class");
}
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
&sp);
}
+ case _UVRSC_PSEUDO: {
+ if (representation != _UVRSD_UINT32 || discriminator != 0)
+ return _UVRSR_FAILED;
+ // Return Address Authentication code (PAC) - discriminator 0
+ uint32_t *sp;
+ if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
+ &sp) != _UVRSR_OK) {
+ return _UVRSR_FAILED;
+ }
+ uint32_t pac = *sp++;
+ _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
+ return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
+ }
}
_LIBUNWIND_ABORT("unsupported register class");
}
+/// Not used by C++.
+/// Unwinds stack, calling "stop" function at each frame.
+/// Could be used to implement longjmp().
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
+ void *stop_parameter) {
+ _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
+ (void *)exception_object, (void *)(uintptr_t)stop);
+ unw_context_t uc;
+ unw_cursor_t cursor;
+ __unw_getcontext(&uc);
+
+ // Mark that this is a forced unwind, so _Unwind_Resume() can do
+ // the right thing.
+ exception_object->unwinder_cache.reserved1 = (uintptr_t)stop;
+ exception_object->unwinder_cache.reserved3 = (uintptr_t)stop_parameter;
+
+ return unwind_phase2_forced(&uc, &cursor, exception_object, stop,
+ stop_parameter);
+}
+
/// Called by personality handler during phase 2 to find the start of the
/// function.
_LIBUNWIND_EXPORT uintptr_t
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
__gnu_unwind_frame(_Unwind_Exception *exception_object,
struct _Unwind_Context *context) {
+ (void)exception_object;
unw_cursor_t *cursor = (unw_cursor_t *)context;
- if (__unw_step(cursor) != UNW_STEP_SUCCESS)
+ switch (__unw_step(cursor)) {
+ case UNW_STEP_SUCCESS:
+ return _URC_OK;
+ case UNW_STEP_END:
+ return _URC_END_OF_STACK;
+ default:
return _URC_FAILURE;
- return _URC_OK;
+ }
}
#endif // defined(_LIBUNWIND_ARM_EHABI)
-//===------------------------- Unwind-EHABI.hpp ---------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
-//===--------------------------- Unwind-seh.cpp ---------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
if (!ctx) {
__unw_init_seh(&cursor, disp->ContextRecord);
__unw_seh_set_disp_ctx(&cursor, disp);
- __unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc - 1);
+ __unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc);
ctx = (struct _Unwind_Context *)&cursor;
if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
// If we were called by __libunwind_seh_personality(), indicate that
// a handler was found; otherwise, initiate phase 2 by unwinding.
if (ours && ms_exc->NumberParameters > 1)
- return 4 /* ExecptionExecuteHandler in mingw */;
+ return 4 /* ExceptionExecuteHandler in mingw */;
// This should never happen in phase 2.
if (IS_UNWINDING(ms_exc->ExceptionFlags))
_LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
// a handler was found; otherwise, it's time to initiate a collided
// unwind to the target.
if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
- return 4 /* ExecptionExecuteHandler in mingw */;
+ return 4 /* ExceptionExecuteHandler in mingw */;
// This should never happen in phase 1.
if (!IS_UNWINDING(ms_exc->ExceptionFlags))
_LIBUNWIND_ABORT("Personality installed context during phase 1!");
__unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]);
#elif defined(__aarch64__)
exc->private_[2] = disp->TargetPc;
- __unw_get_reg(&cursor, UNW_ARM64_X0, &retval);
- __unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]);
+ __unw_get_reg(&cursor, UNW_AARCH64_X0, &retval);
+ __unw_get_reg(&cursor, UNW_AARCH64_X1, &exc->private_[3]);
#endif
__unw_get_reg(&cursor, UNW_REG_IP, &target);
ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
return _URC_FATAL_PHASE2_ERROR;
}
+#ifndef NDEBUG
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
- ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
+ "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
+#endif
// Call stop function at each frame.
_Unwind_Action action =
/// may force a jump to a landing pad in that function; the landing
/// pad code may then call \c _Unwind_Resume() to continue with the
/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler
-/// geneated user code. All other \c _Unwind_* routines are called
+/// generated user code. All other \c _Unwind_* routines are called
/// by the C++ runtime \c __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
-//===--------------------------- Unwind-sjlj.c ----------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
struct _Unwind_FunctionContext *prev;
#if defined(__ve__)
- // VE requires to store 64 bit pointers in the buffer for SjLj execption.
+ // VE requires to store 64 bit pointers in the buffer for SjLj exception.
// We expand the size of values defined here. This size must be matched
// to the size returned by TargetMachine::getSjLjDataSize().
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
-/// geneated user code. All other _Unwind_* routines are called
+/// generated user code. All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Re-throwing an exception is implemented by having the code call
// std::terminate()
}
- // Call through to _Unwind_Resume() which distiguishes between forced and
+ // Call through to _Unwind_Resume() which distinguishes between forced and
// regular exceptions.
_Unwind_SjLj_Resume(exception_object);
_LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
-//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
#include "Unwind-EHABI.h"
#include "unwind.h"
+#if defined(_AIX)
+#include <sys/debug.h>
+#endif
+
#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
-#define private_1 private_[0]
+#define PRIVATE_1 private_[0]
+#elif defined(_LIBUNWIND_ARM_EHABI)
+#define PRIVATE_1 unwinder_cache.reserved1
+#else
+#define PRIVATE_1 private_1
#endif
/// Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
-#if defined(_LIBUNWIND_ARM_EHABI)
- _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
- (void *)exception_object,
- (long)exception_object->unwinder_cache.reserved1);
-#else
- _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR,
- (void *)exception_object,
- (intptr_t)exception_object->private_1);
-#endif
+ _LIBUNWIND_TRACE_API(
+ "_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR,
+ (void *)exception_object, (intptr_t)exception_object->PRIVATE_1);
-#if defined(_LIBUNWIND_ARM_EHABI)
- // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
- // which is in the same position as private_1 below.
- return _Unwind_RaiseException(exception_object);
-#else
// If this is non-forced and a stopping place was found, then this is a
// re-throw.
// Call _Unwind_RaiseException() as if this was a new exception
- if (exception_object->private_1 == 0) {
+ if (exception_object->PRIVATE_1 == 0) {
return _Unwind_RaiseException(exception_object);
// Will return if there is no catch clause, so that __cxa_rethrow can call
// std::terminate().
}
- // Call through to _Unwind_Resume() which distiguishes between forced and
+ // Call through to _Unwind_Resume() which distinguishes between forced and
// regular exceptions.
_Unwind_Resume(exception_object);
_LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()"
" which unexpectedly returned");
-#endif
}
-
/// Called by personality handler during phase 2 to get base address for data
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
- (void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
+#if defined(_AIX)
+ return unw_get_data_rel_base((unw_cursor_t *)context);
+#else
+ (void)context;
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
+#endif
}
-
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
/// specified code address "pc".
_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
_LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc);
+#if defined(_AIX)
+ if (pc == NULL)
+ return NULL;
+
+ // Get the start address of the enclosing function from the function's
+ // traceback table.
+ uint32_t *p = (uint32_t *)pc;
+
+ // Keep looking forward until a word of 0 is found. The traceback
+ // table starts at the following word.
+ while (*p)
+ ++p;
+ struct tbtable *TBTable = (struct tbtable *)(p + 1);
+
+ // Get the address of the traceback table extension.
+ p = (uint32_t *)&TBTable->tb_ext;
+
+ // Skip field parminfo if it exists.
+ if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
+ ++p;
+
+ if (TBTable->tb.has_tboff)
+ // *p contains the offset from the function start to traceback table.
+ return (void *)((uintptr_t)TBTable - *p - sizeof(uint32_t));
+ return NULL;
+#else
// This is slow, but works.
// We create an unwind cursor then alter the IP to be pc
unw_cursor_t cursor;
return (void *)(intptr_t) info.start_ip;
else
return NULL;
+#endif
}
/// Walk every frame and call trace function at each one. If trace function
// Create a mock exception object for force unwinding.
_Unwind_Exception ex;
memset(&ex, '\0', sizeof(ex));
- ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0
+ strcpy((char *)&ex.exception_class, "CLNGUNW");
#endif
// walk each frame
-//===------------------------- UnwindLevel1.c -----------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
#include <stdio.h>
#include <string.h>
+#include "cet_unwind.h"
#include "config.h"
#include "libunwind.h"
#include "libunwind_ext.h"
#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
+// When CET is enabled, each "call" instruction will push return address to
+// CET shadow stack, each "ret" instruction will pop current CET shadow stack
+// top and compare it with target address which program will return.
+// In exception handing, some stack frames will be skipped before jumping to
+// landing pad and we must adjust CET shadow stack accordingly.
+// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we
+// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using
+// a regular function call to avoid pushing to CET shadow stack again.
+#if !defined(_LIBUNWIND_USE_CET)
+#define __unw_phase2_resume(cursor, fn) \
+ do { \
+ (void)fn; \
+ __unw_resume((cursor)); \
+ } while (0)
+#elif defined(_LIBUNWIND_TARGET_I386)
+#define __cet_ss_step_size 4
+#define __unw_phase2_resume(cursor, fn) \
+ do { \
+ _LIBUNWIND_POP_CET_SSP((fn)); \
+ void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
+ void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
+ __asm__ volatile("push %%edi\n\t" \
+ "sub $4, %%esp\n\t" \
+ "jmp *%%edx\n\t" :: "D"(cetRegContext), \
+ "d"(cetJumpAddress)); \
+ } while (0)
+#elif defined(_LIBUNWIND_TARGET_X86_64)
+#define __cet_ss_step_size 8
+#define __unw_phase2_resume(cursor, fn) \
+ do { \
+ _LIBUNWIND_POP_CET_SSP((fn)); \
+ void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
+ void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
+ __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \
+ "d"(cetJumpAddress)); \
+ } while (0)
+#endif
+
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
__unw_init_local(cursor, uc);
int stepResult = __unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): __unw_step() reached "
+ "unwind_phase1(ex_obj=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): __unw_step failed => "
+ "unwind_phase1(ex_obj=%p): __unw_step failed => "
"_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
unw_word_t sp;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): __unw_get_proc_info "
+ "unwind_phase1(ex_obj=%p): __unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
+#ifndef NDEBUG
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
unw_word_t pc;
__unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
+ "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
(void *)exception_object, pc, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
+#endif
// If there is a personality routine, ask it if it will want to stop at
// this frame.
_Unwind_Personality_Fn p =
(_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): calling personality function %p",
+ "unwind_phase1(ex_obj=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
__unw_get_reg(cursor, UNW_REG_SP, &sp);
exception_object->private_2 = (uintptr_t)sp;
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
+ "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND",
(void *)exception_object);
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
+ "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
// continue unwinding
break;
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
+ "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
}
return _URC_NO_REASON;
}
-
+extern int __unw_step_stage2(unw_cursor_t *);
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
__unw_init_local(cursor, uc);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
(void *)exception_object);
+ // uc is initialized by __unw_getcontext in the parent frame. The first stack
+ // frame walked is unwind_phase2.
+ unsigned framesWalked = 1;
+#ifdef _LIBUNWIND_USE_CET
+ unsigned long shadowStackTop = _get_ssp();
+#endif
// Walk each frame until we reach where search phase said to stop.
while (true) {
// Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
- int stepResult = __unw_step(cursor);
+ int stepResult = __unw_step_stage2(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): __unw_step() reached "
+ "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): __unw_step failed => "
+ "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "
"_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
__unw_get_reg(cursor, UNW_REG_SP, &sp);
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): __unw_get_proc_info "
+ "unwind_phase2(ex_obj=%p): __unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
+#ifndef NDEBUG
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR
", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip,
functionName, sp, frameInfo.lsda,
frameInfo.handler);
}
-
+#endif
+
+// In CET enabled environment, we check return address stored in normal stack
+// against return address stored in CET shadow stack, if the 2 addresses don't
+// match, it means return address in normal stack has been corrupted, we return
+// _URC_FATAL_PHASE2_ERROR.
+#ifdef _LIBUNWIND_USE_CET
+ if (shadowStackTop != 0) {
+ unw_word_t retInNormalStack;
+ __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
+ unsigned long retInShadowStack = *(
+ unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked);
+ if (retInNormalStack != retInShadowStack)
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+#endif
+ ++framesWalked;
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
_Unwind_Personality_Fn p =
case _URC_CONTINUE_UNWIND:
// Continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
+ "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
if (sp == exception_object->private_2) {
// Phase 1 said we would stop at this frame, but we did not...
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
+ "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",
(void *)exception_object);
// Personality routine says to transfer control to landing pad.
// We may get control back if landing pad calls _Unwind_Resume().
unw_word_t pc;
__unw_get_reg(cursor, UNW_REG_IP, &pc);
__unw_get_reg(cursor, UNW_REG_SP, &sp);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "
"user code with ip=0x%" PRIxPTR
", sp=0x%" PRIxPTR,
(void *)exception_object, pc, sp);
}
- __unw_resume(cursor);
- // __unw_resume() only returns if there was an error.
+
+ __unw_phase2_resume(cursor, framesWalked);
+ // __unw_phase2_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
default:
// Personality routine returned an unknown result code.
_Unwind_Stop_Fn stop, void *stop_parameter) {
__unw_init_local(cursor, uc);
+ // uc is initialized by __unw_getcontext in the parent frame. The first stack
+ // frame walked is unwind_phase2_forced.
+ unsigned framesWalked = 1;
// Walk each frame until we reach where search phase said to stop
- while (__unw_step(cursor) > 0) {
+ while (__unw_step_stage2(cursor) > 0) {
// 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 "
- "failed => _URC_END_OF_STACK",
- (void *)exception_object);
+ _LIBUNWIND_TRACE_UNWINDING(
+ "unwind_phase2_forced(ex_obj=%p): __unw_step_stage2 "
+ "failed => _URC_END_OF_STACK",
+ (void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
+#ifndef NDEBUG
// When tracing, print state information.
if (_LIBUNWIND_TRACING_UNWINDING) {
char functionBuf[512];
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
+#endif
// Call stop function at each frame.
_Unwind_Action action =
(*stop)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor), stop_parameter);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
+ "unwind_phase2_forced(ex_obj=%p): stop function returned %d",
(void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
+ "unwind_phase2_forced(ex_obj=%p): stopped by stop function",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
+ ++framesWalked;
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
_Unwind_Personality_Fn p =
(_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
+ "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
"personality returned "
"_URC_CONTINUE_UNWIND",
(void *)exception_object);
// Destructors called, continue unwinding
break;
case _URC_INSTALL_CONTEXT:
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
"personality returned "
"_URC_INSTALL_CONTEXT",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
- __unw_resume(cursor);
+ __unw_phase2_resume(cursor, framesWalked);
break;
default:
// Personality routine returned an unknown result code.
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
(void *)exception_object, personalityResult);
// Call stop function one last time and tell it we've reached the end
// of the stack.
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "
"function with _UA_END_OF_STACK",
(void *)exception_object);
_Unwind_Action lastAction =
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
-/// geneated user code. All other _Unwind_* routines are called
+/// generated user code. All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
_LIBUNWIND_TRACE_API(
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
+#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
if (result != 0) {
if (*((uint8_t *)result) != 0xFF)
_LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
result);
}
+#endif
return result;
}
--- /dev/null
+//===--------------------- Unwind_AIXExtras.cpp -------------------------===//
+//
+// 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
+//
+//
+//===----------------------------------------------------------------------===//
+
+// This file is only used for AIX.
+#if defined(_AIX)
+
+#include "config.h"
+#include "libunwind_ext.h"
+#include <sys/debug.h>
+
+namespace libunwind {
+// getFuncNameFromTBTable
+// Get the function name from its traceback table.
+char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen,
+ unw_word_t *Offset) {
+ uint32_t *p = reinterpret_cast<uint32_t *>(Pc);
+ *Offset = 0;
+
+ // 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<tbtable *>(p + 1);
+
+ if (!TBTable->tb.name_present)
+ return NULL;
+
+ // Get to the name of the function.
+ p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
+
+ // Skip field parminfo if it exists.
+ if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
+ p++;
+
+ // If the tb_offset field exists, get the offset from the start of
+ // the function to pc. Skip the field.
+ if (TBTable->tb.has_tboff) {
+ unw_word_t StartIp =
+ reinterpret_cast<uintptr_t>(TBTable) - *p - sizeof(uint32_t);
+ *Offset = Pc - StartIp;
+ 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<uint16_t *>(p));
+ return reinterpret_cast<char *>(p) + sizeof(uint16_t);
+}
+} // namespace libunwind
+#endif // defined(_AIX)
-//===--------------------- Unwind_AppleExtras.cpp -------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBUNWIND_CET_UNWIND_H
+#define LIBUNWIND_CET_UNWIND_H
+
+#include "libunwind.h"
+
+// Currently, CET is implemented on Linux x86 platforms.
+#if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__)
+#define _LIBUNWIND_USE_CET 1
+#endif
+
+#if defined(_LIBUNWIND_USE_CET)
+#include <cet.h>
+#include <immintrin.h>
+
+#define _LIBUNWIND_POP_CET_SSP(x) \
+ do { \
+ unsigned long ssp = _get_ssp(); \
+ if (ssp != 0) { \
+ unsigned int tmp = (x); \
+ while (tmp > 255) { \
+ _inc_ssp(255); \
+ tmp -= 255; \
+ } \
+ _inc_ssp(tmp); \
+ } \
+ } while (0)
+#endif
+
+extern void *__libunwind_cet_get_registers(unw_cursor_t *);
+extern void *__libunwind_cet_get_jump_target(void);
+
+#endif
-//===------------------------------- dwarf2.h -----------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
-//===------------------------ libunwind_ext.h -----------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
extern int __unw_is_signal_frame(unw_cursor_t *);
extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
+#if defined(_AIX)
+extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *);
+#endif
+
// SPI
extern void __unw_iterate_dwarf_unwind_cache(void (*func)(
unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
extern void __unw_add_dynamic_fde(unw_word_t fde);
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);
+
#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,