summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2019-03-07 04:15:03 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-03-07 04:15:03 +0000
commitc84e52d2279c3ba0017511b64515ea56c18e327d (patch)
treeeee7241cdd58a861b1eb25522165c2dc06dad92e
parentc7c8c925e9dd70c1faff39d23ac9fc22b9b86d92 (diff)
parent6352e01a22119b918b6bc30e5882b5a6f81cff80 (diff)
downloadlibunwind_llvm-android10-s1-release.tar.gz
Snap for 5357520 from 6352e01a22119b918b6bc30e5882b5a6f81cff80 to qt-releaseandroid-vts-10.0_r9android-vts-10.0_r8android-vts-10.0_r7android-vts-10.0_r6android-vts-10.0_r5android-vts-10.0_r4android-vts-10.0_r3android-vts-10.0_r2android-vts-10.0_r16android-vts-10.0_r15android-vts-10.0_r14android-vts-10.0_r13android-vts-10.0_r12android-vts-10.0_r11android-vts-10.0_r10android-vts-10.0_r1android-security-10.0.0_r75android-security-10.0.0_r74android-security-10.0.0_r73android-security-10.0.0_r72android-security-10.0.0_r71android-security-10.0.0_r70android-security-10.0.0_r69android-security-10.0.0_r68android-security-10.0.0_r67android-security-10.0.0_r66android-security-10.0.0_r65android-security-10.0.0_r64android-security-10.0.0_r63android-security-10.0.0_r62android-security-10.0.0_r61android-security-10.0.0_r60android-security-10.0.0_r59android-security-10.0.0_r58android-security-10.0.0_r57android-security-10.0.0_r56android-security-10.0.0_r55android-security-10.0.0_r54android-security-10.0.0_r53android-security-10.0.0_r52android-security-10.0.0_r51android-security-10.0.0_r50android-security-10.0.0_r49android-security-10.0.0_r48android-mainline-10.0.0_r3android-mainline-10.0.0_r2android-mainline-10.0.0_r1android-cts-10.0_r9android-cts-10.0_r8android-cts-10.0_r7android-cts-10.0_r6android-cts-10.0_r5android-cts-10.0_r4android-cts-10.0_r3android-cts-10.0_r2android-cts-10.0_r16android-cts-10.0_r15android-cts-10.0_r14android-cts-10.0_r13android-cts-10.0_r12android-cts-10.0_r11android-cts-10.0_r10android-cts-10.0_r1android-10.0.0_r6android-10.0.0_r5android-10.0.0_r47android-10.0.0_r46android-10.0.0_r4android-10.0.0_r3android-10.0.0_r2android-10.0.0_r17android-10.0.0_r11android-10.0.0_r10android-10.0.0_r1android10-tests-releaseandroid10-security-releaseandroid10-s3-releaseandroid10-s2-releaseandroid10-s1-releaseandroid10-releaseandroid10-mainline-releaseandroid10-mainline-a-releaseandroid10-gsi
Change-Id: I421e938dad4c42c45ec5185ab4613134bb8d65f6
-rw-r--r--.arcconfig2
-rw-r--r--CMakeLists.txt173
-rw-r--r--LICENSE.TXT239
-rw-r--r--cmake/Modules/HandleCompilerRT.cmake6
-rw-r--r--cmake/config-ix.cmake11
-rw-r--r--docs/BuildingLibunwind.rst12
-rw-r--r--docs/conf.py7
-rw-r--r--docs/index.rst3
-rw-r--r--include/__libunwind_config.h79
-rw-r--r--include/libunwind.h293
-rw-r--r--include/mach-o/compact_unwind_encoding.h7
-rw-r--r--include/unwind.h36
-rw-r--r--src/AddressSpace.hpp218
-rw-r--r--src/CMakeLists.txt94
-rw-r--r--src/CompactUnwinder.hpp7
-rw-r--r--src/DwarfInstructions.hpp52
-rw-r--r--src/DwarfParser.hpp143
-rw-r--r--src/EHHeaderParser.hpp23
-rw-r--r--src/RWMutex.hpp7
-rw-r--r--src/Registers.hpp1188
-rw-r--r--src/Unwind-EHABI.cpp9
-rw-r--r--src/Unwind-EHABI.h7
-rw-r--r--src/Unwind-seh.cpp500
-rw-r--r--src/Unwind-sjlj.c110
-rw-r--r--src/UnwindCursor.hpp634
-rw-r--r--src/UnwindLevel1-gcc-ext.c25
-rw-r--r--src/UnwindLevel1.c12
-rw-r--r--src/UnwindRegistersRestore.S403
-rw-r--r--src/UnwindRegistersSave.S373
-rw-r--r--src/Unwind_AppleExtras.cpp7
-rw-r--r--src/assembly.h36
-rw-r--r--src/config.h28
-rw-r--r--src/dwarf2.h12
-rw-r--r--src/libunwind.cpp124
-rw-r--r--src/libunwind_ext.h7
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/alignment.pass.cpp7
-rw-r--r--test/libunwind/test/config.py7
-rw-r--r--test/lit.site.cfg.in19
39 files changed, 4208 insertions, 713 deletions
diff --git a/.arcconfig b/.arcconfig
index 97a4bf1..78ee8d3 100644
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,4 +1,4 @@
{
- "project_id" : "libunwind",
+ "repository.callsign" : "UNW",
"conduit_uri" : "https://reviews.llvm.org/"
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b28e4d0..debc847 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,27 +59,31 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
OUTPUT_VARIABLE CONFIG_OUTPUT
ERROR_QUIET)
if(NOT HAD_ERROR)
- string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
+ string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
+ file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH)
else()
- set(LLVM_CMAKE_PATH
- "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
+ file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE)
+ set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
endif()
else()
- message(FATAL_ERROR "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
- "Reconfigure with -DLLVM_CONFIG=path/to/llvm-config "
- "or -DLLVM_PATH=path/to/llvm-source-root.")
+ message(WARNING "UNSUPPORTED LIBUNWIND CONFIGURATION DETECTED: "
+ "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
+ "Reconfigure with -DLLVM_CONFIG=path/to/llvm-config "
+ "or -DLLVM_PATH=path/to/llvm-source-root.")
endif()
if (EXISTS ${LLVM_CMAKE_PATH})
+ # Enable warnings, otherwise -w gets added to the cflags by HandleLLVMOptions.
+ set(LLVM_ENABLE_WARNINGS ON)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
include("${LLVM_CMAKE_PATH}/HandleLLVMOptions.cmake")
else()
- message(FATAL_ERROR "Not found: ${LLVM_CMAKE_PATH}")
+ message(WARNING "Not found: ${LLVM_CMAKE_PATH}")
endif()
set(PACKAGE_NAME libunwind)
- set(PACKAGE_VERSION 5.0.0svn)
+ set(PACKAGE_VERSION 9.0.0svn)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
@@ -111,13 +115,13 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
else()
- set(LLVM_MAIN_SRC_DIR "${CMAKE_SOURCE_DIR}" CACHE PATH "Path to LLVM source tree")
set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
endif()
#===============================================================================
# Setup CMake Options
#===============================================================================
+include(CMakeDependentOption)
include(HandleCompilerRT)
# Define options.
@@ -136,9 +140,19 @@ option(LIBUNWIND_INCLUDE_DOCS "Build the libunwind documentation." ${LLVM_INCLUD
set(LIBUNWIND_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
"Define suffix of library directory name (32/64)")
option(LIBUNWIND_INSTALL_LIBRARY "Install the libunwind library." ON)
+cmake_dependent_option(LIBUNWIND_INSTALL_STATIC_LIBRARY
+ "Install the static libunwind library." ON
+ "LIBUNWIND_ENABLE_STATIC;LIBUNWIND_INSTALL_LIBRARY" OFF)
+cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY
+ "Install the shared libunwind library." ON
+ "LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF)
set(LIBUNWIND_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.")
if (NOT LIBUNWIND_ENABLE_SHARED AND NOT LIBUNWIND_ENABLE_STATIC)
message(FATAL_ERROR "libunwind must be built as either a shared or static library.")
@@ -153,6 +167,9 @@ elseif(LIBUNWIND_BUILD_32_BITS)
message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS=ON is not supported on this platform.")
endif()
+option(LIBUNWIND_HERMETIC_STATIC_LIBRARY
+ "Do not export any symbols from the static library." OFF)
+
#===============================================================================
# Configure System
#===============================================================================
@@ -165,7 +182,14 @@ set(CMAKE_MODULE_PATH
set(LIBUNWIND_COMPILER ${CMAKE_CXX_COMPILER})
set(LIBUNWIND_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBUNWIND_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
-if (LLVM_LIBRARY_OUTPUT_INTDIR)
+
+string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
+ ${PACKAGE_VERSION})
+
+if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
+ set(DEFAULT_INSTALL_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/)
+ set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/lib${LIBUNWIND_LIBDIR_SUFFIX})
+elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
else()
set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX})
@@ -175,41 +199,53 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR})
-set(LIBUNWIND_INSTALL_PREFIX "" CACHE STRING
+set(LIBUNWIND_INSTALL_PREFIX ${DEFAULT_INSTALL_PREFIX} CACHE STRING
"Define libunwind destination prefix.")
-if (NOT LIBUNWIND_INSTALL_PREFIX MATCHES "^$|.*/")
- message(FATAL_ERROR "LIBUNWIND_INSTALL_PREFIX has to end with \"/\".")
-endif()
-
set(LIBUNWIND_C_FLAGS "")
set(LIBUNWIND_CXX_FLAGS "")
set(LIBUNWIND_COMPILE_FLAGS "")
set(LIBUNWIND_LINK_FLAGS "")
# Get required flags.
-macro(append_if list condition var)
+macro(unwind_append_if list condition var)
if (${condition})
list(APPEND ${list} ${var})
endif()
endmacro()
-macro(add_target_flags_if condition var)
+macro(add_target_flags)
+ foreach(value ${ARGN})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}")
+ list(APPEND LIBUNWIND_COMPILE_FLAGS ${value})
+ list(APPEND LIBUNWIND_LINK_FLAGS ${value})
+ endforeach()
+endmacro()
+
+macro(add_target_flags_if condition)
if (${condition})
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${var}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${var}")
- list(APPEND LIBUNWIND_COMPILE_FLAGS ${var})
- list(APPEND LIBUNWIND_LINK_FLAGS ${var})
+ add_target_flags(${ARGN})
endif()
endmacro()
add_target_flags_if(LIBUNWIND_BUILD_32_BITS "-m32")
-add_target_flags_if(LIBUNWIND_TARGET_TRIPLE
- "--target=${LIBUNWIND_TARGET_TRIPLE}")
-add_target_flags_if(LIBUNWIND_GCC_TOOLCHAIN
- "--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}")
-add_target_flags_if(LIBUNWIND_SYSROOT
- "--sysroot=${LIBUNWIND_SYSROOT}")
+
+if(LIBUNWIND_TARGET_TRIPLE)
+ add_target_flags("--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("--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("--sysroot=${LIBUNWIND_SYSROOT}")
+elseif(CMAKE_SYSROOT)
+ set(LIBUNWIND_SYSROOT "${CMAKE_SYSROOT}")
+endif()
if (LIBUNWIND_TARGET_TRIPLE)
set(TARGET_TRIPLE "${LIBUNWIND_TARGET_TRIPLE}")
@@ -218,7 +254,7 @@ endif()
# Configure compiler.
include(config-ix)
-if (LIBUNWIND_USE_COMPILER_RT)
+if (LIBUNWIND_USE_COMPILER_RT AND NOT LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
list(APPEND LIBUNWIND_LINK_FLAGS "-rtlib=compiler-rt")
endif()
@@ -226,48 +262,51 @@ endif()
# Setup Compiler Flags
#===============================================================================
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror=return-type)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror=return-type)
# Get warning flags
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_W_FLAG -W)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WALL_FLAG -Wall)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCHAR_SUBSCRIPTS_FLAG -Wchar-subscripts)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCONVERSION_FLAG -Wconversion)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISMATCHED_TAGS_FLAG -Wmismatched-tags)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISSING_BRACES_FLAG -Wmissing-braces)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNEWLINE_EOF_FLAG -Wnewline-eof)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_UNUSED_FUNCTION_FLAG -Wno-unused-function)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHADOW_FLAG -Wshadow)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHORTEN_64_TO_32_FLAG -Wshorten-64-to-32)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_COMPARE_FLAG -Wsign-compare)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_CONVERSION_FLAG -Wsign-conversion)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_ALIASING_FLAG -Wstrict-aliasing=2)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_OVERFLOW_FLAG -Wstrict-overflow=4)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_PARAMETER_FLAG -Wunused-parameter)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_VARIABLE_FLAG -Wunused-variable)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WWRITE_STRINGS_FLAG -Wwrite-strings)
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNDEF_FLAG -Wundef)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_W_FLAG -W)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WALL_FLAG -Wall)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCHAR_SUBSCRIPTS_FLAG -Wchar-subscripts)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WCONVERSION_FLAG -Wconversion)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISMATCHED_TAGS_FLAG -Wmismatched-tags)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WMISSING_BRACES_FLAG -Wmissing-braces)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNEWLINE_EOF_FLAG -Wnewline-eof)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_UNUSED_FUNCTION_FLAG -Wno-unused-function)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHADOW_FLAG -Wshadow)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSHORTEN_64_TO_32_FLAG -Wshorten-64-to-32)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_COMPARE_FLAG -Wsign-compare)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSIGN_CONVERSION_FLAG -Wsign-conversion)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_ALIASING_FLAG -Wstrict-aliasing=2)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WSTRICT_OVERFLOW_FLAG -Wstrict-overflow=4)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_PARAMETER_FLAG -Wunused-parameter)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNUSED_VARIABLE_FLAG -Wunused-variable)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WWRITE_STRINGS_FLAG -Wwrite-strings)
+unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WUNDEF_FLAG -Wundef)
if (LIBUNWIND_ENABLE_WERROR)
- append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror)
- append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WX_FLAG -WX)
+ unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror)
+ unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WX_FLAG -WX)
else()
- append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_ERROR_FLAG -Wno-error)
- append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_NO_WX_FLAG -WX-)
+ unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WNO_ERROR_FLAG -Wno-error)
+ unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_NO_WX_FLAG -WX-)
endif()
if (LIBUNWIND_ENABLE_PEDANTIC)
- append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_PEDANTIC_FLAG -pedantic)
+ unwind_append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_PEDANTIC_FLAG -pedantic)
endif()
# Get feature flags.
# Exceptions
# Catches C++ exceptions only and tells the compiler to assume that extern C
# functions never throw a C++ exception.
-append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing)
-append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_EHSC_FLAG -EHsc)
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing)
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_EHSC_FLAG -EHsc)
+
+unwind_append_if(LIBUNWIND_C_FLAGS LIBUNWIND_HAS_FUNWIND_TABLES -funwind-tables)
-append_if(LIBUNWIND_C_FLAGS LIBUNWIND_HAS_FUNWIND_TABLES -funwind-tables)
+# Ensure that we don't depend on C++ standard library.
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_NOSTDINCXX_FLAG -nostdinc++)
# Assert
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
@@ -323,30 +362,12 @@ endif()
include_directories(include)
-find_path(
- LIBUNWIND_LIBCXX_INCLUDES_INTERNAL
- __libcpp_version
- PATHS ${LLVM_MAIN_SRC_DIR}/projects/libcxx/include
- ${LLVM_MAIN_SRC_DIR}/runtimes/libcxx/include
- NO_DEFAULT_PATH
-)
-if ((NOT LIBUNWIND_STANDALONE_BUILD OR HAVE_LIBCXX) AND
- IS_DIRECTORY "${LIBUNWIND_LIBCXX_INCLUDES_INTERNAL}")
- set(LIBUNWIND_CXX_INCLUDE_PATHS_DEFAULT "${LIBUNWIND_LIBCXX_INCLUDES_INTERNAL}")
-endif()
-
-set(LIBUNWIND_CXX_INCLUDE_PATHS "${LIBUNWIND_CXX_INCLUDE_PATHS_DEFAULT}" CACHE PATH
- "Paths to C++ header directories separated by ';'.")
-
-if (NOT LIBUNWIND_CXX_INCLUDE_PATHS STREQUAL "")
- list(APPEND LIBUNWIND_CXX_FLAGS -nostdinc++)
- include_directories("${LIBUNWIND_CXX_INCLUDE_PATHS}")
-endif()
-
add_subdirectory(src)
if (LIBUNWIND_INCLUDE_DOCS)
add_subdirectory(docs)
endif()
-add_subdirectory(test)
+if (EXISTS ${LLVM_CMAKE_PATH})
+ add_subdirectory(test)
+endif()
diff --git a/LICENSE.TXT b/LICENSE.TXT
index fb77e1b..1e31206 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -1,5 +1,240 @@
==============================================================================
-libunwind License
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+ `LICENSE` file at the top containing the specific license and restrictions
+ which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+ file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
The libunwind library is dual licensed under both the University of Illinois
@@ -14,7 +249,7 @@ Full text of the relevant licenses is included below.
University of Illinois/NCSA
Open Source License
-Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
All rights reserved.
diff --git a/cmake/Modules/HandleCompilerRT.cmake b/cmake/Modules/HandleCompilerRT.cmake
index 9bf88bb..77168e5 100644
--- a/cmake/Modules/HandleCompilerRT.cmake
+++ b/cmake/Modules/HandleCompilerRT.cmake
@@ -8,12 +8,16 @@ function(find_compiler_rt_library name dest)
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET)
list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}")
endif()
+ get_property(LIBUNWIND_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
+ string(REPLACE " " ";" LIBUNWIND_CXX_FLAGS "${LIBUNWIND_CXX_FLAGS}")
+ list(APPEND CLANG_COMMAND ${LIBUNWIND_CXX_FLAGS})
execute_process(
COMMAND ${CLANG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE LIBRARY_FILE
)
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+ file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}")
message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}")
@@ -37,6 +41,7 @@ function(find_compiler_rt_dir dest)
OUTPUT_VARIABLE LIBRARY_DIR
)
string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR)
+ file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR)
set(LIBRARY_DIR "${LIBRARY_DIR}/darwin")
else()
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
@@ -47,6 +52,7 @@ function(find_compiler_rt_dir dest)
OUTPUT_VARIABLE LIBRARY_FILE
)
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+ file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY)
endif()
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}")
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index 2d4da64..670c31f 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -7,6 +7,7 @@ check_library_exists(c fopen "" LIBUNWIND_HAS_C_LIB)
if (NOT LIBUNWIND_USE_COMPILER_RT)
check_library_exists(gcc_s __gcc_personality_v0 "" LIBUNWIND_HAS_GCC_S_LIB)
+ check_library_exists(gcc __absvdi2 "" LIBUNWIND_HAS_GCC_LIB)
endif()
# libunwind is built with -nodefaultlibs, so we want all our checks to also
@@ -23,11 +24,15 @@ if (LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
endif ()
if (LIBUNWIND_USE_COMPILER_RT)
- list(APPEND CMAKE_REQUIRED_FLAGS -rtlib=compiler-rt)
find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY)
list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBUNWIND_BUILTINS_LIBRARY}")
- elseif (LIBUNWIND_HAS_GCC_S_LIB)
- list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
+ else ()
+ if (LIBUNWIND_HAS_GCC_S_LIB)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
+ endif ()
+ if (LIBUNWIND_HAS_GCC_LIB)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES gcc)
+ endif ()
endif ()
if (MINGW)
# Mingw64 requires quite a few "C" runtime libraries in order for basic
diff --git a/docs/BuildingLibunwind.rst b/docs/BuildingLibunwind.rst
index 6aa4556..7f42133 100644
--- a/docs/BuildingLibunwind.rst
+++ b/docs/BuildingLibunwind.rst
@@ -18,16 +18,10 @@ edge), read on.
The basic steps needed to build libc++ are:
-#. Checkout LLVM:
+#. Checkout LLVM, libunwind, and related projects:
* ``cd where-you-want-llvm-to-live``
- * ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
-
-#. Checkout libunwind:
-
- * ``cd where-you-want-llvm-to-live``
- * ``cd llvm/runtimes``
- * ``svn co http://llvm.org/svn/llvm-project/libunwind/trunk libunwind``
+ * ``git clone https://github.com/llvm/llvm-project.git``
#. Configure and build libunwind:
@@ -38,7 +32,7 @@ The basic steps needed to build libc++ are:
* ``cd where you want to build llvm``
* ``mkdir build``
* ``cd build``
- * ``cmake -G <generator> [options] <path to llvm sources>``
+ * ``cmake -G <generator> -DLLVM_ENABLE_PROJECTS=libunwind [options] <path to llvm sources>``
For more information about configuring libunwind see :ref:`CMake Options`.
diff --git a/docs/conf.py b/docs/conf.py
index 29c95f3..704a1d0 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -11,6 +11,7 @@
# serve to show the default.
import sys, os
+from datetime import date
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -40,16 +41,16 @@ master_doc = 'index'
# General information about the project.
project = u'libunwind'
-copyright = u'2011-2017, LLVM Project'
+copyright = u'2011-%d, LLVM Project' % date.today().year
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '6.0'
+version = '9.0'
# The full version, including alpha/beta/rc tags.
-release = '6.0'
+release = '9.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/index.rst b/docs/index.rst
index 7e7277e..9e53b41 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -101,5 +101,4 @@ Quick Links
* `LLVM Bugzilla <https://bugs.llvm.org/>`_
* `cfe-commits Mailing List`_
* `cfe-dev Mailing List`_
-* `Browse libunwind -- SVN <http://llvm.org/svn/llvm-project/libunwind/trunk/>`_
-* `Browse libunwind -- ViewVC <http://llvm.org/viewvc/llvm-project/libunwind/trunk/>`_
+* `Browse libunwind Sources <https://github.com/llvm/llvm-project/blob/master/libunwind/>`_
diff --git a/include/__libunwind_config.h b/include/__libunwind_config.h
index 69a4996..6e7e5e6 100644
--- a/include/__libunwind_config.h
+++ b/include/__libunwind_config.h
@@ -1,9 +1,8 @@
//===------------------------- __libunwind_config.h -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -18,10 +17,12 @@
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287
-#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 31
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# if defined(__i386__)
@@ -33,12 +34,21 @@
# define _LIBUNWIND_TARGET_X86_64 1
# if defined(_WIN64)
# define _LIBUNWIND_CONTEXT_SIZE 54
-# define _LIBUNWIND_CURSOR_SIZE 66
+# ifdef __SEH__
+# define _LIBUNWIND_CURSOR_SIZE 204
+# else
+# define _LIBUNWIND_CURSOR_SIZE 66
+# endif
# else
# define _LIBUNWIND_CONTEXT_SIZE 21
# define _LIBUNWIND_CURSOR_SIZE 33
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64
+# elif defined(__powerpc64__)
+# define _LIBUNWIND_TARGET_PPC64 1
+# define _LIBUNWIND_CONTEXT_SIZE 167
+# define _LIBUNWIND_CURSOR_SIZE 179
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
# elif defined(__ppc__)
# define _LIBUNWIND_TARGET_PPC 1
# define _LIBUNWIND_CONTEXT_SIZE 117
@@ -47,11 +57,18 @@
# elif defined(__aarch64__)
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_CONTEXT_SIZE 66
-# define _LIBUNWIND_CURSOR_SIZE 78
+# if defined(__SEH__)
+# define _LIBUNWIND_CURSOR_SIZE 164
+# else
+# define _LIBUNWIND_CURSOR_SIZE 78
+# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
# elif defined(__arm__)
# define _LIBUNWIND_TARGET_ARM 1
-# if defined(__ARM_WMMX)
+# if defined(__SEH__)
+# define _LIBUNWIND_CONTEXT_SIZE 42
+# define _LIBUNWIND_CURSOR_SIZE 80
+# elif defined(__ARM_WMMX)
# define _LIBUNWIND_CONTEXT_SIZE 61
# define _LIBUNWIND_CURSOR_SIZE 68
# else
@@ -65,18 +82,42 @@
# define _LIBUNWIND_CURSOR_SIZE 24
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
# elif defined(__mips__)
-# if defined(_ABIO32) && defined(__mips_soft_float)
+# if defined(_ABIO32) && _MIPS_SIM == _ABIO32
# define _LIBUNWIND_TARGET_MIPS_O32 1
-# define _LIBUNWIND_CONTEXT_SIZE 18
-# define _LIBUNWIND_CURSOR_SIZE 24
-# elif defined(_ABI64) && defined(__mips_soft_float)
-# define _LIBUNWIND_TARGET_MIPS_N64 1
-# define _LIBUNWIND_CONTEXT_SIZE 35
-# define _LIBUNWIND_CURSOR_SIZE 47
+# if defined(__mips_hard_float)
+# define _LIBUNWIND_CONTEXT_SIZE 50
+# define _LIBUNWIND_CURSOR_SIZE 57
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 18
+# define _LIBUNWIND_CURSOR_SIZE 24
+# endif
+# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# if defined(__mips_hard_float)
+# define _LIBUNWIND_CONTEXT_SIZE 67
+# define _LIBUNWIND_CURSOR_SIZE 74
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 35
+# define _LIBUNWIND_CURSOR_SIZE 42
+# endif
+# elif defined(_ABI64) && _MIPS_SIM == _ABI64
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# if defined(__mips_hard_float)
+# define _LIBUNWIND_CONTEXT_SIZE 67
+# define _LIBUNWIND_CURSOR_SIZE 79
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 35
+# define _LIBUNWIND_CURSOR_SIZE 47
+# endif
# else
# error "Unsupported MIPS ABI and/or environment"
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
+# elif defined(__sparc__)
+ #define _LIBUNWIND_TARGET_SPARC 1
+ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
+ #define _LIBUNWIND_CONTEXT_SIZE 16
+ #define _LIBUNWIND_CURSOR_SIZE 23
# else
# error "Unsupported architecture."
# endif
@@ -84,13 +125,15 @@
# define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_TARGET_X86_64 1
# define _LIBUNWIND_TARGET_PPC 1
+# define _LIBUNWIND_TARGET_PPC64 1
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_TARGET_ARM 1
# define _LIBUNWIND_TARGET_OR1K 1
# define _LIBUNWIND_TARGET_MIPS_O32 1
-# define _LIBUNWIND_TARGET_MIPS_N64 1
-# define _LIBUNWIND_CONTEXT_SIZE 128
-# define _LIBUNWIND_CURSOR_SIZE 140
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# define _LIBUNWIND_TARGET_SPARC 1
+# define _LIBUNWIND_CONTEXT_SIZE 167
+# define _LIBUNWIND_CURSOR_SIZE 179
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
#endif // _LIBUNWIND_IS_NATIVE_ONLY
diff --git a/include/libunwind.h b/include/libunwind.h
index 9011d55..d06724d 100644
--- a/include/libunwind.h
+++ b/include/libunwind.h
@@ -1,9 +1,8 @@
//===---------------------------- libunwind.h -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Compatible with libunwind API documented at:
@@ -57,6 +56,9 @@ enum {
UNW_EINVAL = -6547, /* unsupported operation or bad value */
UNW_EBADVERSION = -6548, /* unwind info has unsupported version */
UNW_ENOINFO = -6549 /* no unwind info found */
+#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+ , UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */
+#endif
};
struct unw_context_t {
@@ -73,7 +75,7 @@ typedef struct unw_addr_space *unw_addr_space_t;
typedef int unw_regnum_t;
typedef uintptr_t unw_word_t;
-#if defined(__arm__)
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
typedef uint64_t unw_fpreg_t;
#else
typedef double unw_fpreg_t;
@@ -122,32 +124,6 @@ extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUN
extern unw_addr_space_t unw_local_addr_space;
-#ifdef UNW_REMOTE
-/*
- * Mac OS X "remote" API for unwinding other processes on same machine
- *
- */
-extern unw_addr_space_t unw_create_addr_space_for_task(task_t);
-extern void unw_destroy_addr_space(unw_addr_space_t);
-extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *);
-#endif /* UNW_REMOTE */
-
-/*
- * traditional libunwind "remote" API
- * NOT IMPLEMENTED on Mac OS X
- *
- * extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t,
- * thread_t*);
- * extern unw_accessors_t unw_get_accessors(unw_addr_space_t);
- * extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int);
- * extern void unw_flush_cache(unw_addr_space_t, unw_word_t,
- * unw_word_t);
- * extern int unw_set_caching_policy(unw_addr_space_t,
- * unw_caching_policy_t);
- * extern void _U_dyn_register(unw_dyn_info_t*);
- * extern void _U_dyn_cancel(unw_dyn_info_t*);
- */
-
#ifdef __cplusplus
}
#endif
@@ -325,6 +301,190 @@ enum {
UNW_PPC_SPEFSCR = 112
};
+// 64-bit ppc register numbers
+enum {
+ UNW_PPC64_R0 = 0,
+ UNW_PPC64_R1 = 1,
+ UNW_PPC64_R2 = 2,
+ UNW_PPC64_R3 = 3,
+ UNW_PPC64_R4 = 4,
+ UNW_PPC64_R5 = 5,
+ UNW_PPC64_R6 = 6,
+ UNW_PPC64_R7 = 7,
+ UNW_PPC64_R8 = 8,
+ UNW_PPC64_R9 = 9,
+ UNW_PPC64_R10 = 10,
+ UNW_PPC64_R11 = 11,
+ UNW_PPC64_R12 = 12,
+ UNW_PPC64_R13 = 13,
+ UNW_PPC64_R14 = 14,
+ UNW_PPC64_R15 = 15,
+ UNW_PPC64_R16 = 16,
+ UNW_PPC64_R17 = 17,
+ UNW_PPC64_R18 = 18,
+ UNW_PPC64_R19 = 19,
+ UNW_PPC64_R20 = 20,
+ UNW_PPC64_R21 = 21,
+ UNW_PPC64_R22 = 22,
+ UNW_PPC64_R23 = 23,
+ UNW_PPC64_R24 = 24,
+ UNW_PPC64_R25 = 25,
+ UNW_PPC64_R26 = 26,
+ UNW_PPC64_R27 = 27,
+ UNW_PPC64_R28 = 28,
+ UNW_PPC64_R29 = 29,
+ UNW_PPC64_R30 = 30,
+ UNW_PPC64_R31 = 31,
+ UNW_PPC64_F0 = 32,
+ UNW_PPC64_F1 = 33,
+ UNW_PPC64_F2 = 34,
+ UNW_PPC64_F3 = 35,
+ UNW_PPC64_F4 = 36,
+ UNW_PPC64_F5 = 37,
+ UNW_PPC64_F6 = 38,
+ UNW_PPC64_F7 = 39,
+ UNW_PPC64_F8 = 40,
+ UNW_PPC64_F9 = 41,
+ UNW_PPC64_F10 = 42,
+ UNW_PPC64_F11 = 43,
+ UNW_PPC64_F12 = 44,
+ UNW_PPC64_F13 = 45,
+ UNW_PPC64_F14 = 46,
+ UNW_PPC64_F15 = 47,
+ UNW_PPC64_F16 = 48,
+ UNW_PPC64_F17 = 49,
+ UNW_PPC64_F18 = 50,
+ UNW_PPC64_F19 = 51,
+ UNW_PPC64_F20 = 52,
+ UNW_PPC64_F21 = 53,
+ UNW_PPC64_F22 = 54,
+ UNW_PPC64_F23 = 55,
+ UNW_PPC64_F24 = 56,
+ UNW_PPC64_F25 = 57,
+ UNW_PPC64_F26 = 58,
+ UNW_PPC64_F27 = 59,
+ UNW_PPC64_F28 = 60,
+ UNW_PPC64_F29 = 61,
+ UNW_PPC64_F30 = 62,
+ UNW_PPC64_F31 = 63,
+ // 64: reserved
+ UNW_PPC64_LR = 65,
+ UNW_PPC64_CTR = 66,
+ // 67: reserved
+ UNW_PPC64_CR0 = 68,
+ UNW_PPC64_CR1 = 69,
+ UNW_PPC64_CR2 = 70,
+ UNW_PPC64_CR3 = 71,
+ UNW_PPC64_CR4 = 72,
+ UNW_PPC64_CR5 = 73,
+ UNW_PPC64_CR6 = 74,
+ UNW_PPC64_CR7 = 75,
+ UNW_PPC64_XER = 76,
+ UNW_PPC64_V0 = 77,
+ UNW_PPC64_V1 = 78,
+ UNW_PPC64_V2 = 79,
+ UNW_PPC64_V3 = 80,
+ UNW_PPC64_V4 = 81,
+ UNW_PPC64_V5 = 82,
+ UNW_PPC64_V6 = 83,
+ UNW_PPC64_V7 = 84,
+ UNW_PPC64_V8 = 85,
+ UNW_PPC64_V9 = 86,
+ UNW_PPC64_V10 = 87,
+ UNW_PPC64_V11 = 88,
+ UNW_PPC64_V12 = 89,
+ UNW_PPC64_V13 = 90,
+ UNW_PPC64_V14 = 91,
+ UNW_PPC64_V15 = 92,
+ UNW_PPC64_V16 = 93,
+ UNW_PPC64_V17 = 94,
+ UNW_PPC64_V18 = 95,
+ UNW_PPC64_V19 = 96,
+ UNW_PPC64_V20 = 97,
+ UNW_PPC64_V21 = 98,
+ UNW_PPC64_V22 = 99,
+ UNW_PPC64_V23 = 100,
+ UNW_PPC64_V24 = 101,
+ UNW_PPC64_V25 = 102,
+ UNW_PPC64_V26 = 103,
+ UNW_PPC64_V27 = 104,
+ UNW_PPC64_V28 = 105,
+ UNW_PPC64_V29 = 106,
+ UNW_PPC64_V30 = 107,
+ UNW_PPC64_V31 = 108,
+ // 109, 111-113: OpenPOWER ELF V2 ABI: reserved
+ // Borrowing VRSAVE number from PPC32.
+ UNW_PPC64_VRSAVE = 109,
+ UNW_PPC64_VSCR = 110,
+ UNW_PPC64_TFHAR = 114,
+ UNW_PPC64_TFIAR = 115,
+ UNW_PPC64_TEXASR = 116,
+ UNW_PPC64_VS0 = UNW_PPC64_F0,
+ UNW_PPC64_VS1 = UNW_PPC64_F1,
+ UNW_PPC64_VS2 = UNW_PPC64_F2,
+ UNW_PPC64_VS3 = UNW_PPC64_F3,
+ UNW_PPC64_VS4 = UNW_PPC64_F4,
+ UNW_PPC64_VS5 = UNW_PPC64_F5,
+ UNW_PPC64_VS6 = UNW_PPC64_F6,
+ UNW_PPC64_VS7 = UNW_PPC64_F7,
+ UNW_PPC64_VS8 = UNW_PPC64_F8,
+ UNW_PPC64_VS9 = UNW_PPC64_F9,
+ UNW_PPC64_VS10 = UNW_PPC64_F10,
+ UNW_PPC64_VS11 = UNW_PPC64_F11,
+ UNW_PPC64_VS12 = UNW_PPC64_F12,
+ UNW_PPC64_VS13 = UNW_PPC64_F13,
+ UNW_PPC64_VS14 = UNW_PPC64_F14,
+ UNW_PPC64_VS15 = UNW_PPC64_F15,
+ UNW_PPC64_VS16 = UNW_PPC64_F16,
+ UNW_PPC64_VS17 = UNW_PPC64_F17,
+ UNW_PPC64_VS18 = UNW_PPC64_F18,
+ UNW_PPC64_VS19 = UNW_PPC64_F19,
+ UNW_PPC64_VS20 = UNW_PPC64_F20,
+ UNW_PPC64_VS21 = UNW_PPC64_F21,
+ UNW_PPC64_VS22 = UNW_PPC64_F22,
+ UNW_PPC64_VS23 = UNW_PPC64_F23,
+ UNW_PPC64_VS24 = UNW_PPC64_F24,
+ UNW_PPC64_VS25 = UNW_PPC64_F25,
+ UNW_PPC64_VS26 = UNW_PPC64_F26,
+ UNW_PPC64_VS27 = UNW_PPC64_F27,
+ UNW_PPC64_VS28 = UNW_PPC64_F28,
+ UNW_PPC64_VS29 = UNW_PPC64_F29,
+ UNW_PPC64_VS30 = UNW_PPC64_F30,
+ UNW_PPC64_VS31 = UNW_PPC64_F31,
+ UNW_PPC64_VS32 = UNW_PPC64_V0,
+ UNW_PPC64_VS33 = UNW_PPC64_V1,
+ UNW_PPC64_VS34 = UNW_PPC64_V2,
+ UNW_PPC64_VS35 = UNW_PPC64_V3,
+ UNW_PPC64_VS36 = UNW_PPC64_V4,
+ UNW_PPC64_VS37 = UNW_PPC64_V5,
+ UNW_PPC64_VS38 = UNW_PPC64_V6,
+ UNW_PPC64_VS39 = UNW_PPC64_V7,
+ UNW_PPC64_VS40 = UNW_PPC64_V8,
+ UNW_PPC64_VS41 = UNW_PPC64_V9,
+ UNW_PPC64_VS42 = UNW_PPC64_V10,
+ UNW_PPC64_VS43 = UNW_PPC64_V11,
+ UNW_PPC64_VS44 = UNW_PPC64_V12,
+ UNW_PPC64_VS45 = UNW_PPC64_V13,
+ UNW_PPC64_VS46 = UNW_PPC64_V14,
+ UNW_PPC64_VS47 = UNW_PPC64_V15,
+ UNW_PPC64_VS48 = UNW_PPC64_V16,
+ UNW_PPC64_VS49 = UNW_PPC64_V17,
+ UNW_PPC64_VS50 = UNW_PPC64_V18,
+ UNW_PPC64_VS51 = UNW_PPC64_V19,
+ UNW_PPC64_VS52 = UNW_PPC64_V20,
+ UNW_PPC64_VS53 = UNW_PPC64_V21,
+ UNW_PPC64_VS54 = UNW_PPC64_V22,
+ UNW_PPC64_VS55 = UNW_PPC64_V23,
+ UNW_PPC64_VS56 = UNW_PPC64_V24,
+ UNW_PPC64_VS57 = UNW_PPC64_V25,
+ UNW_PPC64_VS58 = UNW_PPC64_V26,
+ UNW_PPC64_VS59 = UNW_PPC64_V27,
+ UNW_PPC64_VS60 = UNW_PPC64_V28,
+ UNW_PPC64_VS61 = UNW_PPC64_V29,
+ UNW_PPC64_VS62 = UNW_PPC64_V30,
+ UNW_PPC64_VS63 = UNW_PPC64_V31
+};
+
// 64-bit ARM64 registers
enum {
UNW_ARM64_X0 = 0,
@@ -363,6 +523,8 @@ enum {
UNW_ARM64_X31 = 31,
UNW_ARM64_SP = 31,
// reserved block
+ UNW_ARM64_RA_SIGN_STATE = 34,
+ // reserved block
UNW_ARM64_D0 = 64,
UNW_ARM64_D1 = 65,
UNW_ARM64_D2 = 66,
@@ -561,6 +723,7 @@ enum {
UNW_OR1K_R29 = 29,
UNW_OR1K_R30 = 30,
UNW_OR1K_R31 = 31,
+ UNW_OR1K_EPCR = 32,
};
// MIPS registers
@@ -597,8 +760,76 @@ enum {
UNW_MIPS_R29 = 29,
UNW_MIPS_R30 = 30,
UNW_MIPS_R31 = 31,
+ UNW_MIPS_F0 = 32,
+ UNW_MIPS_F1 = 33,
+ UNW_MIPS_F2 = 34,
+ UNW_MIPS_F3 = 35,
+ UNW_MIPS_F4 = 36,
+ UNW_MIPS_F5 = 37,
+ UNW_MIPS_F6 = 38,
+ UNW_MIPS_F7 = 39,
+ UNW_MIPS_F8 = 40,
+ UNW_MIPS_F9 = 41,
+ UNW_MIPS_F10 = 42,
+ UNW_MIPS_F11 = 43,
+ UNW_MIPS_F12 = 44,
+ UNW_MIPS_F13 = 45,
+ UNW_MIPS_F14 = 46,
+ UNW_MIPS_F15 = 47,
+ UNW_MIPS_F16 = 48,
+ UNW_MIPS_F17 = 49,
+ UNW_MIPS_F18 = 50,
+ UNW_MIPS_F19 = 51,
+ UNW_MIPS_F20 = 52,
+ UNW_MIPS_F21 = 53,
+ UNW_MIPS_F22 = 54,
+ UNW_MIPS_F23 = 55,
+ UNW_MIPS_F24 = 56,
+ UNW_MIPS_F25 = 57,
+ UNW_MIPS_F26 = 58,
+ UNW_MIPS_F27 = 59,
+ UNW_MIPS_F28 = 60,
+ UNW_MIPS_F29 = 61,
+ UNW_MIPS_F30 = 62,
+ UNW_MIPS_F31 = 63,
UNW_MIPS_HI = 64,
UNW_MIPS_LO = 65,
};
+// SPARC registers
+enum {
+ UNW_SPARC_G0 = 0,
+ UNW_SPARC_G1 = 1,
+ UNW_SPARC_G2 = 2,
+ UNW_SPARC_G3 = 3,
+ UNW_SPARC_G4 = 4,
+ UNW_SPARC_G5 = 5,
+ UNW_SPARC_G6 = 6,
+ UNW_SPARC_G7 = 7,
+ UNW_SPARC_O0 = 8,
+ UNW_SPARC_O1 = 9,
+ UNW_SPARC_O2 = 10,
+ UNW_SPARC_O3 = 11,
+ UNW_SPARC_O4 = 12,
+ UNW_SPARC_O5 = 13,
+ UNW_SPARC_O6 = 14,
+ UNW_SPARC_O7 = 15,
+ UNW_SPARC_L0 = 16,
+ UNW_SPARC_L1 = 17,
+ UNW_SPARC_L2 = 18,
+ UNW_SPARC_L3 = 19,
+ UNW_SPARC_L4 = 20,
+ UNW_SPARC_L5 = 21,
+ UNW_SPARC_L6 = 22,
+ UNW_SPARC_L7 = 23,
+ UNW_SPARC_I0 = 24,
+ UNW_SPARC_I1 = 25,
+ UNW_SPARC_I2 = 26,
+ UNW_SPARC_I3 = 27,
+ UNW_SPARC_I4 = 28,
+ UNW_SPARC_I5 = 29,
+ UNW_SPARC_I6 = 30,
+ UNW_SPARC_I7 = 31,
+};
+
#endif
diff --git a/include/mach-o/compact_unwind_encoding.h b/include/mach-o/compact_unwind_encoding.h
index de14fd5..5301b10 100644
--- a/include/mach-o/compact_unwind_encoding.h
+++ b/include/mach-o/compact_unwind_encoding.h
@@ -1,9 +1,8 @@
//===------------------ mach-o/compact_unwind_encoding.h ------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Darwin's alternative to DWARF based unwind encodings.
diff --git a/include/unwind.h b/include/unwind.h
index 0ab87dd..122b57b 100644
--- a/include/unwind.h
+++ b/include/unwind.h
@@ -1,9 +1,8 @@
//===------------------------------- unwind.h -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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:
@@ -19,6 +18,11 @@
#include <stdint.h>
#include <stddef.h>
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32)
+#include <windows.h>
+#include <ntverp.h>
+#endif
+
#if defined(__APPLE__)
#define LIBUNWIND_UNAVAIL __attribute__ (( unavailable ))
#else
@@ -120,13 +124,17 @@ 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
+#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. To be more explicit, we add pad fields
- // added for binary compatibility.
+ // 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
@@ -369,6 +377,22 @@ extern void *__deregister_frame_info(const void *fde)
extern void *__deregister_frame_info_bases(const void *fde)
LIBUNWIND_UNAVAIL;
+#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+#ifndef _WIN32
+typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
+typedef struct _CONTEXT CONTEXT;
+typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
+#elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
+typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
+#endif
+// This is the common wrapper for GCC-style personality functions with SEH.
+extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc,
+ void *frame,
+ CONTEXT *ctx,
+ DISPATCHER_CONTEXT *disp,
+ __personality_routine pers);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/AddressSpace.hpp b/src/AddressSpace.hpp
index 2be16af..fb370ad 100644
--- a/src/AddressSpace.hpp
+++ b/src/AddressSpace.hpp
@@ -1,9 +1,8 @@
//===------------------------- AddressSpace.hpp ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Abstracts accessing local vs remote address spaces.
@@ -18,7 +17,15 @@
#include <stdlib.h>
#include <string.h>
-#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+#ifndef _LIBUNWIND_USE_DLADDR
+ #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+ #define _LIBUNWIND_USE_DLADDR 1
+ #else
+ #define _LIBUNWIND_USE_DLADDR 0
+ #endif
+#endif
+
+#if _LIBUNWIND_USE_DLADDR
#include <dlfcn.h>
#endif
@@ -83,6 +90,38 @@ namespace libunwind {
}
#endif
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
+
+// When statically linked on bare-metal, the symbols for the EH table are looked
+// up without going through the dynamic loader.
+
+// The following linker script may be used to produce the necessary sections and symbols.
+// Unless the --eh-frame-hdr linker option is provided, the section is not generated
+// and does not take space in the output file.
+//
+// .eh_frame :
+// {
+// __eh_frame_start = .;
+// KEEP(*(.eh_frame))
+// __eh_frame_end = .;
+// }
+//
+// .eh_frame_hdr :
+// {
+// KEEP(*(.eh_frame_hdr))
+// }
+//
+// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
+// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
+
+extern char __eh_frame_start;
+extern char __eh_frame_end;
+
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+extern char __eh_frame_hdr_start;
+extern char __eh_frame_hdr_end;
+#endif
+
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
// When statically linked on bare-metal, the symbols for the EH table are looked
@@ -115,7 +154,7 @@ namespace libunwind {
struct UnwindInfoSections {
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
- // No dso_base for ARM EHABI.
+ // No dso_base for SEH or ARM EHABI.
uintptr_t dso_base;
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -140,7 +179,7 @@ struct UnwindInfoSections {
/// LocalAddressSpace is used as a template parameter to UnwindCursor when
/// unwinding a thread in the same process. The wrappers compile away,
/// making local unwinds fast.
-class __attribute__((visibility("hidden"))) LocalAddressSpace {
+class _LIBUNWIND_HIDDEN LocalAddressSpace {
public:
typedef uintptr_t pint_t;
typedef intptr_t sint_t;
@@ -175,6 +214,7 @@ public:
return val;
}
uintptr_t getP(pint_t addr);
+ uint64_t getRegister(pint_t addr);
static uint64_t getULEB128(pint_t &addr, pint_t end);
static int64_t getSLEB128(pint_t &addr, pint_t end);
@@ -196,6 +236,14 @@ inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
#endif
}
+inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
+#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
+ return get64(addr);
+#else
+ return get32(addr);
+#endif
+}
+
/// Read a ULEB128 into a 64-bit word.
inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
const uint8_t *p = (uint8_t *)addr;
@@ -348,12 +396,26 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
return true;
}
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
+ // Bare metal is statically linked, so no need to ask the dynamic loader
+ info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
+ info.dwarf_section = (uintptr_t)(&__eh_frame_start);
+ _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
+ (void *)info.dwarf_section, (void *)info.dwarf_section_length);
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+ info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
+ info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
+ _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
+ (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
+#endif
+ if (info.dwarf_section_length)
+ return true;
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
// Bare metal is statically linked, so no need to ask the dynamic loader
info.arm_section = (uintptr_t)(&__exidx_start);
info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
- _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
- info.arm_section, info.arm_section_length);
+ _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
+ (void *)info.arm_section, (void *)info.arm_section_length);
if (info.arm_section && info.arm_section_length)
return true;
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
@@ -391,6 +453,12 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
}
}
return false;
+#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
+ // Don't even bother, since Windows has functions that do all this stuff
+ // for us.
+ (void)targetAddr;
+ (void)info;
+ return true;
#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \
(__ANDROID_API__ < 21)
int length = 0;
@@ -467,11 +535,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
#endif
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
- EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
+ found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
hdrInfo);
- cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
- found_hdr = true;
+ if (found_hdr)
+ cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
}
}
@@ -521,7 +589,7 @@ inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
size_t bufLen,
unw_word_t *offset) {
-#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+#if _LIBUNWIND_USE_DLADDR
Dl_info dyldInfo;
if (dladdr((void *)addr, &dyldInfo)) {
if (dyldInfo.dli_sname != NULL) {
@@ -530,129 +598,15 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
return true;
}
}
+#else
+ (void)addr;
+ (void)buf;
+ (void)bufLen;
+ (void)offset;
#endif
return false;
}
-
-
-#ifdef UNW_REMOTE
-
-/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
-/// unwinding a thread in the another process. The other process can be a
-/// different endianness and a different pointer size which is handled by
-/// the P template parameter.
-template <typename P>
-class RemoteAddressSpace {
-public:
- RemoteAddressSpace(task_t task) : fTask(task) {}
-
- typedef typename P::uint_t pint_t;
-
- uint8_t get8(pint_t addr);
- uint16_t get16(pint_t addr);
- uint32_t get32(pint_t addr);
- uint64_t get64(pint_t addr);
- pint_t getP(pint_t addr);
- uint64_t getULEB128(pint_t &addr, pint_t end);
- int64_t getSLEB128(pint_t &addr, pint_t end);
- pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
- pint_t datarelBase = 0);
- bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
- unw_word_t *offset);
- bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
- bool findOtherFDE(pint_t targetAddr, pint_t &fde);
-private:
- void *localCopy(pint_t addr);
-
- task_t fTask;
-};
-
-template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
- return *((uint8_t *)localCopy(addr));
-}
-
-template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
- return P::E::get16(*(uint16_t *)localCopy(addr));
-}
-
-template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
- return P::E::get32(*(uint32_t *)localCopy(addr));
-}
-
-template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
- return P::E::get64(*(uint64_t *)localCopy(addr));
-}
-
-template <typename P>
-typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
- return P::getP(*(uint64_t *)localCopy(addr));
-}
-
-template <typename P>
-uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
- uintptr_t size = (end - addr);
- LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
- LocalAddressSpace::pint_t sladdr = laddr;
- uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
- addr += (laddr - sladdr);
- return result;
-}
-
-template <typename P>
-int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
- uintptr_t size = (end - addr);
- LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
- LocalAddressSpace::pint_t sladdr = laddr;
- uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
- addr += (laddr - sladdr);
- return result;
-}
-
-template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
- // FIX ME
-}
-
-template <typename P>
-bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
- size_t bufLen,
- unw_word_t *offset) {
- // FIX ME
-}
-
-/// unw_addr_space is the base class that abstract unw_addr_space_t type in
-/// libunwind.h points to.
-struct unw_addr_space {
- cpu_type_t cpuType;
- task_t taskPort;
-};
-
-/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
-/// to when examining
-/// a 32-bit intel process.
-struct unw_addr_space_i386 : public unw_addr_space {
- unw_addr_space_i386(task_t task) : oas(task) {}
- RemoteAddressSpace<Pointer32<LittleEndian>> oas;
-};
-
-/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
-/// points to when examining
-/// a 64-bit intel process.
-struct unw_addr_space_x86_64 : public unw_addr_space {
- unw_addr_space_x86_64(task_t task) : oas(task) {}
- RemoteAddressSpace<Pointer64<LittleEndian>> oas;
-};
-
-/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
-/// to when examining
-/// a 32-bit PowerPC process.
-struct unw_addr_space_ppc : public unw_addr_space {
- unw_addr_space_ppc(task_t task) : oas(task) {}
- RemoteAddressSpace<Pointer32<BigEndian>> oas;
-};
-
-#endif // UNW_REMOTE
-
} // namespace libunwind
#endif // __ADDRESSSPACE_HPP__
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2d2ec13..2928a14 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,8 +2,9 @@
set(LIBUNWIND_CXX_SOURCES
libunwind.cpp
- Unwind-EHABI.cpp)
-append_if(LIBUNWIND_CXX_SOURCES APPLE Unwind_AppleExtras.cpp)
+ Unwind-EHABI.cpp
+ Unwind-seh.cpp)
+unwind_append_if(LIBUNWIND_CXX_SOURCES APPLE Unwind_AppleExtras.cpp)
set(LIBUNWIND_C_SOURCES
UnwindLevel1.c
@@ -35,7 +36,7 @@ set(LIBUNWIND_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/../include/libunwind.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/unwind.h)
-append_if(LIBUNWIND_HEADERS APPLE
+unwind_append_if(LIBUNWIND_HEADERS APPLE
"${CMAKE_CURRENT_SOURCE_DIR}/../include/mach-o/compact_unwind_encoding.h")
if (MSVC_IDE)
@@ -50,17 +51,26 @@ set(LIBUNWIND_SOURCES
${LIBUNWIND_ASM_SOURCES})
# Generate library list.
-set(libraries ${LIBUNWINDCXX_ABI_LIBRARIES})
-append_if(libraries LIBUNWIND_HAS_C_LIB c)
-append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
+set(libraries)
+unwind_append_if(libraries LIBUNWIND_HAS_C_LIB c)
+if (LIBUNWIND_USE_COMPILER_RT)
+ list(APPEND libraries "${LIBUNWIND_BUILTINS_LIBRARY}")
+else()
+ unwind_append_if(libraries LIBUNWIND_HAS_GCC_S_LIB gcc_s)
+ unwind_append_if(libraries LIBUNWIND_HAS_GCC_LIB gcc)
+endif()
+unwind_append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
if (LIBUNWIND_ENABLE_THREADS)
- append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
+ unwind_append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
endif()
# Setup flags.
-append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_NO_RTTI_FLAG -fno-rtti)
+unwind_append_if(LIBUNWIND_CXX_FLAGS LIBUNWIND_HAS_NO_RTTI_FLAG -fno-rtti)
+
+unwind_append_if(LIBUNWIND_LINK_FLAGS LIBUNWIND_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs)
-append_if(LIBUNWIND_LINK_FLAGS LIBUNWIND_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs)
+# MINGW_LIBRARIES is defined in config-ix.cmake
+unwind_append_if(libraries MINGW "${MINGW_LIBRARIES}")
if (LIBUNWIND_HAS_NO_EXCEPTIONS_FLAG AND LIBUNWIND_HAS_FUNWIND_TABLES)
list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-exceptions)
@@ -91,49 +101,83 @@ string(REPLACE ";" " " LIBUNWIND_C_FLAGS "${LIBUNWIND_C_FLAGS}")
string(REPLACE ";" " " LIBUNWIND_LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}")
set_property(SOURCE ${LIBUNWIND_CXX_SOURCES}
- APPEND_STRING PROPERTY COMPILE_FLAGS " ${CMAKE_CXX_FLAGS} ${LIBUNWIND_CXX_FLAGS}")
+ APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBUNWIND_CXX_FLAGS}")
set_property(SOURCE ${LIBUNWIND_C_SOURCES}
- APPEND_STRING PROPERTY COMPILE_FLAGS " ${CMAKE_C_FLAGS} ${LIBUNWIND_C_FLAGS}")
+ APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBUNWIND_C_FLAGS}")
+
+macro(unwind_object_library name)
+ cmake_parse_arguments(ARGS "" "" "DEFINES;FLAGS" ${ARGN})
# Add a object library that contains the compiled source files.
-add_library(unwind_objects OBJECT ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
+ add_library(${name} OBJECT ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
-set_target_properties(unwind_objects
- PROPERTIES
- COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
- POSITION_INDEPENDENT_CODE ON)
+ if(ARGS_DEFINES)
+ target_compile_definitions(${name} PRIVATE ${ARGS_DEFINES})
+ endif()
-set(LIBUNWIND_TARGETS)
+ set_target_properties(${name}
+ PROPERTIES
+ COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}"
+ POSITION_INDEPENDENT_CODE ON)
+
+ if(ARGS_FLAGS)
+ target_compile_options(${name} PRIVATE ${ARGS_FLAGS})
+ endif()
+endmacro()
+
+if(LIBUNWIND_HERMETIC_STATIC_LIBRARY)
+ append_flags_if_supported(UNWIND_STATIC_OBJECTS_FLAGS -fvisibility=hidden)
+ append_flags_if_supported(UNWIND_STATIC_OBJECTS_FLAGS -fvisibility-global-new-delete-hidden)
+ unwind_object_library(unwind_static_objects
+ DEFINES _LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS
+ FLAGS ${UNWIND_STATIC_OBJECTS_FLAGS})
+ unwind_object_library(unwind_shared_objects)
+ set(unwind_static_sources $<TARGET_OBJECTS:unwind_static_objects>)
+ set(unwind_shared_sources $<TARGET_OBJECTS:unwind_shared_objects>)
+else()
+ unwind_object_library(unwind_objects)
+ set(unwind_static_sources $<TARGET_OBJECTS:unwind_objects>)
+ set(unwind_shared_sources $<TARGET_OBJECTS:unwind_objects>)
+endif()
# Build the shared library.
if (LIBUNWIND_ENABLE_SHARED)
- add_library(unwind_shared SHARED $<TARGET_OBJECTS:unwind_objects>)
- target_link_libraries(unwind_shared ${libraries})
+ add_library(unwind_shared SHARED ${unwind_shared_sources})
+ if(COMMAND llvm_setup_rpath)
+ llvm_setup_rpath(unwind_shared)
+ endif()
+ target_link_libraries(unwind_shared PRIVATE ${libraries})
set_target_properties(unwind_shared
PROPERTIES
LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
OUTPUT_NAME "unwind"
VERSION "1.0"
SOVERSION "1")
- list(APPEND LIBUNWIND_TARGETS "unwind_shared")
+ list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared")
+ if (LIBUNWIND_INSTALL_SHARED_LIBRARY)
+ list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared")
+ endif()
endif()
# Build the static library.
if (LIBUNWIND_ENABLE_STATIC)
- add_library(unwind_static STATIC $<TARGET_OBJECTS:unwind_objects>)
- target_link_libraries(unwind_static ${libraries})
+ add_library(unwind_static STATIC ${unwind_static_sources})
+ target_link_libraries(unwind_static PRIVATE ${libraries})
set_target_properties(unwind_static
PROPERTIES
LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
OUTPUT_NAME "unwind")
- list(APPEND LIBUNWIND_TARGETS "unwind_static")
+ list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static")
+ if (LIBUNWIND_INSTALL_STATIC_LIBRARY)
+ list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static")
+ endif()
endif()
# Add a meta-target for both libraries.
-add_custom_target(unwind DEPENDS ${LIBUNWIND_TARGETS})
+add_custom_target(unwind DEPENDS ${LIBUNWIND_BUILD_TARGETS})
if (LIBUNWIND_INSTALL_LIBRARY)
- install(TARGETS ${LIBUNWIND_TARGETS}
+ install(TARGETS ${LIBUNWIND_INSTALL_TARGETS}
LIBRARY DESTINATION ${LIBUNWIND_INSTALL_PREFIX}lib${LIBUNWIND_LIBDIR_SUFFIX} COMPONENT unwind
ARCHIVE DESTINATION ${LIBUNWIND_INSTALL_PREFIX}lib${LIBUNWIND_LIBDIR_SUFFIX} COMPONENT unwind)
endif()
diff --git a/src/CompactUnwinder.hpp b/src/CompactUnwinder.hpp
index 7b97bf8..1c3175d 100644
--- a/src/CompactUnwinder.hpp
+++ b/src/CompactUnwinder.hpp
@@ -1,9 +1,8 @@
//===-------------------------- CompactUnwinder.hpp -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Does runtime stack unwinding using compact unwind encodings.
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index bd1448b..4f5f821 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -1,9 +1,8 @@
//===-------------------------- DwarfInstructions.hpp ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Processor specific interpretation of DWARF unwind info.
@@ -82,12 +81,11 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getP(cfa + (pint_t)savedReg.value);
+ return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getP(
- evaluateExpression((pint_t)savedReg.value, addressSpace,
- registers, cfa));
+ return (pint_t)addressSpace.getRegister(evaluateExpression(
+ (pint_t)savedReg.value, addressSpace, registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
return evaluateExpression((pint_t)savedReg.value, addressSpace,
@@ -159,7 +157,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
&cieInfo) == NULL) {
PrologInfo prolog;
if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
- &prolog)) {
+ R::getArch(), &prolog)) {
// get pointer to cfa (architecture specific)
pint_t cfa = getCFA(addressSpace, prolog, registers);
@@ -198,6 +196,42 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
// restoring SP means setting it to CFA.
newRegisters.setSP(cfa);
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ // If the target is aarch64 then the return address may have been signed
+ // using the v8.3 pointer authentication extensions. The original
+ // return address needs to be authenticated before the return address is
+ // restored. autia1716 is used instead of autia as autia1716 assembles
+ // to a NOP on pre-v8.3a architectures.
+ if ((R::getArch() == REGISTERS_ARM64) &&
+ prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
+#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+ return UNW_ECROSSRASIGNING;
+#else
+ register unsigned long long x17 __asm("x17") = returnAddress;
+ register unsigned long long x16 __asm("x16") = cfa;
+
+ // These are the autia1716/autib1716 instructions. The hint instructions
+ // are used here as gcc does not assemble autia1716/autib1716 for pre
+ // armv8.3a targets.
+ if (cieInfo.addressesSignedWithBKey)
+ asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
+ else
+ asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
+ returnAddress = x17;
+#endif
+ }
+#endif
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+ if (R::getArch() == REGISTERS_SPARC) {
+ // Skip call site instruction and delay slot
+ returnAddress += 8;
+ // Skip unimp instruction if function returns a struct
+ if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
+ returnAddress += 4;
+ }
+#endif
+
// Return address is address after call site instruction, so setting IP to
// that does simualates a return.
newRegisters.setIP(returnAddress);
diff --git a/src/DwarfParser.hpp b/src/DwarfParser.hpp
index 95af7a6..df69c2a 100644
--- a/src/DwarfParser.hpp
+++ b/src/DwarfParser.hpp
@@ -1,9 +1,8 @@
//===--------------------------- DwarfParser.hpp --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Parses DWARF CFIs (FDEs and CIEs).
@@ -17,10 +16,10 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <limits>
#include "libunwind.h"
#include "dwarf2.h"
+#include "Registers.hpp"
#include "config.h"
@@ -50,6 +49,9 @@ public:
bool isSignalFrame;
bool fdesHaveAugmentationData;
uint8_t returnAddressRegister;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ bool addressesSignedWithBKey;
+#endif
};
/// Information about an FDE (Frame Description Entry)
@@ -104,7 +106,7 @@ public:
FDE_Info *fdeInfo, CIE_Info *cieInfo);
static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
const CIE_Info &cieInfo, pint_t upToPC,
- PrologInfo *results);
+ int arch, PrologInfo *results);
static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
@@ -112,7 +114,7 @@ private:
static bool parseInstructions(A &addressSpace, pint_t instructions,
pint_t instructionsEnd, const CIE_Info &cieInfo,
pint_t pcoffset,
- PrologInfoStackEntry *&rememberStack,
+ PrologInfoStackEntry *&rememberStack, int arch,
PrologInfo *results);
};
@@ -264,6 +266,9 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
cieInfo->dataAlignFactor = 0;
cieInfo->isSignalFrame = false;
cieInfo->fdesHaveAugmentationData = false;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ cieInfo->addressesSignedWithBKey = false;
+#endif
cieInfo->cieStart = cie;
pint_t p = cie;
pint_t cieLength = (pint_t)addressSpace.get32(p);
@@ -327,6 +332,11 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
case 'S':
cieInfo->isSignalFrame = true;
break;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ case 'B':
+ cieInfo->addressesSignedWithBKey = true;
+ break;
+#endif
default:
// ignore unknown letters
break;
@@ -344,7 +354,7 @@ template <typename A>
bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
const FDE_Info &fdeInfo,
const CIE_Info &cieInfo, pint_t upToPC,
- PrologInfo *results) {
+ int arch, PrologInfo *results) {
// clear results
memset(results, '\0', sizeof(PrologInfo));
PrologInfoStackEntry *rememberStack = NULL;
@@ -352,10 +362,11 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
// parse CIE then FDE instructions
return parseInstructions(addressSpace, cieInfo.cieInstructions,
cieInfo.cieStart + cieInfo.cieLength, cieInfo,
- (pint_t)(-1), rememberStack, results) &&
+ (pint_t)(-1), rememberStack, arch, results) &&
parseInstructions(addressSpace, fdeInfo.fdeInstructions,
fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
- upToPC - fdeInfo.pcStart, rememberStack, results);
+ upToPC - fdeInfo.pcStart, rememberStack, arch,
+ results);
}
/// "run" the DWARF instructions
@@ -364,7 +375,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
pint_t instructionsEnd,
const CIE_Info &cieInfo, pint_t pcoffset,
PrologInfoStackEntry *&rememberStack,
- PrologInfo *results) {
+ int arch, PrologInfo *results) {
pint_t p = instructions;
pint_t codeOffset = 0;
PrologInfo initialState = *results;
@@ -416,8 +427,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
* cieInfo.dataAlignFactor;
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_offset_extended DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterInCFA;
@@ -429,9 +440,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_restore_extended:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(
- stderr,
- "malformed DW_CFA_restore_extended DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg] = initialState.savedRegisters[reg];
@@ -440,8 +450,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_undefined:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_undefined DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_undefined DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterUnused;
@@ -450,8 +460,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_same_value:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_same_value DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_same_value DWARF unwind, reg too big");
return false;
}
// <rdar://problem/8456377> DW_CFA_same_value unsupported
@@ -467,13 +477,13 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
reg = addressSpace.getULEB128(p, instructionsEnd);
reg2 = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_register DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_register DWARF unwind, reg too big");
return false;
}
if (reg2 > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_register DWARF unwind, reg2 too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_register DWARF unwind, reg2 too big");
return false;
}
results->savedRegisters[reg].location = kRegisterInRegister;
@@ -512,7 +522,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
reg = addressSpace.getULEB128(p, instructionsEnd);
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr, "malformed DW_CFA_def_cfa DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
return false;
}
results->cfaRegister = (uint32_t)reg;
@@ -523,9 +533,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_def_cfa_register:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(
- stderr,
- "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
return false;
}
results->cfaRegister = (uint32_t)reg;
@@ -542,7 +551,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
results->cfaRegister = 0;
results->cfaExpression = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
- assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+ assert(length < static_cast<pint_t>(~0) && "pointer overflow");
p += static_cast<pint_t>(length);
_LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
", length=%" PRIu64 ")\n",
@@ -551,14 +560,14 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_expression:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_expression DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_expression DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterAtExpression;
results->savedRegisters[reg].value = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
- assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+ assert(length < static_cast<pint_t>(~0) && "pointer overflow");
p += static_cast<pint_t>(length);
_LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
"expression=0x%" PRIx64 ", "
@@ -568,9 +577,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_offset_extended_sf:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(
- stderr,
- "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
return false;
}
offset =
@@ -586,8 +594,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
offset =
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
return false;
}
results->cfaRegister = (uint32_t)reg;
@@ -606,7 +614,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_val_offset:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
+ _LIBUNWIND_LOG(
"malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
") out of range\n",
reg);
@@ -623,8 +631,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_val_offset_sf:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
return false;
}
offset =
@@ -638,14 +646,14 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_val_expression:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_val_expression DWARF unwind, reg too big\n");
+ _LIBUNWIND_LOG0(
+ "malformed DW_CFA_val_expression DWARF unwind, reg too big");
return false;
}
results->savedRegisters[reg].location = kRegisterIsExpression;
results->savedRegisters[reg].value = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
- assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+ assert(length < static_cast<pint_t>(~0) && "pointer overflow");
p += static_cast<pint_t>(length);
_LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
"expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
@@ -659,8 +667,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_GNU_negative_offset_extended:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
- fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended DWARF "
- "unwind, reg too big\n");
+ _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
+ "unwind, reg too big");
return false;
}
offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
@@ -670,14 +678,51 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
_LIBUNWIND_TRACE_DWARF(
"DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
break;
+
+#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC)
+ // The same constant is used to represent different instructions on
+ // AArch64 (negate_ra_state) and SPARC (window_save).
+ static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
+ "uses the same constant");
+ case DW_CFA_AARCH64_negate_ra_state:
+ switch (arch) {
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ case REGISTERS_ARM64:
+ results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1;
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
+ break;
+#endif
+#if defined(_LIBUNWIND_TARGET_SPARC)
+ // case DW_CFA_GNU_window_save:
+ case REGISTERS_SPARC:
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
+ for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
+ results->savedRegisters[reg].location = kRegisterInRegister;
+ results->savedRegisters[reg].value =
+ ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0;
+ }
+
+ for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
+ results->savedRegisters[reg].location = kRegisterInCFA;
+ results->savedRegisters[reg].value =
+ ((int64_t)reg - UNW_SPARC_L0) * 4;
+ }
+ break;
+#endif
+ }
+ break;
+#else
+ (void)arch;
+#endif
+
default:
operand = opcode & 0x3F;
switch (opcode & 0xC0) {
case DW_CFA_offset:
reg = operand;
if (reg > kMaxRegisterNumber) {
- fprintf(stderr, "malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
- ") out of range\n",
+ _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
+ ") out of range",
reg);
return false;
}
@@ -696,8 +741,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
case DW_CFA_restore:
reg = operand;
if (reg > kMaxRegisterNumber) {
- fprintf(stderr, "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
- ") out of range\n",
+ _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
+ ") out of range",
reg);
return false;
}
diff --git a/src/EHHeaderParser.hpp b/src/EHHeaderParser.hpp
index 9bdaf55..0101835 100644
--- a/src/EHHeaderParser.hpp
+++ b/src/EHHeaderParser.hpp
@@ -1,9 +1,8 @@
//===------------------------- EHHeaderParser.hpp -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Parses ELF .eh_frame_hdr sections.
@@ -36,7 +35,7 @@ public:
uint8_t table_enc;
};
- static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
+ static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
EHHeaderInfo &ehHdrInfo);
static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
uint32_t sectionLength,
@@ -53,12 +52,14 @@ private:
};
template <typename A>
-void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
+bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
pint_t p = ehHdrStart;
uint8_t version = addressSpace.get8(p++);
- if (version != 1)
- _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version");
+ if (version != 1) {
+ _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");
+ return false;
+ }
uint8_t eh_frame_ptr_enc = addressSpace.get8(p++);
uint8_t fde_count_enc = addressSpace.get8(p++);
@@ -71,6 +72,8 @@ void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
? 0
: addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart);
ehHdrInfo.table = p;
+
+ return true;
}
template <typename A>
@@ -102,7 +105,9 @@ bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
pint_t ehHdrEnd = ehHdrStart + sectionLength;
EHHeaderParser<A>::EHHeaderInfo hdrInfo;
- EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo);
+ if (!EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd,
+ hdrInfo))
+ return false;
size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc);
pint_t tableEntry;
diff --git a/src/RWMutex.hpp b/src/RWMutex.hpp
index 50a78a5..92c8db3 100644
--- a/src/RWMutex.hpp
+++ b/src/RWMutex.hpp
@@ -1,9 +1,8 @@
//===----------------------------- Registers.hpp --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Abstract interface to shared reader/writer log, hiding platform and
diff --git a/src/Registers.hpp b/src/Registers.hpp
index d881e20..e88ba51 100644
--- a/src/Registers.hpp
+++ b/src/Registers.hpp
@@ -1,9 +1,8 @@
//===----------------------------- Registers.hpp --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Models register sets for supported processors.
@@ -24,6 +23,18 @@ namespace libunwind {
// For emulating 128-bit registers
struct v128 { uint32_t vec[4]; };
+enum {
+ REGISTERS_X86,
+ REGISTERS_X86_64,
+ REGISTERS_PPC,
+ REGISTERS_PPC64,
+ REGISTERS_ARM64,
+ REGISTERS_ARM,
+ REGISTERS_OR1K,
+ REGISTERS_MIPS_O32,
+ REGISTERS_MIPS_NEWABI,
+ REGISTERS_SPARC,
+};
#if defined(_LIBUNWIND_TARGET_I386)
/// Registers_x86 holds the register state of a thread in a 32-bit intel
@@ -42,9 +53,10 @@ public:
bool validVectorRegister(int) const { return false; }
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
+ static int getArch() { return REGISTERS_X86; }
uint32_t getSP() const { return _registers.__esp; }
void setSP(uint32_t value) { _registers.__esp = value; }
@@ -248,9 +260,10 @@ public:
bool validVectorRegister(int) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
+ static int getArch() { return REGISTERS_X86_64; }
uint64_t getSP() const { return _registers.__rsp; }
void setSP(uint64_t value) { _registers.__rsp = value; }
@@ -517,6 +530,7 @@ inline bool Registers_x86_64::validVectorRegister(int regNum) const {
return false;
return true;
#else
+ (void)regNum; // suppress unused parameter warning
return false;
#endif
}
@@ -526,6 +540,7 @@ inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
assert(validVectorRegister(regNum));
return _xmm[regNum - UNW_X86_64_XMM0];
#else
+ (void)regNum; // suppress unused parameter warning
_LIBUNWIND_ABORT("no x86_64 vector registers");
#endif
}
@@ -535,6 +550,7 @@ inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
assert(validVectorRegister(regNum));
_xmm[regNum - UNW_X86_64_XMM0] = value;
#else
+ (void)regNum; (void)value; // suppress unused parameter warnings
_LIBUNWIND_ABORT("no x86_64 vector registers");
#endif
}
@@ -558,9 +574,10 @@ public:
bool validVectorRegister(int num) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
+ static int getArch() { return REGISTERS_PPC; }
uint64_t getSP() const { return _registers.__r1; }
void setSP(uint32_t value) { _registers.__r1 = value; }
@@ -1106,6 +1123,648 @@ inline const char *Registers_ppc::getRegisterName(int regNum) {
}
#endif // _LIBUNWIND_TARGET_PPC
+#if defined(_LIBUNWIND_TARGET_PPC64)
+/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
+/// process.
+class _LIBUNWIND_HIDDEN Registers_ppc64 {
+public:
+ Registers_ppc64();
+ Registers_ppc64(const void *registers);
+
+ bool validRegister(int num) const;
+ uint64_t getRegister(int num) const;
+ void setRegister(int num, uint64_t value);
+ bool validFloatRegister(int num) const;
+ double getFloatRegister(int num) const;
+ void setFloatRegister(int num, double value);
+ bool validVectorRegister(int num) const;
+ v128 getVectorRegister(int num) const;
+ void setVectorRegister(int num, v128 value);
+ static const char *getRegisterName(int num);
+ void jumpto();
+ static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
+ static int getArch() { return REGISTERS_PPC64; }
+
+ uint64_t getSP() const { return _registers.__r1; }
+ void setSP(uint64_t value) { _registers.__r1 = value; }
+ uint64_t getIP() const { return _registers.__srr0; }
+ void setIP(uint64_t value) { _registers.__srr0 = value; }
+
+private:
+ struct ppc64_thread_state_t {
+ uint64_t __srr0; // Instruction address register (PC)
+ uint64_t __srr1; // Machine state register (supervisor)
+ uint64_t __r0;
+ uint64_t __r1;
+ uint64_t __r2;
+ uint64_t __r3;
+ uint64_t __r4;
+ uint64_t __r5;
+ uint64_t __r6;
+ uint64_t __r7;
+ uint64_t __r8;
+ uint64_t __r9;
+ uint64_t __r10;
+ uint64_t __r11;
+ uint64_t __r12;
+ uint64_t __r13;
+ uint64_t __r14;
+ uint64_t __r15;
+ uint64_t __r16;
+ uint64_t __r17;
+ uint64_t __r18;
+ uint64_t __r19;
+ uint64_t __r20;
+ uint64_t __r21;
+ uint64_t __r22;
+ uint64_t __r23;
+ uint64_t __r24;
+ uint64_t __r25;
+ uint64_t __r26;
+ uint64_t __r27;
+ uint64_t __r28;
+ uint64_t __r29;
+ uint64_t __r30;
+ uint64_t __r31;
+ uint64_t __cr; // Condition register
+ uint64_t __xer; // User's integer exception register
+ uint64_t __lr; // Link register
+ uint64_t __ctr; // Count register
+ uint64_t __vrsave; // Vector Save Register
+ };
+
+ union ppc64_vsr_t {
+ struct asfloat_s {
+ double f;
+ uint64_t v2;
+ } asfloat;
+ v128 v;
+ };
+
+ ppc64_thread_state_t _registers;
+ ppc64_vsr_t _vectorScalarRegisters[64];
+
+ static int getVectorRegNum(int num);
+};
+
+inline Registers_ppc64::Registers_ppc64(const void *registers) {
+ static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
+ "ppc64 registers do not fit into unw_context_t");
+ memcpy(&_registers, static_cast<const uint8_t *>(registers),
+ sizeof(_registers));
+ static_assert(sizeof(_registers) == 312,
+ "expected vector scalar register offset to be 312");
+ memcpy(&_vectorScalarRegisters,
+ static_cast<const uint8_t *>(registers) + sizeof(_registers),
+ sizeof(_vectorScalarRegisters));
+ static_assert(sizeof(_registers) +
+ sizeof(_vectorScalarRegisters) == 1336,
+ "expected vector register offset to be 1336 bytes");
+}
+
+inline Registers_ppc64::Registers_ppc64() {
+ memset(&_registers, 0, sizeof(_registers));
+ memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
+}
+
+inline bool Registers_ppc64::validRegister(int regNum) const {
+ switch (regNum) {
+ case UNW_REG_IP:
+ case UNW_REG_SP:
+ case UNW_PPC64_XER:
+ case UNW_PPC64_LR:
+ case UNW_PPC64_CTR:
+ case UNW_PPC64_VRSAVE:
+ return true;
+ }
+
+ if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
+ return true;
+ if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
+ return true;
+
+ return false;
+}
+
+inline uint64_t Registers_ppc64::getRegister(int regNum) const {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return _registers.__srr0;
+ case UNW_PPC64_R0:
+ return _registers.__r0;
+ case UNW_PPC64_R1:
+ case UNW_REG_SP:
+ return _registers.__r1;
+ case UNW_PPC64_R2:
+ return _registers.__r2;
+ case UNW_PPC64_R3:
+ return _registers.__r3;
+ case UNW_PPC64_R4:
+ return _registers.__r4;
+ case UNW_PPC64_R5:
+ return _registers.__r5;
+ case UNW_PPC64_R6:
+ return _registers.__r6;
+ case UNW_PPC64_R7:
+ return _registers.__r7;
+ case UNW_PPC64_R8:
+ return _registers.__r8;
+ case UNW_PPC64_R9:
+ return _registers.__r9;
+ case UNW_PPC64_R10:
+ return _registers.__r10;
+ case UNW_PPC64_R11:
+ return _registers.__r11;
+ case UNW_PPC64_R12:
+ return _registers.__r12;
+ case UNW_PPC64_R13:
+ return _registers.__r13;
+ case UNW_PPC64_R14:
+ return _registers.__r14;
+ case UNW_PPC64_R15:
+ return _registers.__r15;
+ case UNW_PPC64_R16:
+ return _registers.__r16;
+ case UNW_PPC64_R17:
+ return _registers.__r17;
+ case UNW_PPC64_R18:
+ return _registers.__r18;
+ case UNW_PPC64_R19:
+ return _registers.__r19;
+ case UNW_PPC64_R20:
+ return _registers.__r20;
+ case UNW_PPC64_R21:
+ return _registers.__r21;
+ case UNW_PPC64_R22:
+ return _registers.__r22;
+ case UNW_PPC64_R23:
+ return _registers.__r23;
+ case UNW_PPC64_R24:
+ return _registers.__r24;
+ case UNW_PPC64_R25:
+ return _registers.__r25;
+ case UNW_PPC64_R26:
+ return _registers.__r26;
+ case UNW_PPC64_R27:
+ return _registers.__r27;
+ case UNW_PPC64_R28:
+ return _registers.__r28;
+ case UNW_PPC64_R29:
+ return _registers.__r29;
+ case UNW_PPC64_R30:
+ return _registers.__r30;
+ case UNW_PPC64_R31:
+ return _registers.__r31;
+ case UNW_PPC64_CR0:
+ return (_registers.__cr & 0xF0000000);
+ case UNW_PPC64_CR1:
+ return (_registers.__cr & 0x0F000000);
+ case UNW_PPC64_CR2:
+ return (_registers.__cr & 0x00F00000);
+ case UNW_PPC64_CR3:
+ return (_registers.__cr & 0x000F0000);
+ case UNW_PPC64_CR4:
+ return (_registers.__cr & 0x0000F000);
+ case UNW_PPC64_CR5:
+ return (_registers.__cr & 0x00000F00);
+ case UNW_PPC64_CR6:
+ return (_registers.__cr & 0x000000F0);
+ case UNW_PPC64_CR7:
+ return (_registers.__cr & 0x0000000F);
+ case UNW_PPC64_XER:
+ return _registers.__xer;
+ case UNW_PPC64_LR:
+ return _registers.__lr;
+ case UNW_PPC64_CTR:
+ return _registers.__ctr;
+ case UNW_PPC64_VRSAVE:
+ return _registers.__vrsave;
+ }
+ _LIBUNWIND_ABORT("unsupported ppc64 register");
+}
+
+inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ _registers.__srr0 = value;
+ return;
+ case UNW_PPC64_R0:
+ _registers.__r0 = value;
+ return;
+ case UNW_PPC64_R1:
+ case UNW_REG_SP:
+ _registers.__r1 = value;
+ return;
+ case UNW_PPC64_R2:
+ _registers.__r2 = value;
+ return;
+ case UNW_PPC64_R3:
+ _registers.__r3 = value;
+ return;
+ case UNW_PPC64_R4:
+ _registers.__r4 = value;
+ return;
+ case UNW_PPC64_R5:
+ _registers.__r5 = value;
+ return;
+ case UNW_PPC64_R6:
+ _registers.__r6 = value;
+ return;
+ case UNW_PPC64_R7:
+ _registers.__r7 = value;
+ return;
+ case UNW_PPC64_R8:
+ _registers.__r8 = value;
+ return;
+ case UNW_PPC64_R9:
+ _registers.__r9 = value;
+ return;
+ case UNW_PPC64_R10:
+ _registers.__r10 = value;
+ return;
+ case UNW_PPC64_R11:
+ _registers.__r11 = value;
+ return;
+ case UNW_PPC64_R12:
+ _registers.__r12 = value;
+ return;
+ case UNW_PPC64_R13:
+ _registers.__r13 = value;
+ return;
+ case UNW_PPC64_R14:
+ _registers.__r14 = value;
+ return;
+ case UNW_PPC64_R15:
+ _registers.__r15 = value;
+ return;
+ case UNW_PPC64_R16:
+ _registers.__r16 = value;
+ return;
+ case UNW_PPC64_R17:
+ _registers.__r17 = value;
+ return;
+ case UNW_PPC64_R18:
+ _registers.__r18 = value;
+ return;
+ case UNW_PPC64_R19:
+ _registers.__r19 = value;
+ return;
+ case UNW_PPC64_R20:
+ _registers.__r20 = value;
+ return;
+ case UNW_PPC64_R21:
+ _registers.__r21 = value;
+ return;
+ case UNW_PPC64_R22:
+ _registers.__r22 = value;
+ return;
+ case UNW_PPC64_R23:
+ _registers.__r23 = value;
+ return;
+ case UNW_PPC64_R24:
+ _registers.__r24 = value;
+ return;
+ case UNW_PPC64_R25:
+ _registers.__r25 = value;
+ return;
+ case UNW_PPC64_R26:
+ _registers.__r26 = value;
+ return;
+ case UNW_PPC64_R27:
+ _registers.__r27 = value;
+ return;
+ case UNW_PPC64_R28:
+ _registers.__r28 = value;
+ return;
+ case UNW_PPC64_R29:
+ _registers.__r29 = value;
+ return;
+ case UNW_PPC64_R30:
+ _registers.__r30 = value;
+ return;
+ case UNW_PPC64_R31:
+ _registers.__r31 = value;
+ return;
+ case UNW_PPC64_CR0:
+ _registers.__cr &= 0x0FFFFFFF;
+ _registers.__cr |= (value & 0xF0000000);
+ return;
+ case UNW_PPC64_CR1:
+ _registers.__cr &= 0xF0FFFFFF;
+ _registers.__cr |= (value & 0x0F000000);
+ return;
+ case UNW_PPC64_CR2:
+ _registers.__cr &= 0xFF0FFFFF;
+ _registers.__cr |= (value & 0x00F00000);
+ return;
+ case UNW_PPC64_CR3:
+ _registers.__cr &= 0xFFF0FFFF;
+ _registers.__cr |= (value & 0x000F0000);
+ return;
+ case UNW_PPC64_CR4:
+ _registers.__cr &= 0xFFFF0FFF;
+ _registers.__cr |= (value & 0x0000F000);
+ return;
+ case UNW_PPC64_CR5:
+ _registers.__cr &= 0xFFFFF0FF;
+ _registers.__cr |= (value & 0x00000F00);
+ return;
+ case UNW_PPC64_CR6:
+ _registers.__cr &= 0xFFFFFF0F;
+ _registers.__cr |= (value & 0x000000F0);
+ return;
+ case UNW_PPC64_CR7:
+ _registers.__cr &= 0xFFFFFFF0;
+ _registers.__cr |= (value & 0x0000000F);
+ return;
+ case UNW_PPC64_XER:
+ _registers.__xer = value;
+ return;
+ case UNW_PPC64_LR:
+ _registers.__lr = value;
+ return;
+ case UNW_PPC64_CTR:
+ _registers.__ctr = value;
+ return;
+ case UNW_PPC64_VRSAVE:
+ _registers.__vrsave = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported ppc64 register");
+}
+
+inline bool Registers_ppc64::validFloatRegister(int regNum) const {
+ return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
+}
+
+inline double Registers_ppc64::getFloatRegister(int regNum) const {
+ assert(validFloatRegister(regNum));
+ return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
+}
+
+inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
+ assert(validFloatRegister(regNum));
+ _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
+}
+
+inline bool Registers_ppc64::validVectorRegister(int regNum) const {
+#ifdef PPC64_HAS_VMX
+ if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
+ return true;
+ if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
+ return true;
+#else
+ if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
+ return true;
+#endif
+ return false;
+}
+
+inline int Registers_ppc64::getVectorRegNum(int num)
+{
+ if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
+ return num - UNW_PPC64_VS0;
+ else
+ return num - UNW_PPC64_VS32 + 32;
+}
+
+inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
+ assert(validVectorRegister(regNum));
+ return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
+}
+
+inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
+ assert(validVectorRegister(regNum));
+ _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
+}
+
+inline const char *Registers_ppc64::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return "ip";
+ case UNW_REG_SP:
+ return "sp";
+ case UNW_PPC64_R0:
+ return "r0";
+ case UNW_PPC64_R1:
+ return "r1";
+ case UNW_PPC64_R2:
+ return "r2";
+ case UNW_PPC64_R3:
+ return "r3";
+ case UNW_PPC64_R4:
+ return "r4";
+ case UNW_PPC64_R5:
+ return "r5";
+ case UNW_PPC64_R6:
+ return "r6";
+ case UNW_PPC64_R7:
+ return "r7";
+ case UNW_PPC64_R8:
+ return "r8";
+ case UNW_PPC64_R9:
+ return "r9";
+ case UNW_PPC64_R10:
+ return "r10";
+ case UNW_PPC64_R11:
+ return "r11";
+ case UNW_PPC64_R12:
+ return "r12";
+ case UNW_PPC64_R13:
+ return "r13";
+ case UNW_PPC64_R14:
+ return "r14";
+ case UNW_PPC64_R15:
+ return "r15";
+ case UNW_PPC64_R16:
+ return "r16";
+ case UNW_PPC64_R17:
+ return "r17";
+ case UNW_PPC64_R18:
+ return "r18";
+ case UNW_PPC64_R19:
+ return "r19";
+ case UNW_PPC64_R20:
+ return "r20";
+ case UNW_PPC64_R21:
+ return "r21";
+ case UNW_PPC64_R22:
+ return "r22";
+ case UNW_PPC64_R23:
+ return "r23";
+ case UNW_PPC64_R24:
+ return "r24";
+ case UNW_PPC64_R25:
+ return "r25";
+ case UNW_PPC64_R26:
+ return "r26";
+ case UNW_PPC64_R27:
+ return "r27";
+ case UNW_PPC64_R28:
+ return "r28";
+ case UNW_PPC64_R29:
+ return "r29";
+ case UNW_PPC64_R30:
+ return "r30";
+ case UNW_PPC64_R31:
+ return "r31";
+ case UNW_PPC64_CR0:
+ return "cr0";
+ case UNW_PPC64_CR1:
+ return "cr1";
+ case UNW_PPC64_CR2:
+ return "cr2";
+ case UNW_PPC64_CR3:
+ return "cr3";
+ case UNW_PPC64_CR4:
+ return "cr4";
+ case UNW_PPC64_CR5:
+ return "cr5";
+ case UNW_PPC64_CR6:
+ return "cr6";
+ case UNW_PPC64_CR7:
+ return "cr7";
+ case UNW_PPC64_XER:
+ return "xer";
+ case UNW_PPC64_LR:
+ return "lr";
+ case UNW_PPC64_CTR:
+ return "ctr";
+ case UNW_PPC64_VRSAVE:
+ return "vrsave";
+ case UNW_PPC64_F0:
+ return "fp0";
+ case UNW_PPC64_F1:
+ return "fp1";
+ case UNW_PPC64_F2:
+ return "fp2";
+ case UNW_PPC64_F3:
+ return "fp3";
+ case UNW_PPC64_F4:
+ return "fp4";
+ case UNW_PPC64_F5:
+ return "fp5";
+ case UNW_PPC64_F6:
+ return "fp6";
+ case UNW_PPC64_F7:
+ return "fp7";
+ case UNW_PPC64_F8:
+ return "fp8";
+ case UNW_PPC64_F9:
+ return "fp9";
+ case UNW_PPC64_F10:
+ return "fp10";
+ case UNW_PPC64_F11:
+ return "fp11";
+ case UNW_PPC64_F12:
+ return "fp12";
+ case UNW_PPC64_F13:
+ return "fp13";
+ case UNW_PPC64_F14:
+ return "fp14";
+ case UNW_PPC64_F15:
+ return "fp15";
+ case UNW_PPC64_F16:
+ return "fp16";
+ case UNW_PPC64_F17:
+ return "fp17";
+ case UNW_PPC64_F18:
+ return "fp18";
+ case UNW_PPC64_F19:
+ return "fp19";
+ case UNW_PPC64_F20:
+ return "fp20";
+ case UNW_PPC64_F21:
+ return "fp21";
+ case UNW_PPC64_F22:
+ return "fp22";
+ case UNW_PPC64_F23:
+ return "fp23";
+ case UNW_PPC64_F24:
+ return "fp24";
+ case UNW_PPC64_F25:
+ return "fp25";
+ case UNW_PPC64_F26:
+ return "fp26";
+ case UNW_PPC64_F27:
+ return "fp27";
+ case UNW_PPC64_F28:
+ return "fp28";
+ case UNW_PPC64_F29:
+ return "fp29";
+ case UNW_PPC64_F30:
+ return "fp30";
+ case UNW_PPC64_F31:
+ return "fp31";
+ case UNW_PPC64_V0:
+ return "v0";
+ case UNW_PPC64_V1:
+ return "v1";
+ case UNW_PPC64_V2:
+ return "v2";
+ case UNW_PPC64_V3:
+ return "v3";
+ case UNW_PPC64_V4:
+ return "v4";
+ case UNW_PPC64_V5:
+ return "v5";
+ case UNW_PPC64_V6:
+ return "v6";
+ case UNW_PPC64_V7:
+ return "v7";
+ case UNW_PPC64_V8:
+ return "v8";
+ case UNW_PPC64_V9:
+ return "v9";
+ case UNW_PPC64_V10:
+ return "v10";
+ case UNW_PPC64_V11:
+ return "v11";
+ case UNW_PPC64_V12:
+ return "v12";
+ case UNW_PPC64_V13:
+ return "v13";
+ case UNW_PPC64_V14:
+ return "v14";
+ case UNW_PPC64_V15:
+ return "v15";
+ case UNW_PPC64_V16:
+ return "v16";
+ case UNW_PPC64_V17:
+ return "v17";
+ case UNW_PPC64_V18:
+ return "v18";
+ case UNW_PPC64_V19:
+ return "v19";
+ case UNW_PPC64_V20:
+ return "v20";
+ case UNW_PPC64_V21:
+ return "v21";
+ case UNW_PPC64_V22:
+ return "v22";
+ case UNW_PPC64_V23:
+ return "v23";
+ case UNW_PPC64_V24:
+ return "v24";
+ case UNW_PPC64_V25:
+ return "v25";
+ case UNW_PPC64_V26:
+ return "v26";
+ case UNW_PPC64_V27:
+ return "v27";
+ case UNW_PPC64_V28:
+ return "v28";
+ case UNW_PPC64_V29:
+ return "v29";
+ case UNW_PPC64_V30:
+ return "v30";
+ case UNW_PPC64_V31:
+ return "v31";
+ }
+ return "unknown register";
+}
+#endif // _LIBUNWIND_TARGET_PPC64
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
/// Registers_arm64 holds the register state of a thread in a 64-bit arm
@@ -1124,9 +1783,10 @@ public:
bool validVectorRegister(int num) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
+ static int getArch() { return REGISTERS_ARM64; }
uint64_t getSP() const { return _registers.__sp; }
void setSP(uint64_t value) { _registers.__sp = value; }
@@ -1142,7 +1802,7 @@ private:
uint64_t __lr; // Link register x30
uint64_t __sp; // Stack pointer x31
uint64_t __pc; // Program counter
- uint64_t padding; // 16-byte align
+ uint64_t __ra_sign_state; // RA sign state register
};
GPRs _registers;
@@ -1178,6 +1838,8 @@ inline bool Registers_arm64::validRegister(int regNum) const {
return false;
if (regNum > 95)
return false;
+ if (regNum == UNW_ARM64_RA_SIGN_STATE)
+ return true;
if ((regNum > 31) && (regNum < 64))
return false;
return true;
@@ -1188,6 +1850,8 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const {
return _registers.__pc;
if (regNum == UNW_REG_SP)
return _registers.__sp;
+ if (regNum == UNW_ARM64_RA_SIGN_STATE)
+ return _registers.__ra_sign_state;
if ((regNum >= 0) && (regNum < 32))
return _registers.__x[regNum];
_LIBUNWIND_ABORT("unsupported arm64 register");
@@ -1198,6 +1862,8 @@ inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
_registers.__pc = value;
else if (regNum == UNW_REG_SP)
_registers.__sp = value;
+ else if (regNum == UNW_ARM64_RA_SIGN_STATE)
+ _registers.__ra_sign_state = value;
else if ((regNum >= 0) && (regNum < 32))
_registers.__x[regNum] = value;
else
@@ -1394,12 +2060,13 @@ public:
bool validVectorRegister(int num) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto() {
restoreSavedFloatRegisters();
restoreCoreAndJumpTo();
}
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
+ static int getArch() { return REGISTERS_ARM; }
uint32_t getSP() const { return _registers.__sp; }
void setSP(uint32_t value) { _registers.__sp = value; }
@@ -1436,16 +2103,16 @@ private:
uint32_t __pc; // Program counter r15
};
- static void saveVFPWithFSTMD(unw_fpreg_t*);
- static void saveVFPWithFSTMX(unw_fpreg_t*);
- static void saveVFPv3(unw_fpreg_t*);
- static void restoreVFPWithFLDMD(unw_fpreg_t*);
- static void restoreVFPWithFLDMX(unw_fpreg_t*);
- static void restoreVFPv3(unw_fpreg_t*);
+ static void saveVFPWithFSTMD(void*);
+ static void saveVFPWithFSTMX(void*);
+ static void saveVFPv3(void*);
+ static void restoreVFPWithFLDMD(void*);
+ static void restoreVFPWithFLDMX(void*);
+ static void restoreVFPv3(void*);
#if defined(__ARM_WMMX)
- static void saveiWMMX(unw_fpreg_t*);
+ static void saveiWMMX(void*);
static void saveiWMMXControl(uint32_t*);
- static void restoreiWMMX(unw_fpreg_t*);
+ static void restoreiWMMX(void*);
static void restoreiWMMXControl(uint32_t*);
#endif
void restoreCoreAndJumpTo();
@@ -1508,7 +2175,7 @@ inline Registers_arm::Registers_arm()
memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
#if defined(__ARM_WMMX)
_saved_iwmmx = false;
- _saved_iwmmx_control = false;
+ _saved_iwmmx_control = false;
memset(&_iwmmx, 0, sizeof(_iwmmx));
memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
#endif
@@ -1874,18 +2541,21 @@ public:
bool validVectorRegister(int num) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
+ static int getArch() { return REGISTERS_OR1K; }
uint64_t getSP() const { return _registers.__r[1]; }
void setSP(uint32_t value) { _registers.__r[1] = value; }
- uint64_t getIP() const { return _registers.__r[9]; }
- void setIP(uint32_t value) { _registers.__r[9] = value; }
+ uint64_t getIP() const { return _registers.__pc; }
+ void setIP(uint32_t value) { _registers.__pc = value; }
private:
struct or1k_thread_state_t {
- unsigned int __r[32];
+ unsigned int __r[32]; // r0-r31
+ unsigned int __pc; // Program counter
+ unsigned int __epcr; // Program counter at exception
};
or1k_thread_state_t _registers;
@@ -1911,6 +2581,8 @@ inline bool Registers_or1k::validRegister(int regNum) const {
return false;
if (regNum <= UNW_OR1K_R31)
return true;
+ if (regNum == UNW_OR1K_EPCR)
+ return true;
return false;
}
@@ -1920,9 +2592,11 @@ inline uint32_t Registers_or1k::getRegister(int regNum) const {
switch (regNum) {
case UNW_REG_IP:
- return _registers.__r[9];
+ return _registers.__pc;
case UNW_REG_SP:
return _registers.__r[1];
+ case UNW_OR1K_EPCR:
+ return _registers.__epcr;
}
_LIBUNWIND_ABORT("unsupported or1k register");
}
@@ -1935,11 +2609,14 @@ inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
switch (regNum) {
case UNW_REG_IP:
- _registers.__r[9] = value;
+ _registers.__pc = value;
return;
case UNW_REG_SP:
_registers.__r[1] = value;
return;
+ case UNW_OR1K_EPCR:
+ _registers.__epcr = value;
+ return;
}
_LIBUNWIND_ABORT("unsupported or1k register");
}
@@ -2035,6 +2712,8 @@ inline const char *Registers_or1k::getRegisterName(int regNum) {
return "r30";
case UNW_OR1K_R31:
return "r31";
+ case UNW_OR1K_EPCR:
+ return "EPCR";
default:
return "unknown register";
}
@@ -2059,9 +2738,10 @@ public:
bool validVectorRegister(int num) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+ static int getArch() { return REGISTERS_MIPS_O32; }
uint32_t getSP() const { return _registers.__r[29]; }
void setSP(uint32_t value) { _registers.__r[29] = value; }
@@ -2077,6 +2757,14 @@ private:
};
mips_o32_thread_state_t _registers;
+#ifdef __mips_hard_float
+ /// O32 with 32-bit floating point registers only uses half of this
+ /// space. However, using the same layout for 32-bit vs 64-bit
+ /// floating point registers results in a single context size for
+ /// O32 with hard float.
+ uint32_t _padding;
+ double _floats[32];
+#endif
};
inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
@@ -2099,17 +2787,34 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
return false;
if (regNum <= UNW_MIPS_R31)
return true;
+#if __mips_isa_rev != 6
if (regNum == UNW_MIPS_HI)
return true;
if (regNum == UNW_MIPS_LO)
return true;
- // FIXME: Hard float, DSP accumulator registers, MSA registers
+#endif
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
+ // FIXME: DSP accumulator registers, MSA registers
return false;
}
inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
return _registers.__r[regNum - UNW_MIPS_R0];
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+ uint32_t *p;
+
+ if (regNum % 2 == 0)
+ p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+ else
+ p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+ return *p;
+ }
+#endif
switch (regNum) {
case UNW_REG_IP:
@@ -2129,6 +2834,18 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
_registers.__r[regNum - UNW_MIPS_R0] = value;
return;
}
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+ uint32_t *p;
+
+ if (regNum % 2 == 0)
+ p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+ else
+ p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+ *p = value;
+ return;
+ }
+#endif
switch (regNum) {
case UNW_REG_IP:
@@ -2147,17 +2864,31 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
_LIBUNWIND_ABORT("unsupported mips_o32 register");
}
-inline bool Registers_mips_o32::validFloatRegister(int /* regNum */) const {
+inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
return false;
}
-inline double Registers_mips_o32::getFloatRegister(int /* regNum */) const {
+inline double Registers_mips_o32::getFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_MIPS_F0];
+#else
_LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
}
-inline void Registers_mips_o32::setFloatRegister(int /* regNum */,
- double /* value */) {
+inline void Registers_mips_o32::setFloatRegister(int regNum,
+ double value) {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_MIPS_F0] = value;
+#else
_LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
}
inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
@@ -2238,6 +2969,70 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
return "$30";
case UNW_MIPS_R31:
return "$31";
+ case UNW_MIPS_F0:
+ return "$f0";
+ case UNW_MIPS_F1:
+ return "$f1";
+ case UNW_MIPS_F2:
+ return "$f2";
+ case UNW_MIPS_F3:
+ return "$f3";
+ case UNW_MIPS_F4:
+ return "$f4";
+ case UNW_MIPS_F5:
+ return "$f5";
+ case UNW_MIPS_F6:
+ return "$f6";
+ case UNW_MIPS_F7:
+ return "$f7";
+ case UNW_MIPS_F8:
+ return "$f8";
+ case UNW_MIPS_F9:
+ return "$f9";
+ case UNW_MIPS_F10:
+ return "$f10";
+ case UNW_MIPS_F11:
+ return "$f11";
+ case UNW_MIPS_F12:
+ return "$f12";
+ case UNW_MIPS_F13:
+ return "$f13";
+ case UNW_MIPS_F14:
+ return "$f14";
+ case UNW_MIPS_F15:
+ return "$f15";
+ case UNW_MIPS_F16:
+ return "$f16";
+ case UNW_MIPS_F17:
+ return "$f17";
+ case UNW_MIPS_F18:
+ return "$f18";
+ case UNW_MIPS_F19:
+ return "$f19";
+ case UNW_MIPS_F20:
+ return "$f20";
+ case UNW_MIPS_F21:
+ return "$f21";
+ case UNW_MIPS_F22:
+ return "$f22";
+ case UNW_MIPS_F23:
+ return "$f23";
+ case UNW_MIPS_F24:
+ return "$f24";
+ case UNW_MIPS_F25:
+ return "$f25";
+ case UNW_MIPS_F26:
+ return "$f26";
+ case UNW_MIPS_F27:
+ return "$f27";
+ case UNW_MIPS_F28:
+ return "$f28";
+ case UNW_MIPS_F29:
+ return "$f29";
+ case UNW_MIPS_F30:
+ return "$f30";
+ case UNW_MIPS_F31:
+ return "$f31";
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
@@ -2248,13 +3043,13 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
}
#endif // _LIBUNWIND_TARGET_MIPS_O32
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
-/// Registers_mips_n64 holds the register state of a thread in a 64-bit MIPS
-/// process.
-class _LIBUNWIND_HIDDEN Registers_mips_n64 {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+/// Registers_mips_newabi holds the register state of a thread in a
+/// MIPS process using NEWABI (the N32 or N64 ABIs).
+class _LIBUNWIND_HIDDEN Registers_mips_newabi {
public:
- Registers_mips_n64();
- Registers_mips_n64(const void *registers);
+ Registers_mips_newabi();
+ Registers_mips_newabi(const void *registers);
bool validRegister(int num) const;
uint64_t getRegister(int num) const;
@@ -2265,9 +3060,10 @@ public:
bool validVectorRegister(int num) const;
v128 getVectorRegister(int num) const;
void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
+ static const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+ static int getArch() { return REGISTERS_MIPS_NEWABI; }
uint64_t getSP() const { return _registers.__r[29]; }
void setSP(uint64_t value) { _registers.__r[29] = value; }
@@ -2275,28 +3071,31 @@ public:
void setIP(uint64_t value) { _registers.__pc = value; }
private:
- struct mips_n64_thread_state_t {
+ struct mips_newabi_thread_state_t {
uint64_t __r[32];
uint64_t __pc;
uint64_t __hi;
uint64_t __lo;
};
- mips_n64_thread_state_t _registers;
+ mips_newabi_thread_state_t _registers;
+#ifdef __mips_hard_float
+ double _floats[32];
+#endif
};
-inline Registers_mips_n64::Registers_mips_n64(const void *registers) {
- static_assert((check_fit<Registers_mips_n64, unw_context_t>::does_fit),
- "mips_n64 registers do not fit into unw_context_t");
+inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
+ static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
+ "mips_newabi registers do not fit into unw_context_t");
memcpy(&_registers, static_cast<const uint8_t *>(registers),
sizeof(_registers));
}
-inline Registers_mips_n64::Registers_mips_n64() {
+inline Registers_mips_newabi::Registers_mips_newabi() {
memset(&_registers, 0, sizeof(_registers));
}
-inline bool Registers_mips_n64::validRegister(int regNum) const {
+inline bool Registers_mips_newabi::validRegister(int regNum) const {
if (regNum == UNW_REG_IP)
return true;
if (regNum == UNW_REG_SP)
@@ -2305,15 +3104,17 @@ inline bool Registers_mips_n64::validRegister(int regNum) const {
return false;
if (regNum <= UNW_MIPS_R31)
return true;
+#if __mips_isa_rev != 6
if (regNum == UNW_MIPS_HI)
return true;
if (regNum == UNW_MIPS_LO)
return true;
+#endif
// FIXME: Hard float, DSP accumulator registers, MSA registers
return false;
}
-inline uint64_t Registers_mips_n64::getRegister(int regNum) const {
+inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
return _registers.__r[regNum - UNW_MIPS_R0];
@@ -2327,10 +3128,10 @@ inline uint64_t Registers_mips_n64::getRegister(int regNum) const {
case UNW_MIPS_LO:
return _registers.__lo;
}
- _LIBUNWIND_ABORT("unsupported mips_n64 register");
+ _LIBUNWIND_ABORT("unsupported mips_newabi register");
}
-inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
+inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
_registers.__r[regNum - UNW_MIPS_R0] = value;
return;
@@ -2350,35 +3151,49 @@ inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
_registers.__lo = value;
return;
}
- _LIBUNWIND_ABORT("unsupported mips_n64 register");
+ _LIBUNWIND_ABORT("unsupported mips_newabi register");
}
-inline bool Registers_mips_n64::validFloatRegister(int /* regNum */) const {
+inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
return false;
}
-inline double Registers_mips_n64::getFloatRegister(int /* regNum */) const {
- _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_MIPS_F0];
+#else
+ _LIBUNWIND_ABORT("mips_newabi float support not implemented");
+#endif
}
-inline void Registers_mips_n64::setFloatRegister(int /* regNum */,
- double /* value */) {
- _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+inline void Registers_mips_newabi::setFloatRegister(int regNum,
+ double value) {
+#ifdef __mips_hard_float
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_MIPS_F0] = value;
+#else
+ _LIBUNWIND_ABORT("mips_newabi float support not implemented");
+#endif
}
-inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const {
+inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
return false;
}
-inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const {
- _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
+ _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
}
-inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) {
- _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
+ _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
}
-inline const char *Registers_mips_n64::getRegisterName(int regNum) {
+inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
switch (regNum) {
case UNW_MIPS_R0:
return "$0";
@@ -2444,6 +3259,70 @@ inline const char *Registers_mips_n64::getRegisterName(int regNum) {
return "$30";
case UNW_MIPS_R31:
return "$31";
+ case UNW_MIPS_F0:
+ return "$f0";
+ case UNW_MIPS_F1:
+ return "$f1";
+ case UNW_MIPS_F2:
+ return "$f2";
+ case UNW_MIPS_F3:
+ return "$f3";
+ case UNW_MIPS_F4:
+ return "$f4";
+ case UNW_MIPS_F5:
+ return "$f5";
+ case UNW_MIPS_F6:
+ return "$f6";
+ case UNW_MIPS_F7:
+ return "$f7";
+ case UNW_MIPS_F8:
+ return "$f8";
+ case UNW_MIPS_F9:
+ return "$f9";
+ case UNW_MIPS_F10:
+ return "$f10";
+ case UNW_MIPS_F11:
+ return "$f11";
+ case UNW_MIPS_F12:
+ return "$f12";
+ case UNW_MIPS_F13:
+ return "$f13";
+ case UNW_MIPS_F14:
+ return "$f14";
+ case UNW_MIPS_F15:
+ return "$f15";
+ case UNW_MIPS_F16:
+ return "$f16";
+ case UNW_MIPS_F17:
+ return "$f17";
+ case UNW_MIPS_F18:
+ return "$f18";
+ case UNW_MIPS_F19:
+ return "$f19";
+ case UNW_MIPS_F20:
+ return "$f20";
+ case UNW_MIPS_F21:
+ return "$f21";
+ case UNW_MIPS_F22:
+ return "$f22";
+ case UNW_MIPS_F23:
+ return "$f23";
+ case UNW_MIPS_F24:
+ return "$f24";
+ case UNW_MIPS_F25:
+ return "$f25";
+ case UNW_MIPS_F26:
+ return "$f26";
+ case UNW_MIPS_F27:
+ return "$f27";
+ case UNW_MIPS_F28:
+ return "$f28";
+ case UNW_MIPS_F29:
+ return "$f29";
+ case UNW_MIPS_F30:
+ return "$f30";
+ case UNW_MIPS_F31:
+ return "$f31";
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
@@ -2452,7 +3331,192 @@ inline const char *Registers_mips_n64::getRegisterName(int regNum) {
return "unknown register";
}
}
-#endif // _LIBUNWIND_TARGET_MIPS_N64
+#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
+/// process.
+class _LIBUNWIND_HIDDEN Registers_sparc {
+public:
+ Registers_sparc();
+ Registers_sparc(const void *registers);
+
+ bool validRegister(int num) const;
+ uint32_t getRegister(int num) const;
+ void setRegister(int num, uint32_t value);
+ bool validFloatRegister(int num) const;
+ double getFloatRegister(int num) const;
+ void setFloatRegister(int num, double value);
+ bool validVectorRegister(int num) const;
+ v128 getVectorRegister(int num) const;
+ void setVectorRegister(int num, v128 value);
+ static const char *getRegisterName(int num);
+ void jumpto();
+ static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
+ static int getArch() { return REGISTERS_SPARC; }
+
+ uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
+ void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
+ uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
+ void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
+
+private:
+ struct sparc_thread_state_t {
+ unsigned int __regs[32];
+ };
+
+ sparc_thread_state_t _registers;
+};
+
+inline Registers_sparc::Registers_sparc(const void *registers) {
+ static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
+ "sparc registers do not fit into unw_context_t");
+ memcpy(&_registers, static_cast<const uint8_t *>(registers),
+ sizeof(_registers));
+}
+
+inline Registers_sparc::Registers_sparc() {
+ memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_sparc::validRegister(int regNum) const {
+ if (regNum == UNW_REG_IP)
+ return true;
+ if (regNum == UNW_REG_SP)
+ return true;
+ if (regNum < 0)
+ return false;
+ if (regNum <= UNW_SPARC_I7)
+ return true;
+ return false;
+}
+
+inline uint32_t Registers_sparc::getRegister(int regNum) const {
+ if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
+ return _registers.__regs[regNum];
+ }
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ return _registers.__regs[UNW_SPARC_O7];
+ case UNW_REG_SP:
+ return _registers.__regs[UNW_SPARC_O6];
+ }
+ _LIBUNWIND_ABORT("unsupported sparc register");
+}
+
+inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
+ if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
+ _registers.__regs[regNum] = value;
+ return;
+ }
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ _registers.__regs[UNW_SPARC_O7] = value;
+ return;
+ case UNW_REG_SP:
+ _registers.__regs[UNW_SPARC_O6] = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported sparc register");
+}
+
+inline bool Registers_sparc::validFloatRegister(int) const { return false; }
+
+inline double Registers_sparc::getFloatRegister(int) const {
+ _LIBUNWIND_ABORT("no Sparc float registers");
+}
+
+inline void Registers_sparc::setFloatRegister(int, double) {
+ _LIBUNWIND_ABORT("no Sparc float registers");
+}
+
+inline bool Registers_sparc::validVectorRegister(int) const { return false; }
+
+inline v128 Registers_sparc::getVectorRegister(int) const {
+ _LIBUNWIND_ABORT("no Sparc vector registers");
+}
+
+inline void Registers_sparc::setVectorRegister(int, v128) {
+ _LIBUNWIND_ABORT("no Sparc vector registers");
+}
+
+inline const char *Registers_sparc::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return "pc";
+ case UNW_SPARC_G0:
+ return "g0";
+ case UNW_SPARC_G1:
+ return "g1";
+ case UNW_SPARC_G2:
+ return "g2";
+ case UNW_SPARC_G3:
+ return "g3";
+ case UNW_SPARC_G4:
+ return "g4";
+ case UNW_SPARC_G5:
+ return "g5";
+ case UNW_SPARC_G6:
+ return "g6";
+ case UNW_SPARC_G7:
+ return "g7";
+ case UNW_SPARC_O0:
+ return "o0";
+ case UNW_SPARC_O1:
+ return "o1";
+ case UNW_SPARC_O2:
+ return "o2";
+ case UNW_SPARC_O3:
+ return "o3";
+ case UNW_SPARC_O4:
+ return "o4";
+ case UNW_SPARC_O5:
+ return "o5";
+ case UNW_REG_SP:
+ case UNW_SPARC_O6:
+ return "sp";
+ case UNW_SPARC_O7:
+ return "o7";
+ case UNW_SPARC_L0:
+ return "l0";
+ case UNW_SPARC_L1:
+ return "l1";
+ case UNW_SPARC_L2:
+ return "l2";
+ case UNW_SPARC_L3:
+ return "l3";
+ case UNW_SPARC_L4:
+ return "l4";
+ case UNW_SPARC_L5:
+ return "l5";
+ case UNW_SPARC_L6:
+ return "l6";
+ case UNW_SPARC_L7:
+ return "l7";
+ case UNW_SPARC_I0:
+ return "i0";
+ case UNW_SPARC_I1:
+ return "i1";
+ case UNW_SPARC_I2:
+ return "i2";
+ case UNW_SPARC_I3:
+ return "i3";
+ case UNW_SPARC_I4:
+ return "i4";
+ case UNW_SPARC_I5:
+ return "i5";
+ case UNW_SPARC_I6:
+ return "fp";
+ case UNW_SPARC_I7:
+ return "i7";
+ default:
+ return "unknown register";
+ }
+}
+#endif // _LIBUNWIND_TARGET_SPARC
+
} // namespace libunwind
#endif // __REGISTERS_HPP__
diff --git a/src/Unwind-EHABI.cpp b/src/Unwind-EHABI.cpp
index f37732c..c64ca12 100644
--- a/src/Unwind-EHABI.cpp
+++ b/src/Unwind-EHABI.cpp
@@ -1,9 +1,8 @@
//===--------------------------- Unwind-EHABI.cpp -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements ARM zero-cost C++ exceptions
@@ -21,8 +20,6 @@
#include <stdlib.h>
#include <string.h>
-#include <type_traits>
-
#include "config.h"
#include "libunwind.h"
#include "libunwind_ext.h"
diff --git a/src/Unwind-EHABI.h b/src/Unwind-EHABI.h
index fe164ff..6897082 100644
--- a/src/Unwind-EHABI.h
+++ b/src/Unwind-EHABI.h
@@ -1,9 +1,8 @@
//===------------------------- Unwind-EHABI.hpp ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
//===----------------------------------------------------------------------===//
diff --git a/src/Unwind-seh.cpp b/src/Unwind-seh.cpp
new file mode 100644
index 0000000..8b4b7d5
--- /dev/null
+++ b/src/Unwind-seh.cpp
@@ -0,0 +1,500 @@
+//===--------------------------- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements SEH-based Itanium C++ exceptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "config.h"
+
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+
+#include <unwind.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <windef.h>
+#include <excpt.h>
+#include <winnt.h>
+#include <ntstatus.h>
+
+#include "libunwind_ext.h"
+#include "UnwindCursor.hpp"
+
+using namespace libunwind;
+
+#define STATUS_USER_DEFINED (1u << 29)
+
+#define STATUS_GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C')
+
+#define MAKE_CUSTOM_STATUS(s, c) \
+ ((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c)))
+#define MAKE_GCC_EXCEPTION(c) \
+ MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24))
+
+/// SEH exception raised by libunwind when the program calls
+/// \c _Unwind_RaiseException.
+#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x20474343
+/// SEH exception raised by libunwind to initiate phase 2 of exception
+/// handling.
+#define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343
+
+/// Class of foreign exceptions based on unrecognized SEH exceptions.
+static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0
+
+/// Exception cleanup routine used by \c _GCC_specific_handler to
+/// free foreign exceptions.
+static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) {
+ (void)urc;
+ if (exc->exception_class != kSEHExceptionClass)
+ _LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception");
+ free(exc);
+}
+
+static int _unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx);
+static DISPATCHER_CONTEXT *_unw_seh_get_disp_ctx(unw_cursor_t *cursor);
+static void _unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp);
+
+/// Common implementation of SEH-style handler functions used by Itanium-
+/// style frames. Depending on how and why it was called, it may do one of:
+/// a) Delegate to the given Itanium-style personality function; or
+/// b) Initiate a collided unwind to halt unwinding.
+_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION
+_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
+ DISPATCHER_CONTEXT *disp, __personality_routine pers) {
+ unw_cursor_t cursor;
+ _Unwind_Exception *exc;
+ _Unwind_Action action;
+ struct _Unwind_Context *ctx = nullptr;
+ _Unwind_Reason_Code urc;
+ uintptr_t retval, target;
+ bool ours = false;
+
+ _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010lx(%lx), %p)",
+ ms_exc->ExceptionCode, ms_exc->ExceptionFlags,
+ (void *)frame);
+ if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) {
+ if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) {
+ // Set up the upper return value (the lower one and the target PC
+ // were set in the call to RtlUnwindEx()) for the landing pad.
+#ifdef __x86_64__
+ disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];
+#elif defined(__arm__)
+ disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3];
+#elif defined(__aarch64__)
+ disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3];
+#endif
+ }
+ // This is the collided unwind to the landing pad. Nothing to do.
+ return ExceptionContinueSearch;
+ }
+
+ if (ms_exc->ExceptionCode == STATUS_GCC_THROW) {
+ // This is (probably) a libunwind-controlled exception/unwind. Recover the
+ // parameters which we set below, and pass them to the personality function.
+ ours = true;
+ exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0];
+ if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) {
+ ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1];
+ action = (_Unwind_Action)ms_exc->ExceptionInformation[2];
+ }
+ } else {
+ // Foreign exception.
+ exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception));
+ exc->exception_class = kSEHExceptionClass;
+ exc->exception_cleanup = seh_exc_cleanup;
+ memset(exc->private_, 0, sizeof(exc->private_));
+ }
+ 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);
+ ctx = (struct _Unwind_Context *)&cursor;
+
+ if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
+ if (ours && ms_exc->NumberParameters > 1)
+ action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND);
+ else
+ action = _UA_SEARCH_PHASE;
+ } else {
+ if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame)
+ action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
+ else
+ action = _UA_CLEANUP_PHASE;
+ }
+ }
+
+ _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality "
+ "function %p(1, %d, %llx, %p, %p)",
+ (void *)pers, action, exc->exception_class,
+ (void *)exc, (void *)ctx);
+ urc = pers(1, action, exc->exception_class, exc, ctx);
+ _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc);
+ switch (urc) {
+ case _URC_CONTINUE_UNWIND:
+ // If we're in phase 2, and the personality routine said to continue
+ // at the target frame, we're in real trouble.
+ if (action & _UA_HANDLER_FRAME)
+ _LIBUNWIND_ABORT("Personality continued unwind at the target frame!");
+ return ExceptionContinueSearch;
+ case _URC_HANDLER_FOUND:
+ // 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 */;
+ // This should never happen in phase 2.
+ if (IS_UNWINDING(ms_exc->ExceptionFlags))
+ _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
+ exc->private_[1] = (ULONG_PTR)frame;
+ if (ours) {
+ ms_exc->NumberParameters = 4;
+ ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame;
+ }
+ // FIXME: Indicate target frame in foreign case!
+ // phase 2: the clean up phase
+ RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable);
+ _LIBUNWIND_ABORT("RtlUnwindEx() failed");
+ case _URC_INSTALL_CONTEXT: {
+ // If we were called by __libunwind_seh_personality(), indicate that
+ // 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 */;
+ // This should never happen in phase 1.
+ if (!IS_UNWINDING(ms_exc->ExceptionFlags))
+ _LIBUNWIND_ABORT("Personality installed context during phase 1!");
+#ifdef __x86_64__
+ exc->private_[2] = disp->TargetIp;
+ unw_get_reg(&cursor, UNW_X86_64_RAX, &retval);
+ unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]);
+#elif defined(__arm__)
+ exc->private_[2] = disp->TargetPc;
+ unw_get_reg(&cursor, UNW_ARM_R0, &retval);
+ 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]);
+#endif
+ unw_get_reg(&cursor, UNW_REG_IP, &target);
+ ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
+#ifdef __x86_64__
+ ms_exc->ExceptionInformation[2] = disp->TargetIp;
+#elif defined(__arm__) || defined(__aarch64__)
+ ms_exc->ExceptionInformation[2] = disp->TargetPc;
+#endif
+ ms_exc->ExceptionInformation[3] = exc->private_[3];
+ // Give NTRTL some scratch space to keep track of the collided unwind.
+ // Don't use the one that was passed in; we don't want to overwrite the
+ // context in the DISPATCHER_CONTEXT.
+ CONTEXT new_ctx;
+ RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable);
+ _LIBUNWIND_ABORT("RtlUnwindEx() failed");
+ }
+ // Anything else indicates a serious problem.
+ default: return ExceptionContinueExecution;
+ }
+}
+
+/// Personality function returned by \c unw_get_proc_info() in SEH contexts.
+/// This is a wrapper that calls the real SEH handler function, which in
+/// turn (at least, for Itanium-style frames) calls the real Itanium
+/// personality function (see \c _GCC_specific_handler()).
+extern "C" _Unwind_Reason_Code
+__libunwind_seh_personality(int version, _Unwind_Action state,
+ uint64_t klass, _Unwind_Exception *exc,
+ struct _Unwind_Context *context) {
+ (void)version;
+ (void)klass;
+ EXCEPTION_RECORD ms_exc;
+ bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE;
+ ms_exc.ExceptionCode = STATUS_GCC_THROW;
+ ms_exc.ExceptionFlags = 0;
+ ms_exc.NumberParameters = 3;
+ ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc;
+ ms_exc.ExceptionInformation[1] = (ULONG_PTR)context;
+ ms_exc.ExceptionInformation[2] = state;
+ DISPATCHER_CONTEXT *disp_ctx = _unw_seh_get_disp_ctx((unw_cursor_t *)context);
+ EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
+ (PVOID)disp_ctx->EstablisherFrame,
+ disp_ctx->ContextRecord,
+ disp_ctx);
+ switch (ms_act) {
+ case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
+ case 4 /*ExceptionExecuteHandler*/:
+ return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
+ default:
+ return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR;
+ }
+}
+
+static _Unwind_Reason_Code
+unwind_phase2_forced(unw_context_t *uc,
+ _Unwind_Exception *exception_object,
+ _Unwind_Stop_Fn stop, void *stop_parameter) {
+ unw_cursor_t cursor2;
+ unw_init_local(&cursor2, uc);
+
+ // Walk each frame until we reach where search phase said to stop
+ while (unw_step(&cursor2) > 0) {
+
+ // Update info about this frame.
+ unw_proc_info_t frameInfo;
+ if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
+ "failed => _URC_END_OF_STACK",
+ (void *)exception_object);
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+
+ // 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(&cursor2, 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%" PRIx64
+ ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
+ (void *)exception_object, frameInfo.start_ip, functionName,
+ frameInfo.lsda, frameInfo.handler);
+ }
+
+ // 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,
+ (struct _Unwind_Context *)(&cursor2), 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) {
+ __personality_routine p =
+ (__personality_routine)(intptr_t)(frameInfo.handler);
+ _LIBUNWIND_TRACE_UNWINDING(
+ "unwind_phase2_forced(ex_ojb=%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 *)(&cursor2));
+ 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(&cursor2);
+ 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 *)(&cursor2), 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 \c __cxa_throw(). Only returns if there is a fatal error.
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_RaiseException(_Unwind_Exception *exception_object) {
+ _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
+ (void *)exception_object);
+
+ // Mark that this is a non-forced unwind, so _Unwind_Resume()
+ // can do the right thing.
+ memset(exception_object->private_, 0, sizeof(exception_object->private_));
+
+ // phase 1: the search phase
+ // We'll let the system do that for us.
+ RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object);
+
+ // If we get here, either something went horribly wrong or we reached the
+ // top of the stack. Either way, let libc++abi call std::terminate().
+ return _URC_END_OF_STACK;
+}
+
+/// When \c _Unwind_RaiseException() is in phase2, it hands control
+/// to the personality function at each frame. The personality
+/// 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
+/// by the C++ runtime \c __cxa_* routines.
+///
+/// Note: re-throwing an exception (as opposed to continuing the unwind)
+/// is implemented by having the code call \c __cxa_rethrow() which
+/// in turn calls \c _Unwind_Resume_or_Rethrow().
+_LIBUNWIND_EXPORT void
+_Unwind_Resume(_Unwind_Exception *exception_object) {
+ _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
+
+ if (exception_object->private_[0] != 0) {
+ unw_context_t uc;
+
+ unw_getcontext(&uc);
+ unwind_phase2_forced(&uc, exception_object,
+ (_Unwind_Stop_Fn) exception_object->private_[0],
+ (void *)exception_object->private_[4]);
+ } else {
+ // Recover the parameters for the unwind from the exception object
+ // so we can start unwinding again.
+ EXCEPTION_RECORD ms_exc;
+ CONTEXT ms_ctx;
+ UNWIND_HISTORY_TABLE hist;
+
+ memset(&ms_exc, 0, sizeof(ms_exc));
+ memset(&hist, 0, sizeof(hist));
+ ms_exc.ExceptionCode = STATUS_GCC_THROW;
+ ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ ms_exc.NumberParameters = 4;
+ ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object;
+ ms_exc.ExceptionInformation[1] = exception_object->private_[1];
+ ms_exc.ExceptionInformation[2] = exception_object->private_[2];
+ ms_exc.ExceptionInformation[3] = exception_object->private_[3];
+ RtlUnwindEx((PVOID)exception_object->private_[1],
+ (PVOID)exception_object->private_[2], &ms_exc,
+ exception_object, &ms_ctx, &hist);
+ }
+
+ // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
+ _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
+}
+
+/// Not used by C++.
+/// Unwinds stack, calling "stop" function at each frame.
+/// Could be used to implement \c 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_getcontext(&uc);
+
+ // Mark that this is a forced unwind, so _Unwind_Resume() can do
+ // the right thing.
+ exception_object->private_[0] = (uintptr_t) stop;
+ exception_object->private_[4] = (uintptr_t) stop_parameter;
+
+ // do it
+ return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
+}
+
+/// Called by personality handler during phase 2 to get LSDA for current frame.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
+ uintptr_t result = (uintptr_t)_unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData;
+ _LIBUNWIND_TRACE_API(
+ "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
+ (void *)context, result);
+ return result;
+}
+
+/// Called by personality handler during phase 2 to find the start of the
+/// function.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetRegionStart(struct _Unwind_Context *context) {
+ DISPATCHER_CONTEXT *disp = _unw_seh_get_disp_ctx((unw_cursor_t *)context);
+ uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase;
+ _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
+ (void *)context, result);
+ return result;
+}
+
+static int
+_unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
+#ifdef _LIBUNWIND_TARGET_X86_64
+ new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor))
+ UnwindCursor<LocalAddressSpace, Registers_x86_64>(
+ context, LocalAddressSpace::sThisAddressSpace);
+ auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+ co->setInfoBasedOnIPRegister();
+ return UNW_ESUCCESS;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor))
+ UnwindCursor<LocalAddressSpace, Registers_arm>(
+ context, LocalAddressSpace::sThisAddressSpace);
+ auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+ co->setInfoBasedOnIPRegister();
+ return UNW_ESUCCESS;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ new (reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor))
+ UnwindCursor<LocalAddressSpace, Registers_arm64>(
+ context, LocalAddressSpace::sThisAddressSpace);
+ auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+ co->setInfoBasedOnIPRegister();
+ return UNW_ESUCCESS;
+#else
+ return UNW_EINVAL;
+#endif
+}
+
+static DISPATCHER_CONTEXT *
+_unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
+#ifdef _LIBUNWIND_TARGET_X86_64
+ return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->getDispatcherContext();
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->getDispatcherContext();
+#else
+ return nullptr;
+#endif
+}
+
+static void
+_unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) {
+#ifdef _LIBUNWIND_TARGET_X86_64
+ reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->setDispatcherContext(disp);
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->setDispatcherContext(disp);
+#endif
+}
+
+#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
diff --git a/src/Unwind-sjlj.c b/src/Unwind-sjlj.c
index 90cac3f..2204161 100644
--- a/src/Unwind-sjlj.c
+++ b/src/Unwind-sjlj.c
@@ -1,9 +1,8 @@
//===--------------------------- Unwind-sjlj.c ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements setjump-longjump based C++ exceptions
@@ -12,6 +11,7 @@
#include <unwind.h>
+#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -52,7 +52,7 @@ struct _Unwind_FunctionContext {
#else
# if __STDC_VERSION__ >= 201112L
# define _LIBUNWIND_THREAD_LOCAL _Thread_local
-# elif defined(_WIN32)
+# elif defined(_MSC_VER)
# define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
# elif defined(__GNUC__) || defined(__clang__)
# define _LIBUNWIND_THREAD_LOCAL __thread
@@ -108,7 +108,8 @@ _Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
static _Unwind_Reason_Code
unwind_phase1(struct _Unwind_Exception *exception_object) {
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p",
+ (void *)c);
// walk each frame looking for a place to stop
for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
@@ -117,17 +118,18 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
"bottom => _URC_END_OF_STACK",
- exception_object);
+ (void *)exception_object);
return _URC_END_OF_STACK;
}
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", (void *)c);
// if there is a personality routine, ask it if it will want to stop at this
// frame
if (c->personality != NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
- "personality function %p",
- exception_object, c->personality);
+ "personality function %p",
+ (void *)exception_object,
+ (void *)c->personality);
_Unwind_Reason_Code personalityResult = (*c->personality)(
1, _UA_SEARCH_PHASE, exception_object->exception_class,
exception_object, (struct _Unwind_Context *)c);
@@ -138,12 +140,14 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
handlerNotFound = false;
exception_object->private_2 = (uintptr_t) c;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
- "_URC_HANDLER_FOUND", exception_object);
+ "_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", exception_object);
+ "_URC_CONTINUE_UNWIND",
+ (void *)exception_object);
// continue unwinding
break;
@@ -151,7 +155,7 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
- exception_object);
+ (void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
}
@@ -162,19 +166,20 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
static _Unwind_Reason_Code
unwind_phase2(struct _Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
+ (void *)exception_object);
// walk each frame until we reach where search phase said to stop
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
while (true) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p",
- exception_object, c);
+ (void *)exception_object, (void *)c);
// check for no more frames
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK",
- exception_object);
+ "bottom => _URC_END_OF_STACK",
+ (void *)exception_object);
return _URC_END_OF_STACK;
}
@@ -194,7 +199,7 @@ unwind_phase2(struct _Unwind_Exception *exception_object) {
// continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
- exception_object);
+ (void *)exception_object);
if ((uintptr_t) c == exception_object->private_2) {
// phase 1 said we would stop at this frame, but we did not...
_LIBUNWIND_ABORT("during phase1 personality function said it would "
@@ -203,9 +208,9 @@ unwind_phase2(struct _Unwind_Exception *exception_object) {
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
- "_URC_INSTALL_CONTEXT, will resume at "
- "landing pad %p",
- exception_object, c->jbuf[1]);
+ "_URC_INSTALL_CONTEXT, will resume at "
+ "landing pad %p",
+ (void *)exception_object, c->jbuf[1]);
// personality routine says to transfer control to landing pad
// we may get control back if landing pad calls _Unwind_Resume()
__Unwind_SjLj_SetTopOfFunctionStack(c);
@@ -239,7 +244,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
"bottom => _URC_END_OF_STACK",
- exception_object);
+ (void *)exception_object);
return _URC_END_OF_STACK;
}
@@ -251,11 +256,11 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
(struct _Unwind_Context *)c, stop_parameter);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"stop function returned %d",
- exception_object, stopResult);
+ (void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"stopped by stop function",
- exception_object);
+ (void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -264,7 +269,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
__personality_routine p = (__personality_routine) c->personality;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"calling personality function %p",
- exception_object, p);
+ (void *)exception_object, (void *)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)c);
@@ -272,13 +277,13 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned _URC_CONTINUE_UNWIND",
- exception_object);
+ (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",
- exception_object);
+ (void *)exception_object);
// we may get control back if landing pad calls _Unwind_Resume()
__Unwind_SjLj_SetTopOfFunctionStack(c);
__builtin_longjmp(c->jbuf, 1);
@@ -288,7 +293,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
- exception_object, personalityResult);
+ (void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
}
@@ -298,8 +303,8 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
// 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",
- exception_object);
+ "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,
@@ -314,7 +319,8 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
/// Called by __cxa_throw. Only returns if there is a fatal error
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object);
+ _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)",
+ (void *)exception_object);
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
// thing
@@ -344,7 +350,8 @@ _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object);
+ _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)",
+ (void *)exception_object);
if (exception_object->private_1 != 0)
unwind_phase2_forced(exception_object,
@@ -362,8 +369,8 @@ _Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
- "private_1=%ld",
- exception_object, exception_object->private_1);
+ "private_1=%" PRIuPTR,
+ (void *)exception_object, exception_object->private_1);
// 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.
@@ -386,7 +393,8 @@ _LIBUNWIND_EXPORT uintptr_t
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
_LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
- "=> 0x%0lX", context, ufc->lsda);
+ "=> 0x%" PRIuPTR,
+ (void *)context, ufc->lsda);
return ufc->lsda;
}
@@ -394,8 +402,8 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
/// Called by personality handler during phase 2 to get register values.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
int index) {
- _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)",
- context, index);
+ _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", (void *)context,
+ index);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
return ufc->resumeParameters[index];
}
@@ -404,8 +412,9 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)"
- , context, index, new_value);
+ _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR
+ ")",
+ (void *)context, index, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeParameters[index] = new_value;
}
@@ -414,8 +423,8 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
- _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context,
- ufc->resumeLocation + 1);
+ _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,
+ (void *)context, ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@@ -427,8 +436,9 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
*ipBefore = 0;
- _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX",
- context, ipBefore, ufc->resumeLocation + 1);
+ _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
+ (void *)context, (void *)ipBefore,
+ ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@@ -436,8 +446,8 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter instruction pointer.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t new_value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)",
- context, new_value);
+ _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",
+ (void *)context, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeLocation = new_value - 1;
}
@@ -449,7 +459,7 @@ _LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
// Not supported or needed for sjlj based unwinding
(void)context;
- _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", (void *)context);
return 0;
}
@@ -459,7 +469,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
- exception_object);
+ (void *)exception_object);
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
exception_object);
@@ -473,7 +483,7 @@ _LIBUNWIND_EXPORT uintptr_t
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
// Not supported or needed for sjlj based unwinding
(void)context;
- _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
}
@@ -484,14 +494,14 @@ _LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
// Not supported or needed for sjlj based unwinding
(void)context;
- _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
/// Called by personality handler to get "Call Frame Area" for current frame.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
- _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", (void *)context);
if (context != NULL) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
// Setjmp/longjmp based exceptions don't have a true CFA.
diff --git a/src/UnwindCursor.hpp b/src/UnwindCursor.hpp
index f09bd23..836de38 100644
--- a/src/UnwindCursor.hpp
+++ b/src/UnwindCursor.hpp
@@ -1,9 +1,8 @@
//===------------------------- UnwindCursor.hpp ---------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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++ interface to lower levels of libunwind
@@ -12,16 +11,56 @@
#ifndef __UNWINDCURSOR_HPP__
#define __UNWINDCURSOR_HPP__
-#include <algorithm>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unwind.h>
+#ifdef _WIN32
+ #include <windows.h>
+ #include <ntverp.h>
+#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
+// earlier) SDKs.
+// MinGW-w64 has always provided this struct.
+ #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
+ !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
+struct _DISPATCHER_CONTEXT {
+ ULONG64 ControlPc;
+ ULONG64 ImageBase;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG64 EstablisherFrame;
+ ULONG64 TargetIp;
+ PCONTEXT ContextRecord;
+ PEXCEPTION_ROUTINE LanguageHandler;
+ PVOID HandlerData;
+ PUNWIND_HISTORY_TABLE HistoryTable;
+ ULONG ScopeIndex;
+ ULONG Fill0;
+};
+ #endif
+
+struct UNWIND_INFO {
+ uint8_t Version : 3;
+ uint8_t Flags : 5;
+ uint8_t SizeOfProlog;
+ uint8_t CountOfCodes;
+ uint8_t FrameRegister : 4;
+ uint8_t FrameOffset : 4;
+ uint16_t UnwindCodes[2];
+};
+
+extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
+ int, _Unwind_Action, uint64_t, _Unwind_Exception *,
+ struct _Unwind_Context *);
+
+#endif
+
#include "config.h"
#include "AddressSpace.hpp"
@@ -65,7 +104,6 @@ private:
static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
static bool _registeredForDyldUnloads;
#endif
- // Can't use std::vector<> here because this code is below libc++.
static entry *_buffer;
static entry *_bufferUsed;
static entry *_bufferEnd;
@@ -412,6 +450,428 @@ public:
#endif
};
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
+
+/// \c UnwindCursor contains all state (including all register values) during
+/// an unwind. This is normally stack-allocated inside a unw_cursor_t.
+template <typename A, typename R>
+class UnwindCursor : public AbstractUnwindCursor {
+ typedef typename A::pint_t pint_t;
+public:
+ UnwindCursor(unw_context_t *context, A &as);
+ UnwindCursor(CONTEXT *context, A &as);
+ UnwindCursor(A &as, void *threadArg);
+ virtual ~UnwindCursor() {}
+ virtual bool validReg(int);
+ virtual unw_word_t getReg(int);
+ virtual void setReg(int, unw_word_t);
+ virtual bool validFloatReg(int);
+ virtual unw_fpreg_t getFloatReg(int);
+ virtual void setFloatReg(int, unw_fpreg_t);
+ virtual int step();
+ virtual void getInfo(unw_proc_info_t *);
+ virtual void jumpto();
+ virtual bool isSignalFrame();
+ virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
+ virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
+ virtual const char *getRegisterName(int num);
+#ifdef __arm__
+ virtual void saveVFPAsX();
+#endif
+
+ DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
+ void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
+
+ // libunwind does not and should not depend on C++ library which means that we
+ // need our own defition of inline placement new.
+ static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
+
+private:
+
+ pint_t getLastPC() const { return _dispContext.ControlPc; }
+ void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
+ RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
+ _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
+ &_dispContext.ImageBase,
+ _dispContext.HistoryTable);
+ *base = _dispContext.ImageBase;
+ return _dispContext.FunctionEntry;
+ }
+ bool getInfoFromSEH(pint_t pc);
+ int stepWithSEHData() {
+ _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
+ _dispContext.ImageBase,
+ _dispContext.ControlPc,
+ _dispContext.FunctionEntry,
+ _dispContext.ContextRecord,
+ &_dispContext.HandlerData,
+ &_dispContext.EstablisherFrame,
+ NULL);
+ // Update some fields of the unwind info now, since we have them.
+ _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
+ if (_dispContext.LanguageHandler) {
+ _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+ } else
+ _info.handler = 0;
+ return UNW_STEP_SUCCESS;
+ }
+
+ A &_addressSpace;
+ unw_proc_info_t _info;
+ DISPATCHER_CONTEXT _dispContext;
+ CONTEXT _msContext;
+ UNWIND_HISTORY_TABLE _histTable;
+ bool _unwindInfoMissing;
+};
+
+
+template <typename A, typename R>
+UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
+ : _addressSpace(as), _unwindInfoMissing(false) {
+ static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
+ "UnwindCursor<> does not fit in unw_cursor_t");
+ memset(&_info, 0, sizeof(_info));
+ memset(&_histTable, 0, sizeof(_histTable));
+ _dispContext.ContextRecord = &_msContext;
+ _dispContext.HistoryTable = &_histTable;
+ // Initialize MS context from ours.
+ R r(context);
+ _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
+#if defined(_LIBUNWIND_TARGET_X86_64)
+ _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
+ _msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
+ _msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
+ _msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
+ _msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
+ _msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
+ _msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
+ _msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
+ _msContext.R8 = r.getRegister(UNW_X86_64_R8);
+ _msContext.R9 = r.getRegister(UNW_X86_64_R9);
+ _msContext.R10 = r.getRegister(UNW_X86_64_R10);
+ _msContext.R11 = r.getRegister(UNW_X86_64_R11);
+ _msContext.R12 = r.getRegister(UNW_X86_64_R12);
+ _msContext.R13 = r.getRegister(UNW_X86_64_R13);
+ _msContext.R14 = r.getRegister(UNW_X86_64_R14);
+ _msContext.R15 = r.getRegister(UNW_X86_64_R15);
+ _msContext.Rip = r.getRegister(UNW_REG_IP);
+ union {
+ v128 v;
+ M128A m;
+ } t;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM0);
+ _msContext.Xmm0 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM1);
+ _msContext.Xmm1 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM2);
+ _msContext.Xmm2 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM3);
+ _msContext.Xmm3 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM4);
+ _msContext.Xmm4 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM5);
+ _msContext.Xmm5 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM6);
+ _msContext.Xmm6 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM7);
+ _msContext.Xmm7 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM8);
+ _msContext.Xmm8 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM9);
+ _msContext.Xmm9 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM10);
+ _msContext.Xmm10 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM11);
+ _msContext.Xmm11 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM12);
+ _msContext.Xmm12 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM13);
+ _msContext.Xmm13 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM14);
+ _msContext.Xmm14 = t.m;
+ t.v = r.getVectorRegister(UNW_X86_64_XMM15);
+ _msContext.Xmm15 = t.m;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ _msContext.R0 = r.getRegister(UNW_ARM_R0);
+ _msContext.R1 = r.getRegister(UNW_ARM_R1);
+ _msContext.R2 = r.getRegister(UNW_ARM_R2);
+ _msContext.R3 = r.getRegister(UNW_ARM_R3);
+ _msContext.R4 = r.getRegister(UNW_ARM_R4);
+ _msContext.R5 = r.getRegister(UNW_ARM_R5);
+ _msContext.R6 = r.getRegister(UNW_ARM_R6);
+ _msContext.R7 = r.getRegister(UNW_ARM_R7);
+ _msContext.R8 = r.getRegister(UNW_ARM_R8);
+ _msContext.R9 = r.getRegister(UNW_ARM_R9);
+ _msContext.R10 = r.getRegister(UNW_ARM_R10);
+ _msContext.R11 = r.getRegister(UNW_ARM_R11);
+ _msContext.R12 = r.getRegister(UNW_ARM_R12);
+ _msContext.Sp = r.getRegister(UNW_ARM_SP);
+ _msContext.Lr = r.getRegister(UNW_ARM_LR);
+ _msContext.Pc = r.getRegister(UNW_ARM_IP);
+ for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
+ union {
+ uint64_t w;
+ double d;
+ } d;
+ d.d = r.getFloatRegister(i);
+ _msContext.D[i - UNW_ARM_D0] = d.w;
+ }
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i)
+ _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i);
+ _msContext.Sp = r.getRegister(UNW_REG_SP);
+ _msContext.Pc = r.getRegister(UNW_REG_IP);
+ for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i)
+ _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i);
+#endif
+}
+
+template <typename A, typename R>
+UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
+ : _addressSpace(as), _unwindInfoMissing(false) {
+ static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
+ "UnwindCursor<> does not fit in unw_cursor_t");
+ memset(&_info, 0, sizeof(_info));
+ memset(&_histTable, 0, sizeof(_histTable));
+ _dispContext.ContextRecord = &_msContext;
+ _dispContext.HistoryTable = &_histTable;
+ _msContext = *context;
+}
+
+
+template <typename A, typename R>
+bool UnwindCursor<A, R>::validReg(int regNum) {
+ if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
+#if defined(_LIBUNWIND_TARGET_X86_64)
+ if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true;
+#endif
+ return false;
+}
+
+template <typename A, typename R>
+unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
+ switch (regNum) {
+#if defined(_LIBUNWIND_TARGET_X86_64)
+ case UNW_REG_IP: return _msContext.Rip;
+ case UNW_X86_64_RAX: return _msContext.Rax;
+ case UNW_X86_64_RDX: return _msContext.Rdx;
+ case UNW_X86_64_RCX: return _msContext.Rcx;
+ case UNW_X86_64_RBX: return _msContext.Rbx;
+ case UNW_REG_SP:
+ case UNW_X86_64_RSP: return _msContext.Rsp;
+ case UNW_X86_64_RBP: return _msContext.Rbp;
+ case UNW_X86_64_RSI: return _msContext.Rsi;
+ case UNW_X86_64_RDI: return _msContext.Rdi;
+ case UNW_X86_64_R8: return _msContext.R8;
+ case UNW_X86_64_R9: return _msContext.R9;
+ case UNW_X86_64_R10: return _msContext.R10;
+ case UNW_X86_64_R11: return _msContext.R11;
+ case UNW_X86_64_R12: return _msContext.R12;
+ case UNW_X86_64_R13: return _msContext.R13;
+ case UNW_X86_64_R14: return _msContext.R14;
+ case UNW_X86_64_R15: return _msContext.R15;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ case UNW_ARM_R0: return _msContext.R0;
+ case UNW_ARM_R1: return _msContext.R1;
+ case UNW_ARM_R2: return _msContext.R2;
+ case UNW_ARM_R3: return _msContext.R3;
+ case UNW_ARM_R4: return _msContext.R4;
+ case UNW_ARM_R5: return _msContext.R5;
+ case UNW_ARM_R6: return _msContext.R6;
+ case UNW_ARM_R7: return _msContext.R7;
+ case UNW_ARM_R8: return _msContext.R8;
+ case UNW_ARM_R9: return _msContext.R9;
+ case UNW_ARM_R10: return _msContext.R10;
+ case UNW_ARM_R11: return _msContext.R11;
+ case UNW_ARM_R12: return _msContext.R12;
+ case UNW_REG_SP:
+ case UNW_ARM_SP: return _msContext.Sp;
+ case UNW_ARM_LR: return _msContext.Lr;
+ case UNW_REG_IP:
+ case UNW_ARM_IP: return _msContext.Pc;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ case UNW_REG_SP: return _msContext.Sp;
+ case UNW_REG_IP: return _msContext.Pc;
+ default: return _msContext.X[regNum - UNW_ARM64_X0];
+#endif
+ }
+ _LIBUNWIND_ABORT("unsupported register");
+}
+
+template <typename A, typename R>
+void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
+ switch (regNum) {
+#if defined(_LIBUNWIND_TARGET_X86_64)
+ case UNW_REG_IP: _msContext.Rip = value; break;
+ case UNW_X86_64_RAX: _msContext.Rax = value; break;
+ case UNW_X86_64_RDX: _msContext.Rdx = value; break;
+ case UNW_X86_64_RCX: _msContext.Rcx = value; break;
+ case UNW_X86_64_RBX: _msContext.Rbx = value; break;
+ case UNW_REG_SP:
+ case UNW_X86_64_RSP: _msContext.Rsp = value; break;
+ case UNW_X86_64_RBP: _msContext.Rbp = value; break;
+ case UNW_X86_64_RSI: _msContext.Rsi = value; break;
+ case UNW_X86_64_RDI: _msContext.Rdi = value; break;
+ case UNW_X86_64_R8: _msContext.R8 = value; break;
+ case UNW_X86_64_R9: _msContext.R9 = value; break;
+ case UNW_X86_64_R10: _msContext.R10 = value; break;
+ case UNW_X86_64_R11: _msContext.R11 = value; break;
+ case UNW_X86_64_R12: _msContext.R12 = value; break;
+ case UNW_X86_64_R13: _msContext.R13 = value; break;
+ case UNW_X86_64_R14: _msContext.R14 = value; break;
+ case UNW_X86_64_R15: _msContext.R15 = value; break;
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ case UNW_ARM_R0: _msContext.R0 = value; break;
+ case UNW_ARM_R1: _msContext.R1 = value; break;
+ case UNW_ARM_R2: _msContext.R2 = value; break;
+ case UNW_ARM_R3: _msContext.R3 = value; break;
+ case UNW_ARM_R4: _msContext.R4 = value; break;
+ case UNW_ARM_R5: _msContext.R5 = value; break;
+ case UNW_ARM_R6: _msContext.R6 = value; break;
+ case UNW_ARM_R7: _msContext.R7 = value; break;
+ case UNW_ARM_R8: _msContext.R8 = value; break;
+ case UNW_ARM_R9: _msContext.R9 = value; break;
+ case UNW_ARM_R10: _msContext.R10 = value; break;
+ case UNW_ARM_R11: _msContext.R11 = value; break;
+ case UNW_ARM_R12: _msContext.R12 = value; break;
+ case UNW_REG_SP:
+ case UNW_ARM_SP: _msContext.Sp = value; break;
+ case UNW_ARM_LR: _msContext.Lr = value; break;
+ case UNW_REG_IP:
+ case UNW_ARM_IP: _msContext.Pc = value; break;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ case UNW_REG_SP: _msContext.Sp = value; break;
+ case UNW_REG_IP: _msContext.Pc = value; break;
+ case UNW_ARM64_X0:
+ case UNW_ARM64_X1:
+ case UNW_ARM64_X2:
+ case UNW_ARM64_X3:
+ case UNW_ARM64_X4:
+ case UNW_ARM64_X5:
+ case UNW_ARM64_X6:
+ case UNW_ARM64_X7:
+ case UNW_ARM64_X8:
+ case UNW_ARM64_X9:
+ case UNW_ARM64_X10:
+ case UNW_ARM64_X11:
+ case UNW_ARM64_X12:
+ case UNW_ARM64_X13:
+ case UNW_ARM64_X14:
+ case UNW_ARM64_X15:
+ case UNW_ARM64_X16:
+ case UNW_ARM64_X17:
+ case UNW_ARM64_X18:
+ case UNW_ARM64_X19:
+ case UNW_ARM64_X20:
+ case UNW_ARM64_X21:
+ case UNW_ARM64_X22:
+ case UNW_ARM64_X23:
+ case UNW_ARM64_X24:
+ case UNW_ARM64_X25:
+ case UNW_ARM64_X26:
+ case UNW_ARM64_X27:
+ case UNW_ARM64_X28:
+ case UNW_ARM64_FP:
+ case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
+#endif
+ default:
+ _LIBUNWIND_ABORT("unsupported register");
+ }
+}
+
+template <typename A, typename R>
+bool UnwindCursor<A, R>::validFloatReg(int regNum) {
+#if defined(_LIBUNWIND_TARGET_ARM)
+ if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
+ if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true;
+#else
+ (void)regNum;
+#endif
+ return false;
+}
+
+template <typename A, typename R>
+unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
+#if defined(_LIBUNWIND_TARGET_ARM)
+ if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
+ union {
+ uint32_t w;
+ float f;
+ } d;
+ d.w = _msContext.S[regNum - UNW_ARM_S0];
+ return d.f;
+ }
+ if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
+ union {
+ uint64_t w;
+ double d;
+ } d;
+ d.w = _msContext.D[regNum - UNW_ARM_D0];
+ return d.d;
+ }
+ _LIBUNWIND_ABORT("unsupported float register");
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ return _msContext.V[regNum - UNW_ARM64_D0].D[0];
+#else
+ (void)regNum;
+ _LIBUNWIND_ABORT("float registers unimplemented");
+#endif
+}
+
+template <typename A, typename R>
+void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
+#if defined(_LIBUNWIND_TARGET_ARM)
+ if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
+ union {
+ uint32_t w;
+ float f;
+ } d;
+ d.f = value;
+ _msContext.S[regNum - UNW_ARM_S0] = d.w;
+ }
+ if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
+ union {
+ uint64_t w;
+ double d;
+ } d;
+ d.d = value;
+ _msContext.D[regNum - UNW_ARM_D0] = d.w;
+ }
+ _LIBUNWIND_ABORT("unsupported float register");
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+ _msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
+#else
+ (void)regNum;
+ (void)value;
+ _LIBUNWIND_ABORT("float registers unimplemented");
+#endif
+}
+
+template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
+ RtlRestoreContext(&_msContext, nullptr);
+}
+
+#ifdef __arm__
+template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
+#endif
+
+template <typename A, typename R>
+const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
+ return R::getRegisterName(regNum);
+}
+
+template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
+ return false;
+}
+
+#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
+
/// UnwindCursor contains all state (including all register values) during
/// an unwind. This is normally stack allocated inside a unw_cursor_t.
template <typename A, typename R>
@@ -438,6 +898,10 @@ public:
virtual void saveVFPAsX();
#endif
+ // libunwind does not and should not depend on C++ library which means that we
+ // need our own defition of inline placement new.
+ static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
+
private:
#if defined(_LIBUNWIND_ARM_EHABI)
@@ -501,6 +965,13 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+ int stepWithCompactEncoding(Registers_ppc64 &) {
+ return UNW_EINVAL;
+ }
+#endif
+
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
int stepWithCompactEncoding(Registers_arm64 &) {
return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
@@ -514,12 +985,16 @@ private:
}
#endif
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
- int stepWithCompactEncoding(Registers_mips_n64 &) {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+ int stepWithCompactEncoding(Registers_mips_newabi &) {
return UNW_EINVAL;
}
#endif
+#if defined(_LIBUNWIND_TARGET_SPARC)
+ int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
+#endif
+
bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
R dummy;
return compactSaysUseDwarf(dummy, offset);
@@ -553,6 +1028,12 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+ bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
+ return true;
+ }
+#endif
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
@@ -570,11 +1051,16 @@ private:
}
#endif
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
- bool compactSaysUseDwarf(Registers_mips_n64 &, uint32_t *) const {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+ bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
return true;
}
#endif
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+ bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
+#endif
+
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -601,6 +1087,12 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+ compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
+ return 0;
+ }
+#endif
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
return UNWIND_ARM64_MODE_DWARF;
@@ -625,13 +1117,32 @@ private:
}
#endif
-#if defined (_LIBUNWIND_TARGET_MIPS_N64)
- compact_unwind_encoding_t dwarfEncoding(Registers_mips_n64 &) const {
+#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
+ compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
return 0;
}
#endif
+
+#if defined(_LIBUNWIND_TARGET_SPARC)
+ compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
+#endif
+
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+ // For runtime environments using SEH unwind data without Windows runtime
+ // support.
+ pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
+ void setLastPC(pint_t pc) { /* FIXME: Implement */ }
+ RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
+ /* FIXME: Implement */
+ *base = 0;
+ return nullptr;
+ }
+ bool getInfoFromSEH(pint_t pc);
+ int stepWithSEHData() { /* FIXME: Implement */ return 0; }
+#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+
A &_addressSpace;
R _registers;
@@ -708,6 +1219,8 @@ template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
return _isSignalFrame;
}
+#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+
#if defined(_LIBUNWIND_ARM_EHABI)
struct EHABIIndexEntry {
uint32_t functionOffset;
@@ -718,7 +1231,6 @@ template<typename A>
struct EHABISectionIterator {
typedef EHABISectionIterator _Self;
- typedef std::random_access_iterator_tag iterator_category;
typedef typename A::pint_t value_type;
typedef typename A::pint_t* pointer;
typedef typename A::pint_t& reference;
@@ -772,6 +1284,29 @@ struct EHABISectionIterator {
const UnwindInfoSections* _sects;
};
+namespace {
+
+template <typename A>
+EHABISectionIterator<A> EHABISectionUpperBound(
+ EHABISectionIterator<A> first,
+ EHABISectionIterator<A> last,
+ typename A::pint_t value) {
+ size_t len = last - first;
+ while (len > 0) {
+ size_t l2 = len / 2;
+ EHABISectionIterator<A> m = first + l2;
+ if (value < *m) {
+ len = l2;
+ } else {
+ first = ++m;
+ len -= l2 + 1;
+ }
+ }
+ return first;
+}
+
+}
+
template <typename A, typename R>
bool UnwindCursor<A, R>::getInfoFromEHABISection(
pint_t pc,
@@ -783,7 +1318,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
if (begin == end)
return false;
- EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
+ EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);
if (itNextPC == begin)
return false;
EHABISectionIterator<A> itThisPC = itNextPC - 1;
@@ -793,8 +1328,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
// in the table, we don't really know the function extent and have to choose a
// value for nextPC. Choosing max() will allow the range check during trace to
// succeed.
- pint_t nextPC = (itNextPC == end) ? std::numeric_limits<pint_t>::max()
- : itNextPC.functionAddress();
+ pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();
pint_t indexDataAddr = itThisPC.dataAddress();
if (indexDataAddr == 0)
@@ -954,7 +1488,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
if (foundFDE) {
typename CFI_Parser<A>::PrologInfo prolog;
if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
- &prolog)) {
+ R::getArch(), &prolog)) {
// Save off parsed FDE info
_info.start_ip = fdeInfo.pcStart;
_info.end_ip = fdeInfo.pcEnd;
@@ -1242,6 +1776,55 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
+ pint_t base;
+ RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
+ if (!unwindEntry) {
+ _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
+ return false;
+ }
+ _info.gp = 0;
+ _info.flags = 0;
+ _info.format = 0;
+ _info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
+ _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
+ _info.extra = base;
+ _info.start_ip = base + unwindEntry->BeginAddress;
+#ifdef _LIBUNWIND_TARGET_X86_64
+ _info.end_ip = base + unwindEntry->EndAddress;
+ // Only fill in the handler and LSDA if they're stale.
+ if (pc != getLastPC()) {
+ UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
+ if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
+ // The personality is given in the UNWIND_INFO itself. The LSDA immediately
+ // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
+ // these structures.)
+ // N.B. UNWIND_INFO structs are DWORD-aligned.
+ uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
+ const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
+ _info.lsda = reinterpret_cast<unw_word_t>(handler+1);
+ if (*handler) {
+ _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+ } else
+ _info.handler = 0;
+ } else {
+ _info.lsda = 0;
+ _info.handler = 0;
+ }
+ }
+#elif defined(_LIBUNWIND_TARGET_ARM)
+ _info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
+ _info.lsda = 0; // FIXME
+ _info.handler = 0; // FIXME
+#endif
+ setLastPC(pc);
+ return true;
+}
+#endif
+
+
template <typename A, typename R>
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
@@ -1285,6 +1868,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
}
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+ // If there is SEH unwind info, look there next.
+ if (this->getInfoFromSEH(pc))
+ return;
+#endif
+
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// If there is dwarf unwind info, look there next.
if (sects.dwarf_section != 0) {
@@ -1314,7 +1903,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
if (msg == NULL) {
typename CFI_Parser<A>::PrologInfo prolog;
if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
- pc, &prolog)) {
+ pc, R::getArch(), &prolog)) {
// save off parsed FDE info
_info.start_ip = fdeInfo.pcStart;
_info.end_ip = fdeInfo.pcEnd;
@@ -1343,8 +1932,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
// Double check this FDE is for a function that includes the pc.
if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
typename CFI_Parser<A>::PrologInfo prolog;
- if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo,
- cieInfo, pc, &prolog)) {
+ if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
+ pc, R::getArch(), &prolog)) {
// save off parsed FDE info
_info.start_ip = fdeInfo.pcStart;
_info.end_ip = fdeInfo.pcEnd;
@@ -1377,12 +1966,15 @@ int UnwindCursor<A, R>::step() {
int result;
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
result = this->stepWithCompactEncoding();
+#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+ result = this->stepWithSEHData();
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
result = this->stepWithDwarfFDE();
#elif defined(_LIBUNWIND_ARM_EHABI)
result = this->stepWithEHABI();
#else
#error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
+ _LIBUNWIND_SUPPORT_SEH_UNWIND or \
_LIBUNWIND_SUPPORT_DWARF_UNWIND or \
_LIBUNWIND_ARM_EHABI
#endif
@@ -1392,8 +1984,6 @@ int UnwindCursor<A, R>::step() {
this->setInfoBasedOnIPRegister(true);
if (_unwindInfoMissing)
return UNW_STEP_END;
- if (_info.gp)
- setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp);
}
return result;
diff --git a/src/UnwindLevel1-gcc-ext.c b/src/UnwindLevel1-gcc-ext.c
index 10619ba..fc303a9 100644
--- a/src/UnwindLevel1-gcc-ext.c
+++ b/src/UnwindLevel1-gcc-ext.c
@@ -1,9 +1,8 @@
//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements gcc extensions to the C++ ABI Exception Handling Level 1.
@@ -25,6 +24,10 @@
#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
+#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+#define private_1 private_[0]
+#endif
+
/// Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
@@ -33,9 +36,9 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
(void *)exception_object,
(long)exception_object->unwinder_cache.reserved1);
#else
- _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
+ _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR,
(void *)exception_object,
- (long)exception_object->private_1);
+ (intptr_t)exception_object->private_1);
#endif
#if defined(_LIBUNWIND_ARM_EHABI)
@@ -92,9 +95,9 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
unw_proc_info_t info;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
- unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc);
+ unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc);
if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS)
- return (void *)(long) info.start_ip;
+ return (void *)(intptr_t) info.start_ip;
else
return NULL;
}
@@ -190,14 +193,14 @@ _LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
unw_proc_info_t info;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
- unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc);
+ unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc);
unw_get_proc_info(&cursor, &info);
bases->tbase = (uintptr_t)info.extra;
bases->dbase = 0; // dbase not used on Mac OS X
bases->func = (uintptr_t)info.start_ip;
_LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc,
- (void *)(long) info.unwind_info);
- return (void *)(long) info.unwind_info;
+ (void *)(intptr_t) info.unwind_info);
+ return (void *)(intptr_t) info.unwind_info;
}
/// Returns the CFA (call frame area, or stack pointer at start of function)
diff --git a/src/UnwindLevel1.c b/src/UnwindLevel1.c
index 518577b..9d4084f 100644
--- a/src/UnwindLevel1.c
+++ b/src/UnwindLevel1.c
@@ -1,9 +1,8 @@
//===------------------------- UnwindLevel1.c -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements C++ ABI Exception Handling Level 1 as documented at:
@@ -32,6 +31,8 @@
#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
+#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
+
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
unw_init_local(cursor, uc);
@@ -287,7 +288,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
__personality_routine p =
- (__personality_routine)(long)(frameInfo.handler);
+ (__personality_routine)(intptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
@@ -449,6 +450,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
return result;
}
+#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND
/// Called by personality handler during phase 2 if a foreign exception
// is caught.
diff --git a/src/UnwindRegistersRestore.S b/src/UnwindRegistersRestore.S
index bd797f6..ead6454 100644
--- a/src/UnwindRegistersRestore.S
+++ b/src/UnwindRegistersRestore.S
@@ -1,9 +1,8 @@
//===-------------------- UnwindRegistersRestore.S ------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -128,6 +127,271 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
ret # rip was saved here
+#elif defined(__powerpc64__)
+
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
+//
+// void libunwind::Registers_ppc64::jumpto()
+//
+// On entry:
+// thread_state pointer is in r3
+//
+
+// load register (GPR)
+#define PPC64_LR(n) \
+ ld %r##n, (8 * (n + 2))(%r3)
+
+ // restore integral registers
+ // skip r0 for now
+ // skip r1 for now
+ PPC64_LR(2)
+ // skip r3 for now
+ // skip r4 for now
+ // skip r5 for now
+ PPC64_LR(6)
+ PPC64_LR(7)
+ PPC64_LR(8)
+ PPC64_LR(9)
+ PPC64_LR(10)
+ PPC64_LR(11)
+ PPC64_LR(12)
+ PPC64_LR(13)
+ PPC64_LR(14)
+ PPC64_LR(15)
+ PPC64_LR(16)
+ PPC64_LR(17)
+ PPC64_LR(18)
+ PPC64_LR(19)
+ PPC64_LR(20)
+ PPC64_LR(21)
+ PPC64_LR(22)
+ PPC64_LR(23)
+ PPC64_LR(24)
+ PPC64_LR(25)
+ PPC64_LR(26)
+ PPC64_LR(27)
+ PPC64_LR(28)
+ PPC64_LR(29)
+ PPC64_LR(30)
+ PPC64_LR(31)
+
+#ifdef PPC64_HAS_VMX
+
+ // restore VS registers
+ // (note that this also restores floating point registers and V registers,
+ // because part of VS is mapped to these registers)
+
+ addi %r4, %r3, PPC64_OFFS_FP
+
+// load VS register
+#define PPC64_LVS(n) \
+ lxvd2x %vs##n, 0, %r4 ;\
+ addi %r4, %r4, 16
+
+ // restore the first 32 VS regs (and also all floating point regs)
+ PPC64_LVS(0)
+ PPC64_LVS(1)
+ PPC64_LVS(2)
+ PPC64_LVS(3)
+ PPC64_LVS(4)
+ PPC64_LVS(5)
+ PPC64_LVS(6)
+ PPC64_LVS(7)
+ PPC64_LVS(8)
+ PPC64_LVS(9)
+ PPC64_LVS(10)
+ PPC64_LVS(11)
+ PPC64_LVS(12)
+ PPC64_LVS(13)
+ PPC64_LVS(14)
+ PPC64_LVS(15)
+ PPC64_LVS(16)
+ PPC64_LVS(17)
+ PPC64_LVS(18)
+ PPC64_LVS(19)
+ PPC64_LVS(20)
+ PPC64_LVS(21)
+ PPC64_LVS(22)
+ PPC64_LVS(23)
+ PPC64_LVS(24)
+ PPC64_LVS(25)
+ PPC64_LVS(26)
+ PPC64_LVS(27)
+ PPC64_LVS(28)
+ PPC64_LVS(29)
+ PPC64_LVS(30)
+ PPC64_LVS(31)
+
+ // use VRSAVE to conditionally restore the remaining VS regs,
+ // that are where the V regs are mapped
+
+ ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave
+ cmpwi %r5, 0
+ beq Lnovec
+
+// conditionally load VS
+#define PPC64_CLVS_BOTTOM(n) \
+ beq Ldone##n ;\
+ addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\
+ lxvd2x %vs##n, 0, %r4 ;\
+Ldone##n:
+
+#define PPC64_CLVSl(n) \
+ andis. %r0, %r5, (1<<(47-n)) ;\
+PPC64_CLVS_BOTTOM(n)
+
+#define PPC64_CLVSh(n) \
+ andi. %r0, %r5, (1<<(63-n)) ;\
+PPC64_CLVS_BOTTOM(n)
+
+ PPC64_CLVSl(32)
+ PPC64_CLVSl(33)
+ PPC64_CLVSl(34)
+ PPC64_CLVSl(35)
+ PPC64_CLVSl(36)
+ PPC64_CLVSl(37)
+ PPC64_CLVSl(38)
+ PPC64_CLVSl(39)
+ PPC64_CLVSl(40)
+ PPC64_CLVSl(41)
+ PPC64_CLVSl(42)
+ PPC64_CLVSl(43)
+ PPC64_CLVSl(44)
+ PPC64_CLVSl(45)
+ PPC64_CLVSl(46)
+ PPC64_CLVSl(47)
+ PPC64_CLVSh(48)
+ PPC64_CLVSh(49)
+ PPC64_CLVSh(50)
+ PPC64_CLVSh(51)
+ PPC64_CLVSh(52)
+ PPC64_CLVSh(53)
+ PPC64_CLVSh(54)
+ PPC64_CLVSh(55)
+ PPC64_CLVSh(56)
+ PPC64_CLVSh(57)
+ PPC64_CLVSh(58)
+ PPC64_CLVSh(59)
+ PPC64_CLVSh(60)
+ PPC64_CLVSh(61)
+ PPC64_CLVSh(62)
+ PPC64_CLVSh(63)
+
+#else
+
+// load FP register
+#define PPC64_LF(n) \
+ lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
+
+ // restore float registers
+ PPC64_LF(0)
+ PPC64_LF(1)
+ PPC64_LF(2)
+ PPC64_LF(3)
+ PPC64_LF(4)
+ PPC64_LF(5)
+ PPC64_LF(6)
+ PPC64_LF(7)
+ PPC64_LF(8)
+ PPC64_LF(9)
+ PPC64_LF(10)
+ PPC64_LF(11)
+ PPC64_LF(12)
+ PPC64_LF(13)
+ PPC64_LF(14)
+ PPC64_LF(15)
+ PPC64_LF(16)
+ PPC64_LF(17)
+ PPC64_LF(18)
+ PPC64_LF(19)
+ PPC64_LF(20)
+ PPC64_LF(21)
+ PPC64_LF(22)
+ PPC64_LF(23)
+ PPC64_LF(24)
+ PPC64_LF(25)
+ PPC64_LF(26)
+ PPC64_LF(27)
+ PPC64_LF(28)
+ PPC64_LF(29)
+ PPC64_LF(30)
+ PPC64_LF(31)
+
+ // restore vector registers if any are in use
+ ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave
+ cmpwi %r5, 0
+ beq Lnovec
+
+ subi %r4, %r1, 16
+ // r4 is now a 16-byte aligned pointer into the red zone
+ // the _vectorScalarRegisters may not be 16-byte aligned
+ // so copy via red zone temp buffer
+
+#define PPC64_CLV_UNALIGNED_BOTTOM(n) \
+ beq Ldone##n ;\
+ ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\
+ std %r0, 0(%r4) ;\
+ ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\
+ std %r0, 8(%r4) ;\
+ lvx %v##n, 0, %r4 ;\
+Ldone ## n:
+
+#define PPC64_CLV_UNALIGNEDl(n) \
+ andis. %r0, %r5, (1<<(15-n)) ;\
+PPC64_CLV_UNALIGNED_BOTTOM(n)
+
+#define PPC64_CLV_UNALIGNEDh(n) \
+ andi. %r0, %r5, (1<<(31-n)) ;\
+PPC64_CLV_UNALIGNED_BOTTOM(n)
+
+ PPC64_CLV_UNALIGNEDl(0)
+ PPC64_CLV_UNALIGNEDl(1)
+ PPC64_CLV_UNALIGNEDl(2)
+ PPC64_CLV_UNALIGNEDl(3)
+ PPC64_CLV_UNALIGNEDl(4)
+ PPC64_CLV_UNALIGNEDl(5)
+ PPC64_CLV_UNALIGNEDl(6)
+ PPC64_CLV_UNALIGNEDl(7)
+ PPC64_CLV_UNALIGNEDl(8)
+ PPC64_CLV_UNALIGNEDl(9)
+ PPC64_CLV_UNALIGNEDl(10)
+ PPC64_CLV_UNALIGNEDl(11)
+ PPC64_CLV_UNALIGNEDl(12)
+ PPC64_CLV_UNALIGNEDl(13)
+ PPC64_CLV_UNALIGNEDl(14)
+ PPC64_CLV_UNALIGNEDl(15)
+ PPC64_CLV_UNALIGNEDh(16)
+ PPC64_CLV_UNALIGNEDh(17)
+ PPC64_CLV_UNALIGNEDh(18)
+ PPC64_CLV_UNALIGNEDh(19)
+ PPC64_CLV_UNALIGNEDh(20)
+ PPC64_CLV_UNALIGNEDh(21)
+ PPC64_CLV_UNALIGNEDh(22)
+ PPC64_CLV_UNALIGNEDh(23)
+ PPC64_CLV_UNALIGNEDh(24)
+ PPC64_CLV_UNALIGNEDh(25)
+ PPC64_CLV_UNALIGNEDh(26)
+ PPC64_CLV_UNALIGNEDh(27)
+ PPC64_CLV_UNALIGNEDh(28)
+ PPC64_CLV_UNALIGNEDh(29)
+ PPC64_CLV_UNALIGNEDh(30)
+ PPC64_CLV_UNALIGNEDh(31)
+
+#endif
+
+Lnovec:
+ ld %r0, PPC64_OFFS_CR(%r3)
+ mtcr %r0
+ ld %r0, PPC64_OFFS_SRR0(%r3)
+ mtctr %r0
+
+ PPC64_LR(0)
+ PPC64_LR(5)
+ PPC64_LR(4)
+ PPC64_LR(1)
+ PPC64_LR(3)
+ bctr
+
#elif defined(__ppc__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
@@ -394,7 +658,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJu
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv)
@ VFP and iwMMX instructions are only available when compiling with the flags
@ that enable them. We do not want to do that in the library (because we do not
@ want the compiler to generate instructions that access those) but this is
@@ -415,7 +679,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv)
vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
JMP(lr)
@@ -429,7 +693,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFL
#if defined(__ELF__)
.fpu vfpv3
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv)
vldmia r0, {d16-d31}
JMP(lr)
@@ -445,7 +709,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
#if defined(__ELF__)
.arch armv5te
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv)
ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8
ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8
ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8
@@ -493,7 +757,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
# thread_state pointer is in r3
#
- # restore integral registerrs
+ # restore integral registers
l.lwz r0, 0(r3)
l.lwz r1, 4(r3)
l.lwz r2, 8(r3)
@@ -503,7 +767,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
l.lwz r6, 24(r3)
l.lwz r7, 28(r3)
l.lwz r8, 32(r3)
- l.lwz r9, 36(r3)
+ # skip r9
l.lwz r10, 40(r3)
l.lwz r11, 44(r3)
l.lwz r12, 48(r3)
@@ -530,11 +794,13 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
# at last, restore r3
l.lwz r3, 12(r3)
+ # load new pc into ra
+ l.lwz r9, 128(r3)
# jump to pc
l.jr r9
l.nop
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
//
// void libunwind::Registers_mips_o32::jumpto()
@@ -547,6 +813,59 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
.set noat
.set noreorder
.set nomacro
+#ifdef __mips_hard_float
+#if __mips_fpr != 64
+ ldc1 $f0, (4 * 36 + 8 * 0)($4)
+ ldc1 $f2, (4 * 36 + 8 * 2)($4)
+ ldc1 $f4, (4 * 36 + 8 * 4)($4)
+ ldc1 $f6, (4 * 36 + 8 * 6)($4)
+ ldc1 $f8, (4 * 36 + 8 * 8)($4)
+ ldc1 $f10, (4 * 36 + 8 * 10)($4)
+ ldc1 $f12, (4 * 36 + 8 * 12)($4)
+ ldc1 $f14, (4 * 36 + 8 * 14)($4)
+ ldc1 $f16, (4 * 36 + 8 * 16)($4)
+ ldc1 $f18, (4 * 36 + 8 * 18)($4)
+ ldc1 $f20, (4 * 36 + 8 * 20)($4)
+ ldc1 $f22, (4 * 36 + 8 * 22)($4)
+ ldc1 $f24, (4 * 36 + 8 * 24)($4)
+ ldc1 $f26, (4 * 36 + 8 * 26)($4)
+ ldc1 $f28, (4 * 36 + 8 * 28)($4)
+ ldc1 $f30, (4 * 36 + 8 * 30)($4)
+#else
+ ldc1 $f0, (4 * 36 + 8 * 0)($4)
+ ldc1 $f1, (4 * 36 + 8 * 1)($4)
+ ldc1 $f2, (4 * 36 + 8 * 2)($4)
+ ldc1 $f3, (4 * 36 + 8 * 3)($4)
+ ldc1 $f4, (4 * 36 + 8 * 4)($4)
+ ldc1 $f5, (4 * 36 + 8 * 5)($4)
+ ldc1 $f6, (4 * 36 + 8 * 6)($4)
+ ldc1 $f7, (4 * 36 + 8 * 7)($4)
+ ldc1 $f8, (4 * 36 + 8 * 8)($4)
+ ldc1 $f9, (4 * 36 + 8 * 9)($4)
+ ldc1 $f10, (4 * 36 + 8 * 10)($4)
+ ldc1 $f11, (4 * 36 + 8 * 11)($4)
+ ldc1 $f12, (4 * 36 + 8 * 12)($4)
+ ldc1 $f13, (4 * 36 + 8 * 13)($4)
+ ldc1 $f14, (4 * 36 + 8 * 14)($4)
+ ldc1 $f15, (4 * 36 + 8 * 15)($4)
+ ldc1 $f16, (4 * 36 + 8 * 16)($4)
+ ldc1 $f17, (4 * 36 + 8 * 17)($4)
+ ldc1 $f18, (4 * 36 + 8 * 18)($4)
+ ldc1 $f19, (4 * 36 + 8 * 19)($4)
+ ldc1 $f20, (4 * 36 + 8 * 20)($4)
+ ldc1 $f21, (4 * 36 + 8 * 21)($4)
+ ldc1 $f22, (4 * 36 + 8 * 22)($4)
+ ldc1 $f23, (4 * 36 + 8 * 23)($4)
+ ldc1 $f24, (4 * 36 + 8 * 24)($4)
+ ldc1 $f25, (4 * 36 + 8 * 25)($4)
+ ldc1 $f26, (4 * 36 + 8 * 26)($4)
+ ldc1 $f27, (4 * 36 + 8 * 27)($4)
+ ldc1 $f28, (4 * 36 + 8 * 28)($4)
+ ldc1 $f29, (4 * 36 + 8 * 29)($4)
+ ldc1 $f30, (4 * 36 + 8 * 30)($4)
+ ldc1 $f31, (4 * 36 + 8 * 31)($4)
+#endif
+#endif
// restore hi and lo
lw $8, (4 * 33)($4)
mthi $8
@@ -590,19 +909,53 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
lw $4, (4 * 4)($4)
.set pop
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64)
//
-// void libunwind::Registers_mips_n64::jumpto()
+// void libunwind::Registers_mips_newabi::jumpto()
//
// On entry:
// thread state pointer is in a0 ($4)
//
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
.set push
.set noat
.set noreorder
.set nomacro
+#ifdef __mips_hard_float
+ ldc1 $f0, (8 * 35)($4)
+ ldc1 $f1, (8 * 36)($4)
+ ldc1 $f2, (8 * 37)($4)
+ ldc1 $f3, (8 * 38)($4)
+ ldc1 $f4, (8 * 39)($4)
+ ldc1 $f5, (8 * 40)($4)
+ ldc1 $f6, (8 * 41)($4)
+ ldc1 $f7, (8 * 42)($4)
+ ldc1 $f8, (8 * 43)($4)
+ ldc1 $f9, (8 * 44)($4)
+ ldc1 $f10, (8 * 45)($4)
+ ldc1 $f11, (8 * 46)($4)
+ ldc1 $f12, (8 * 47)($4)
+ ldc1 $f13, (8 * 48)($4)
+ ldc1 $f14, (8 * 49)($4)
+ ldc1 $f15, (8 * 50)($4)
+ ldc1 $f16, (8 * 51)($4)
+ ldc1 $f17, (8 * 52)($4)
+ ldc1 $f18, (8 * 53)($4)
+ ldc1 $f19, (8 * 54)($4)
+ ldc1 $f20, (8 * 55)($4)
+ ldc1 $f21, (8 * 56)($4)
+ ldc1 $f22, (8 * 57)($4)
+ ldc1 $f23, (8 * 58)($4)
+ ldc1 $f24, (8 * 59)($4)
+ ldc1 $f25, (8 * 60)($4)
+ ldc1 $f26, (8 * 61)($4)
+ ldc1 $f27, (8 * 62)($4)
+ ldc1 $f28, (8 * 63)($4)
+ ldc1 $f29, (8 * 64)($4)
+ ldc1 $f30, (8 * 65)($4)
+ ldc1 $f31, (8 * 66)($4)
+#endif
// restore hi and lo
ld $8, (8 * 33)($4)
mthi $8
@@ -646,6 +999,28 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv)
ld $4, (8 * 4)($4)
.set pop
+#elif defined(__sparc__)
+
+//
+// void libunwind::Registers_sparc_o32::jumpto()
+//
+// On entry:
+// thread_state pointer is in o0
+//
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
+ ta 3
+ ldd [%o0 + 64], %l0
+ ldd [%o0 + 72], %l2
+ ldd [%o0 + 80], %l4
+ ldd [%o0 + 88], %l6
+ ldd [%o0 + 96], %i0
+ ldd [%o0 + 104], %i2
+ ldd [%o0 + 112], %i4
+ ldd [%o0 + 120], %i6
+ ld [%o0 + 60], %o7
+ jmp %o7
+ nop
+
#endif
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
diff --git a/src/UnwindRegistersSave.S b/src/UnwindRegistersSave.S
index 4583f50..c7c4959 100644
--- a/src/UnwindRegistersSave.S
+++ b/src/UnwindRegistersSave.S
@@ -1,9 +1,8 @@
//===------------------------ UnwindRegistersSave.S -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -116,7 +115,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
xorl %eax, %eax # return UNW_ESUCCESS
ret
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
#
# extern int unw_getcontext(unw_context_t* thread_state)
@@ -167,12 +166,65 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
sw $8, (4 * 33)($4)
mflo $8
sw $8, (4 * 34)($4)
+#ifdef __mips_hard_float
+#if __mips_fpr != 64
+ sdc1 $f0, (4 * 36 + 8 * 0)($4)
+ sdc1 $f2, (4 * 36 + 8 * 2)($4)
+ sdc1 $f4, (4 * 36 + 8 * 4)($4)
+ sdc1 $f6, (4 * 36 + 8 * 6)($4)
+ sdc1 $f8, (4 * 36 + 8 * 8)($4)
+ sdc1 $f10, (4 * 36 + 8 * 10)($4)
+ sdc1 $f12, (4 * 36 + 8 * 12)($4)
+ sdc1 $f14, (4 * 36 + 8 * 14)($4)
+ sdc1 $f16, (4 * 36 + 8 * 16)($4)
+ sdc1 $f18, (4 * 36 + 8 * 18)($4)
+ sdc1 $f20, (4 * 36 + 8 * 20)($4)
+ sdc1 $f22, (4 * 36 + 8 * 22)($4)
+ sdc1 $f24, (4 * 36 + 8 * 24)($4)
+ sdc1 $f26, (4 * 36 + 8 * 26)($4)
+ sdc1 $f28, (4 * 36 + 8 * 28)($4)
+ sdc1 $f30, (4 * 36 + 8 * 30)($4)
+#else
+ sdc1 $f0, (4 * 36 + 8 * 0)($4)
+ sdc1 $f1, (4 * 36 + 8 * 1)($4)
+ sdc1 $f2, (4 * 36 + 8 * 2)($4)
+ sdc1 $f3, (4 * 36 + 8 * 3)($4)
+ sdc1 $f4, (4 * 36 + 8 * 4)($4)
+ sdc1 $f5, (4 * 36 + 8 * 5)($4)
+ sdc1 $f6, (4 * 36 + 8 * 6)($4)
+ sdc1 $f7, (4 * 36 + 8 * 7)($4)
+ sdc1 $f8, (4 * 36 + 8 * 8)($4)
+ sdc1 $f9, (4 * 36 + 8 * 9)($4)
+ sdc1 $f10, (4 * 36 + 8 * 10)($4)
+ sdc1 $f11, (4 * 36 + 8 * 11)($4)
+ sdc1 $f12, (4 * 36 + 8 * 12)($4)
+ sdc1 $f13, (4 * 36 + 8 * 13)($4)
+ sdc1 $f14, (4 * 36 + 8 * 14)($4)
+ sdc1 $f15, (4 * 36 + 8 * 15)($4)
+ sdc1 $f16, (4 * 36 + 8 * 16)($4)
+ sdc1 $f17, (4 * 36 + 8 * 17)($4)
+ sdc1 $f18, (4 * 36 + 8 * 18)($4)
+ sdc1 $f19, (4 * 36 + 8 * 19)($4)
+ sdc1 $f20, (4 * 36 + 8 * 20)($4)
+ sdc1 $f21, (4 * 36 + 8 * 21)($4)
+ sdc1 $f22, (4 * 36 + 8 * 22)($4)
+ sdc1 $f23, (4 * 36 + 8 * 23)($4)
+ sdc1 $f24, (4 * 36 + 8 * 24)($4)
+ sdc1 $f25, (4 * 36 + 8 * 25)($4)
+ sdc1 $f26, (4 * 36 + 8 * 26)($4)
+ sdc1 $f27, (4 * 36 + 8 * 27)($4)
+ sdc1 $f28, (4 * 36 + 8 * 28)($4)
+ sdc1 $f29, (4 * 36 + 8 * 29)($4)
+ sdc1 $f30, (4 * 36 + 8 * 30)($4)
+ sdc1 $f31, (4 * 36 + 8 * 31)($4)
+#endif
+#endif
jr $31
# return UNW_ESUCCESS
or $2, $0, $0
.set pop
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+#elif defined(__mips64)
#
# extern int unw_getcontext(unw_context_t* thread_state)
@@ -223,6 +275,40 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
sd $8, (8 * 33)($4)
mflo $8
sd $8, (8 * 34)($4)
+#ifdef __mips_hard_float
+ sdc1 $f0, (8 * 35)($4)
+ sdc1 $f1, (8 * 36)($4)
+ sdc1 $f2, (8 * 37)($4)
+ sdc1 $f3, (8 * 38)($4)
+ sdc1 $f4, (8 * 39)($4)
+ sdc1 $f5, (8 * 40)($4)
+ sdc1 $f6, (8 * 41)($4)
+ sdc1 $f7, (8 * 42)($4)
+ sdc1 $f8, (8 * 43)($4)
+ sdc1 $f9, (8 * 44)($4)
+ sdc1 $f10, (8 * 45)($4)
+ sdc1 $f11, (8 * 46)($4)
+ sdc1 $f12, (8 * 47)($4)
+ sdc1 $f13, (8 * 48)($4)
+ sdc1 $f14, (8 * 49)($4)
+ sdc1 $f15, (8 * 50)($4)
+ sdc1 $f16, (8 * 51)($4)
+ sdc1 $f17, (8 * 52)($4)
+ sdc1 $f18, (8 * 53)($4)
+ sdc1 $f19, (8 * 54)($4)
+ sdc1 $f20, (8 * 55)($4)
+ sdc1 $f21, (8 * 56)($4)
+ sdc1 $f22, (8 * 57)($4)
+ sdc1 $f23, (8 * 58)($4)
+ sdc1 $f24, (8 * 59)($4)
+ sdc1 $f25, (8 * 60)($4)
+ sdc1 $f26, (8 * 61)($4)
+ sdc1 $f27, (8 * 62)($4)
+ sdc1 $f28, (8 * 63)($4)
+ sdc1 $f29, (8 * 64)($4)
+ sdc1 $f30, (8 * 65)($4)
+ sdc1 $f31, (8 * 66)($4)
+#endif
jr $31
# return UNW_ESUCCESS
or $2, $0, $0
@@ -237,6 +323,237 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
teq $0, $0
+#elif defined(__powerpc64__)
+
+//
+// extern int unw_getcontext(unw_context_t* thread_state)
+//
+// On entry:
+// thread_state pointer is in r3
+//
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+
+// store register (GPR)
+#define PPC64_STR(n) \
+ std %r##n, (8 * (n + 2))(%r3)
+
+ // save GPRs
+ PPC64_STR(0)
+ mflr %r0
+ std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
+ PPC64_STR(1)
+ PPC64_STR(2)
+ PPC64_STR(3)
+ PPC64_STR(4)
+ PPC64_STR(5)
+ PPC64_STR(6)
+ PPC64_STR(7)
+ PPC64_STR(8)
+ PPC64_STR(9)
+ PPC64_STR(10)
+ PPC64_STR(11)
+ PPC64_STR(12)
+ PPC64_STR(13)
+ PPC64_STR(14)
+ PPC64_STR(15)
+ PPC64_STR(16)
+ PPC64_STR(17)
+ PPC64_STR(18)
+ PPC64_STR(19)
+ PPC64_STR(20)
+ PPC64_STR(21)
+ PPC64_STR(22)
+ PPC64_STR(23)
+ PPC64_STR(24)
+ PPC64_STR(25)
+ PPC64_STR(26)
+ PPC64_STR(27)
+ PPC64_STR(28)
+ PPC64_STR(29)
+ PPC64_STR(30)
+ PPC64_STR(31)
+
+ mfcr %r0
+ std %r0, PPC64_OFFS_CR(%r3)
+ mfxer %r0
+ std %r0, PPC64_OFFS_XER(%r3)
+ mflr %r0
+ std %r0, PPC64_OFFS_LR(%r3)
+ mfctr %r0
+ std %r0, PPC64_OFFS_CTR(%r3)
+ mfvrsave %r0
+ std %r0, PPC64_OFFS_VRSAVE(%r3)
+
+#ifdef PPC64_HAS_VMX
+ // save VS registers
+ // (note that this also saves floating point registers and V registers,
+ // because part of VS is mapped to these registers)
+
+ addi %r4, %r3, PPC64_OFFS_FP
+
+// store VS register
+#define PPC64_STVS(n) \
+ stxvd2x %vs##n, 0, %r4 ;\
+ addi %r4, %r4, 16
+
+ PPC64_STVS(0)
+ PPC64_STVS(1)
+ PPC64_STVS(2)
+ PPC64_STVS(3)
+ PPC64_STVS(4)
+ PPC64_STVS(5)
+ PPC64_STVS(6)
+ PPC64_STVS(7)
+ PPC64_STVS(8)
+ PPC64_STVS(9)
+ PPC64_STVS(10)
+ PPC64_STVS(11)
+ PPC64_STVS(12)
+ PPC64_STVS(13)
+ PPC64_STVS(14)
+ PPC64_STVS(15)
+ PPC64_STVS(16)
+ PPC64_STVS(17)
+ PPC64_STVS(18)
+ PPC64_STVS(19)
+ PPC64_STVS(20)
+ PPC64_STVS(21)
+ PPC64_STVS(22)
+ PPC64_STVS(23)
+ PPC64_STVS(24)
+ PPC64_STVS(25)
+ PPC64_STVS(26)
+ PPC64_STVS(27)
+ PPC64_STVS(28)
+ PPC64_STVS(29)
+ PPC64_STVS(30)
+ PPC64_STVS(31)
+ PPC64_STVS(32)
+ PPC64_STVS(33)
+ PPC64_STVS(34)
+ PPC64_STVS(35)
+ PPC64_STVS(36)
+ PPC64_STVS(37)
+ PPC64_STVS(38)
+ PPC64_STVS(39)
+ PPC64_STVS(40)
+ PPC64_STVS(41)
+ PPC64_STVS(42)
+ PPC64_STVS(43)
+ PPC64_STVS(44)
+ PPC64_STVS(45)
+ PPC64_STVS(46)
+ PPC64_STVS(47)
+ PPC64_STVS(48)
+ PPC64_STVS(49)
+ PPC64_STVS(50)
+ PPC64_STVS(51)
+ PPC64_STVS(52)
+ PPC64_STVS(53)
+ PPC64_STVS(54)
+ PPC64_STVS(55)
+ PPC64_STVS(56)
+ PPC64_STVS(57)
+ PPC64_STVS(58)
+ PPC64_STVS(59)
+ PPC64_STVS(60)
+ PPC64_STVS(61)
+ PPC64_STVS(62)
+ PPC64_STVS(63)
+
+#else
+
+// store FP register
+#define PPC64_STF(n) \
+ stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
+
+ // save float registers
+ PPC64_STF(0)
+ PPC64_STF(1)
+ PPC64_STF(2)
+ PPC64_STF(3)
+ PPC64_STF(4)
+ PPC64_STF(5)
+ PPC64_STF(6)
+ PPC64_STF(7)
+ PPC64_STF(8)
+ PPC64_STF(9)
+ PPC64_STF(10)
+ PPC64_STF(11)
+ PPC64_STF(12)
+ PPC64_STF(13)
+ PPC64_STF(14)
+ PPC64_STF(15)
+ PPC64_STF(16)
+ PPC64_STF(17)
+ PPC64_STF(18)
+ PPC64_STF(19)
+ PPC64_STF(20)
+ PPC64_STF(21)
+ PPC64_STF(22)
+ PPC64_STF(23)
+ PPC64_STF(24)
+ PPC64_STF(25)
+ PPC64_STF(26)
+ PPC64_STF(27)
+ PPC64_STF(28)
+ PPC64_STF(29)
+ PPC64_STF(30)
+ PPC64_STF(31)
+
+ // save vector registers
+
+ // Use 16-bytes below the stack pointer as an
+ // aligned buffer to save each vector register.
+ // Note that the stack pointer is always 16-byte aligned.
+ subi %r4, %r1, 16
+
+#define PPC64_STV_UNALIGNED(n) \
+ stvx %v##n, 0, %r4 ;\
+ ld %r5, 0(%r4) ;\
+ std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\
+ ld %r5, 8(%r4) ;\
+ std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
+
+ PPC64_STV_UNALIGNED(0)
+ PPC64_STV_UNALIGNED(1)
+ PPC64_STV_UNALIGNED(2)
+ PPC64_STV_UNALIGNED(3)
+ PPC64_STV_UNALIGNED(4)
+ PPC64_STV_UNALIGNED(5)
+ PPC64_STV_UNALIGNED(6)
+ PPC64_STV_UNALIGNED(7)
+ PPC64_STV_UNALIGNED(8)
+ PPC64_STV_UNALIGNED(9)
+ PPC64_STV_UNALIGNED(10)
+ PPC64_STV_UNALIGNED(11)
+ PPC64_STV_UNALIGNED(12)
+ PPC64_STV_UNALIGNED(13)
+ PPC64_STV_UNALIGNED(14)
+ PPC64_STV_UNALIGNED(15)
+ PPC64_STV_UNALIGNED(16)
+ PPC64_STV_UNALIGNED(17)
+ PPC64_STV_UNALIGNED(18)
+ PPC64_STV_UNALIGNED(19)
+ PPC64_STV_UNALIGNED(20)
+ PPC64_STV_UNALIGNED(21)
+ PPC64_STV_UNALIGNED(22)
+ PPC64_STV_UNALIGNED(23)
+ PPC64_STV_UNALIGNED(24)
+ PPC64_STV_UNALIGNED(25)
+ PPC64_STV_UNALIGNED(26)
+ PPC64_STV_UNALIGNED(27)
+ PPC64_STV_UNALIGNED(28)
+ PPC64_STV_UNALIGNED(29)
+ PPC64_STV_UNALIGNED(30)
+ PPC64_STV_UNALIGNED(31)
+
+#endif
+
+ li %r3, 0 // return UNW_ESUCCESS
+ blr
+
+
#elif defined(__ppc__)
;
@@ -490,7 +807,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
vstmia r0, {d0-d15}
JMP(lr)
@@ -504,7 +821,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMD
#if defined(__ELF__)
.fpu vfpv3-d16
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
JMP(lr)
@@ -518,7 +835,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMX
#if defined(__ELF__)
.fpu vfpv3
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
@ VFP and iwMMX instructions are only available when compiling with the flags
@ that enable them. We do not want to do that in the library (because we do not
@ want the compiler to generate instructions that access those) but this is
@@ -541,7 +858,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
#if defined(__ELF__)
.arch armv5te
#endif
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
@@ -620,9 +937,41 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
l.sw 116(r3), r29
l.sw 120(r3), r30
l.sw 124(r3), r31
-#endif
+ # store ra to pc
+ l.sw 128(r3), r9
+ # zero epcr
+ l.sw 132(r3), r0
+
+#elif defined(__sparc__)
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+# thread_state pointer is in o0
+#
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+ ta 3
+ add %o7, 8, %o7
+ std %g0, [%o0 + 0]
+ std %g2, [%o0 + 8]
+ std %g4, [%o0 + 16]
+ std %g6, [%o0 + 24]
+ std %o0, [%o0 + 32]
+ std %o2, [%o0 + 40]
+ std %o4, [%o0 + 48]
+ std %o6, [%o0 + 56]
+ std %l0, [%o0 + 64]
+ std %l2, [%o0 + 72]
+ std %l4, [%o0 + 80]
+ std %l6, [%o0 + 88]
+ std %i0, [%o0 + 96]
+ std %i2, [%o0 + 104]
+ std %i4, [%o0 + 112]
+ std %i6, [%o0 + 120]
+ jmp %o7
+ clr %o0 // return UNW_ESUCCESS
+#endif
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
NO_EXEC_STACK_DIRECTIVE
-
diff --git a/src/Unwind_AppleExtras.cpp b/src/Unwind_AppleExtras.cpp
index 39f379c..248d995 100644
--- a/src/Unwind_AppleExtras.cpp
+++ b/src/Unwind_AppleExtras.cpp
@@ -1,9 +1,8 @@
//===--------------------- Unwind_AppleExtras.cpp -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
//===----------------------------------------------------------------------===//
diff --git a/src/assembly.h b/src/assembly.h
index 2b2269c..a15b89f 100644
--- a/src/assembly.h
+++ b/src/assembly.h
@@ -1,9 +1,8 @@
/* ===-- assembly.h - libUnwind assembler support macros -------------------===
*
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
+ * 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
*
* ===----------------------------------------------------------------------===
*
@@ -16,7 +15,20 @@
#ifndef UNWIND_ASSEMBLY_H
#define UNWIND_ASSEMBLY_H
-#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__)
+#define SEPARATOR ;
+#define PPC64_OFFS_SRR0 0
+#define PPC64_OFFS_CR 272
+#define PPC64_OFFS_XER 280
+#define PPC64_OFFS_LR 288
+#define PPC64_OFFS_CTR 296
+#define PPC64_OFFS_VRSAVE 304
+#define PPC64_OFFS_FP 312
+#define PPC64_OFFS_V 824
+#ifdef _ARCH_PWR8
+#define PPC64_HAS_VMX
+#endif
+#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
#define SEPARATOR @
#elif defined(__arm64__)
#define SEPARATOR %%
@@ -31,6 +43,7 @@
#if defined(__APPLE__)
#define SYMBOL_IS_FUNC(name)
+#define EXPORT_SYMBOL(name)
#define HIDDEN_SYMBOL(name) .private_extern name
#define NO_EXEC_STACK_DIRECTIVE
@@ -41,6 +54,7 @@
#else
#define SYMBOL_IS_FUNC(name) .type name,@function
#endif
+#define EXPORT_SYMBOL(name)
#define HIDDEN_SYMBOL(name) .hidden name
#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
@@ -57,10 +71,21 @@
.scl 2 SEPARATOR \
.type 32 SEPARATOR \
.endef
+#define EXPORT_SYMBOL2(name) \
+ .section .drectve,"yn" SEPARATOR \
+ .ascii "-export:", #name, "\0" SEPARATOR \
+ .text
+#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
+#define EXPORT_SYMBOL(name)
+#else
+#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
+#endif
#define HIDDEN_SYMBOL(name)
#define NO_EXEC_STACK_DIRECTIVE
+#elif defined(__sparc__)
+
#else
#error Unsupported target
@@ -69,6 +94,7 @@
#define DEFINE_LIBUNWIND_FUNCTION(name) \
.globl SYMBOL_NAME(name) SEPARATOR \
+ EXPORT_SYMBOL(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
SYMBOL_NAME(name):
diff --git a/src/config.h b/src/config.h
index 0f29b77..c2fff50 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,9 +1,8 @@
//===----------------------------- config.h -------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Defines macros used within libunwind project.
@@ -38,7 +37,11 @@
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#endif
#elif defined(_WIN32)
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+ #ifdef __SEH__
+ #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
+ #else
+ #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+ #endif
#else
#if defined(__ARM_DWARF_EH__) || !defined(__arm__)
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
@@ -63,17 +66,23 @@
#define _LIBUNWIND_BUILD_SJLJ_APIS
#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
#define _LIBUNWIND_SUPPORT_FRAME_APIS
#endif
#if defined(__i386__) || defined(__x86_64__) || \
- defined(__ppc__) || defined(__ppc64__) || \
+ defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
(!defined(__APPLE__) && defined(__arm__)) || \
(defined(__arm64__) || defined(__aarch64__)) || \
defined(__mips__)
+#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
#define _LIBUNWIND_BUILD_ZERO_COST_APIS
#endif
+#endif
+
+#if defined(__powerpc64__) && defined(_ARCH_PWR8)
+#define PPC64_HAS_VMX
+#endif
#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
#define _LIBUNWIND_ABORT(msg) \
@@ -91,8 +100,11 @@
#endif
#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
+#define _LIBUNWIND_LOG0(msg)
#define _LIBUNWIND_LOG(msg, ...)
#else
+#define _LIBUNWIND_LOG0(msg) \
+ fprintf(stderr, "libunwind: " msg "\n")
#define _LIBUNWIND_LOG(msg, ...) \
fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
#endif
@@ -152,7 +164,7 @@
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# define COMP_OP ==
#else
-# define COMP_OP <
+# define COMP_OP <=
#endif
template <typename _Type, typename _Mem>
struct check_fit {
diff --git a/src/dwarf2.h b/src/dwarf2.h
index 0dcd2ca..40f0daf 100644
--- a/src/dwarf2.h
+++ b/src/dwarf2.h
@@ -1,9 +1,8 @@
//===------------------------------- dwarf2.h -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -49,7 +48,10 @@ enum {
// GNU extensions
DW_CFA_GNU_window_save = 0x2D,
DW_CFA_GNU_args_size = 0x2E,
- DW_CFA_GNU_negative_offset_extended = 0x2F
+ DW_CFA_GNU_negative_offset_extended = 0x2F,
+
+ // AARCH64 extensions
+ DW_CFA_AARCH64_negate_ra_state = 0x2D
};
diff --git a/src/libunwind.cpp b/src/libunwind.cpp
index 0b7fb40..03dfeae 100644
--- a/src/libunwind.cpp
+++ b/src/libunwind.cpp
@@ -1,9 +1,8 @@
//===--------------------------- libunwind.cpp ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements unw_* functions from <libunwind.h>
@@ -12,12 +11,6 @@
#include <libunwind.h>
-#ifndef NDEBUG
-#include <cstdlib> // getenv
-#endif
-#include <new>
-#include <algorithm>
-
#include "libunwind_ext.h"
#include "config.h"
@@ -51,6 +44,8 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_x86
#elif defined(__x86_64__)
# define REGISTER_KIND Registers_x86_64
+#elif defined(__powerpc64__)
+# define REGISTER_KIND Registers_ppc64
#elif defined(__ppc__)
# define REGISTER_KIND Registers_ppc
#elif defined(__aarch64__)
@@ -59,18 +54,21 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_arm
#elif defined(__or1k__)
# define REGISTER_KIND Registers_or1k
-#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
# define REGISTER_KIND Registers_mips_o32
-#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
-# define REGISTER_KIND Registers_mips_n64
+#elif defined(__mips64)
+# define REGISTER_KIND Registers_mips_newabi
#elif defined(__mips__)
# warning The MIPS architecture is not supported with this ABI and environment!
+#elif defined(__sparc__)
+# define REGISTER_KIND Registers_sparc
#else
# error Architecture not supported
#endif
// Use "placement new" to allocate UnwindCursor in the cursor buffer.
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
- context, LocalAddressSpace::sThisAddressSpace);
+ new (reinterpret_cast<UnwindCursor<LocalAddressSpace, REGISTER_KIND> *>(cursor))
+ UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
+ context, LocalAddressSpace::sThisAddressSpace);
#undef REGISTER_KIND
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->setInfoBasedOnIPRegister();
@@ -78,88 +76,6 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
return UNW_ESUCCESS;
}
-#ifdef UNW_REMOTE
-/// Create a cursor into a thread in another process.
-_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
- unw_addr_space_t as,
- void *arg) {
- // special case: unw_init_remote(xx, unw_local_addr_space, xx)
- if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
- return unw_init_local(cursor, NULL); //FIXME
-
- // use "placement new" to allocate UnwindCursor in the cursor buffer
- switch (as->cpuType) {
- case CPU_TYPE_I386:
- new ((void *)cursor)
- UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
- Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
- break;
- case CPU_TYPE_X86_64:
- new ((void *)cursor)
- UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>,
- Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg);
- break;
- case CPU_TYPE_POWERPC:
- new ((void *)cursor)
- UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
- Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
- break;
- default:
- return UNW_EUNSPEC;
- }
- return UNW_ESUCCESS;
-}
-
-
-static bool is64bit(task_t task) {
- return false; // FIXME
-}
-
-/// Create an address_space object for use in examining another task.
-_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
-#if __i386__
- if (is64bit(task)) {
- unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
- as->taskPort = task;
- as->cpuType = CPU_TYPE_X86_64;
- //as->oas
- } else {
- unw_addr_space_i386 *as = new unw_addr_space_i386(task);
- as->taskPort = task;
- as->cpuType = CPU_TYPE_I386;
- //as->oas
- }
-#else
-// FIXME
-#endif
-}
-
-
-/// Delete an address_space object.
-_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
- switch (asp->cpuType) {
-#if __i386__ || __x86_64__
- case CPU_TYPE_I386: {
- unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
- delete as;
- }
- break;
- case CPU_TYPE_X86_64: {
- unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
- delete as;
- }
- break;
-#endif
- case CPU_TYPE_POWERPC: {
- unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
- delete as;
- }
- break;
- }
-}
-#endif // UNW_REMOTE
-
-
/// Get value of specified register at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_word_t *value) {
@@ -186,8 +102,20 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
co->setReg(regNum, (pint_t)value);
// specical case altering IP to re-find info (being called by personality
// function)
- if (regNum == UNW_REG_IP)
+ if (regNum == UNW_REG_IP) {
+ unw_proc_info_t info;
+ // First, get the FDE for the old location and then update it.
+ co->getInfo(&info);
co->setInfoBasedOnIPRegister(false);
+ // If the original call expects stack adjustment, perform this now.
+ // Normal frame unwinding would have included the offset already in the
+ // CFA computation.
+ // Note: for PA-RISC and other platforms where the stack grows up,
+ // this should actually be - info.gp. LLVM doesn't currently support
+ // any such platforms and Clang doesn't export a macro for them.
+ if (info.gp)
+ co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
+ }
return UNW_ESUCCESS;
}
return UNW_EBADREG;
diff --git a/src/libunwind_ext.h b/src/libunwind_ext.h
index ec645a8..01b58a9 100644
--- a/src/libunwind_ext.h
+++ b/src/libunwind_ext.h
@@ -1,9 +1,8 @@
//===------------------------ libunwind_ext.h -----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//
// Extensions to libunwind API.
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 97917b8..d902e3e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -16,6 +16,7 @@ pythonize_bool(LIBCXX_ENABLE_SHARED)
pythonize_bool(LIBUNWIND_ENABLE_SHARED)
pythonize_bool(LIBUNWIND_ENABLE_THREADS)
pythonize_bool(LIBUNWIND_ENABLE_EXCEPTIONS)
+pythonize_bool(LIBUNWIND_USE_COMPILER_RT)
pythonize_bool(LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY)
set(LIBUNWIND_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
"TargetInfo to use when setting up test environment.")
diff --git a/test/alignment.pass.cpp b/test/alignment.pass.cpp
index 1a3ca5a..b0da7f1 100644
--- a/test/alignment.pass.cpp
+++ b/test/alignment.pass.cpp
@@ -1,10 +1,9 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/test/libunwind/test/config.py b/test/libunwind/test/config.py
index 2a0c828..8034625 100644
--- a/test/libunwind/test/config.py
+++ b/test/libunwind/test/config.py
@@ -1,9 +1,8 @@
#===----------------------------------------------------------------------===##
#
-# The LLVM Compiler Infrastructure
-#
-# This file is dual licensed under the MIT and the University of Illinois Open
-# Source Licenses. See LICENSE.TXT for details.
+# 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
#
#===----------------------------------------------------------------------===##
import os
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index 888b960..34da72a 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -7,21 +7,24 @@ config.abi_library_path = "@LIBUNWIND_LIBRARY_DIR@"
config.libcxx_src_root = "@LIBUNWIND_LIBCXX_PATH@"
config.libunwind_headers = "@LIBUNWIND_SOURCE_DIR@/include"
config.cxx_library_root = "@LIBUNWIND_LIBCXX_LIBRARY_PATH@"
-config.llvm_unwinder = "1"
-config.enable_threads = "@LIBUNWIND_ENABLE_THREADS@"
+config.llvm_unwinder = True
+config.builtins_library = "@LIBUNWIND_BUILTINS_LIBRARY@"
+config.enable_threads = @LIBUNWIND_ENABLE_THREADS@
config.use_sanitizer = "@LLVM_USE_SANITIZER@"
-config.enable_32bit = "@LIBUNWIND_BUILD_32_BITS@"
+config.enable_32bit = @LIBUNWIND_BUILD_32_BITS@
config.target_info = "@LIBUNWIND_TARGET_INFO@"
+config.test_linker_flags = "@LIBUNWIND_TEST_LINKER_FLAGS@"
+config.test_compiler_flags = "@LIBUNWIND_TEST_COMPILER_FLAGS@"
config.executor = "@LIBUNWIND_EXECUTOR@"
-config.libunwind_shared = "@LIBUNWIND_ENABLE_SHARED@"
-config.enable_shared = "@LIBCXX_ENABLE_SHARED@"
-config.enable_exceptions = "@LIBUNWIND_ENABLE_EXCEPTIONS@"
+config.libunwind_shared = @LIBUNWIND_ENABLE_SHARED@
+config.enable_shared = @LIBCXX_ENABLE_SHARED@
+config.enable_exceptions = @LIBUNWIND_ENABLE_EXCEPTIONS@
config.host_triple = "@LLVM_HOST_TRIPLE@"
config.target_triple = "@TARGET_TRIPLE@"
-config.use_target = len("@LIBUNWIND_TARGET_TRIPLE@") > 0
+config.use_target = bool("@LIBUNWIND_TARGET_TRIPLE@")
config.sysroot = "@LIBUNWIND_SYSROOT@"
config.gcc_toolchain = "@LIBUNWIND_GCC_TOOLCHAIN@"
-config.cxx_ext_threads = "@LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY@"
+config.cxx_ext_threads = @LIBUNWIND_BUILD_EXTERNAL_THREAD_LIBRARY@
# Let the main config do the real work.
lit_config.load_config(config, "@LIBUNWIND_SOURCE_DIR@/test/lit.cfg")