summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-05-17 08:10:28 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-05-17 08:10:28 +0000
commita3a975c39cf0610271d65e87e3c031271ce5bbf1 (patch)
treed7ba88d5be2e801eeeca651bbfe09dc19be90603
parentd87c20e3305a253b95e4df0819d43feafc9ad236 (diff)
parent142862f579ddcdd66a679243b8272ed2d504184d (diff)
downloadlibunwind_llvm-oreo-m2-s4-release.tar.gz
release-request-655284b0-7f0b-48b5-b01d-27f48a99f2c0-for-git_oc-mr1-release-4017105 snap-temp-L82600000064873863android-wear-8.1.0_r1android-vts-8.1_r9android-vts-8.1_r8android-vts-8.1_r7android-vts-8.1_r6android-vts-8.1_r5android-vts-8.1_r4android-vts-8.1_r3android-vts-8.1_r14android-vts-8.1_r13android-vts-8.1_r12android-vts-8.1_r11android-vts-8.1_r10android-security-8.1.0_r93android-security-8.1.0_r92android-security-8.1.0_r91android-security-8.1.0_r90android-security-8.1.0_r89android-security-8.1.0_r88android-security-8.1.0_r87android-security-8.1.0_r86android-security-8.1.0_r85android-security-8.1.0_r84android-security-8.1.0_r83android-security-8.1.0_r82android-cts-8.1_r9android-cts-8.1_r8android-cts-8.1_r7android-cts-8.1_r6android-cts-8.1_r5android-cts-8.1_r4android-cts-8.1_r3android-cts-8.1_r25android-cts-8.1_r24android-cts-8.1_r23android-cts-8.1_r22android-cts-8.1_r21android-cts-8.1_r20android-cts-8.1_r2android-cts-8.1_r19android-cts-8.1_r18android-cts-8.1_r17android-cts-8.1_r16android-cts-8.1_r15android-cts-8.1_r14android-cts-8.1_r13android-cts-8.1_r12android-cts-8.1_r11android-cts-8.1_r10android-cts-8.1_r1android-8.1.0_r9android-8.1.0_r81android-8.1.0_r80android-8.1.0_r8android-8.1.0_r79android-8.1.0_r78android-8.1.0_r77android-8.1.0_r76android-8.1.0_r75android-8.1.0_r74android-8.1.0_r73android-8.1.0_r72android-8.1.0_r71android-8.1.0_r70android-8.1.0_r7android-8.1.0_r69android-8.1.0_r68android-8.1.0_r67android-8.1.0_r66android-8.1.0_r65android-8.1.0_r64android-8.1.0_r63android-8.1.0_r62android-8.1.0_r61android-8.1.0_r60android-8.1.0_r6android-8.1.0_r53android-8.1.0_r52android-8.1.0_r51android-8.1.0_r50android-8.1.0_r5android-8.1.0_r48android-8.1.0_r47android-8.1.0_r46android-8.1.0_r45android-8.1.0_r43android-8.1.0_r42android-8.1.0_r41android-8.1.0_r40android-8.1.0_r4android-8.1.0_r39android-8.1.0_r38android-8.1.0_r37android-8.1.0_r36android-8.1.0_r35android-8.1.0_r33android-8.1.0_r32android-8.1.0_r31android-8.1.0_r30android-8.1.0_r3android-8.1.0_r29android-8.1.0_r28android-8.1.0_r27android-8.1.0_r26android-8.1.0_r25android-8.1.0_r23android-8.1.0_r22android-8.1.0_r21android-8.1.0_r20android-8.1.0_r2android-8.1.0_r19android-8.1.0_r18android-8.1.0_r17android-8.1.0_r16android-8.1.0_r15android-8.1.0_r14android-8.1.0_r13android-8.1.0_r12android-8.1.0_r11android-8.1.0_r10android-8.1.0_r1security-oc-mr1-releaseoreo-mr1-wear-releaseoreo-mr1-vts-releaseoreo-mr1-security-releaseoreo-mr1-s1-releaseoreo-mr1-releaseoreo-mr1-cuttlefish-testingoreo-mr1-cts-releaseoreo-m8-releaseoreo-m7-releaseoreo-m6-s4-releaseoreo-m6-s3-releaseoreo-m6-s2-releaseoreo-m5-releaseoreo-m4-s9-releaseoreo-m4-s8-releaseoreo-m4-s7-releaseoreo-m4-s6-releaseoreo-m4-s5-releaseoreo-m4-s4-releaseoreo-m4-s3-releaseoreo-m4-s2-releaseoreo-m4-s12-releaseoreo-m4-s11-releaseoreo-m4-s10-releaseoreo-m4-s1-releaseoreo-m3-releaseoreo-m2-s5-releaseoreo-m2-s4-releaseoreo-m2-s3-releaseoreo-m2-s2-releaseoreo-m2-s1-releaseoreo-m2-release
Change-Id: I3498bddcdd82f82338d6a71f0a1ff13560bbf88b
-rw-r--r--.arcconfig2
-rw-r--r--Android.bp1
-rw-r--r--CMakeLists.txt185
-rw-r--r--LICENSE.TXT76
-rw-r--r--cmake/Modules/HandleCompilerRT.cmake58
-rw-r--r--cmake/config-ix.cmake41
-rw-r--r--docs/BuildingLibunwind.rst167
-rw-r--r--docs/CMakeLists.txt7
-rw-r--r--docs/README.txt13
-rw-r--r--docs/conf.py251
-rw-r--r--docs/index.rst102
-rw-r--r--include/__libunwind_config.h55
-rw-r--r--include/libunwind.h72
-rw-r--r--include/mach-o/compact_unwind_encoding.h32
-rw-r--r--include/unwind.h26
-rw-r--r--src/AddressSpace.hpp204
-rw-r--r--src/CMakeLists.txt62
-rw-r--r--src/CompactUnwinder.hpp15
-rw-r--r--src/DwarfInstructions.hpp11
-rw-r--r--src/DwarfParser.hpp233
-rw-r--r--src/EHHeaderParser.hpp3
-rw-r--r--src/Registers.hpp345
-rw-r--r--src/Unwind-EHABI.cpp221
-rw-r--r--src/Unwind-EHABI.h4
-rw-r--r--src/Unwind-sjlj.c72
-rw-r--r--src/UnwindCursor.hpp117
-rw-r--r--src/UnwindLevel1-gcc-ext.c68
-rw-r--r--src/UnwindLevel1.c150
-rw-r--r--src/UnwindRegistersRestore.S85
-rw-r--r--src/UnwindRegistersSave.S97
-rw-r--r--src/Unwind_AppleExtras.cpp29
-rw-r--r--src/assembly.h16
-rw-r--r--src/config.h169
-rw-r--r--src/libunwind.cpp98
-rw-r--r--src/libunwind_ext.h2
-rw-r--r--test/alignment.pass.cpp21
36 files changed, 2279 insertions, 831 deletions
diff --git a/.arcconfig b/.arcconfig
index ef07b36..97a4bf1 100644
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,4 +1,4 @@
{
"project_id" : "libunwind",
- "conduit_uri" : "http://reviews.llvm.org/"
+ "conduit_uri" : "https://reviews.llvm.org/"
}
diff --git a/Android.bp b/Android.bp
index 841e19d..0e2f170 100644
--- a/Android.bp
+++ b/Android.bp
@@ -39,6 +39,7 @@ LIBUNWIND_CPPFLAGS = [
"-Wextra",
"-Wno-unused-function",
"-Wno-unused-parameter",
+ "-Wno-unused-local-typedef",
"-Werror",
]
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d9b2367..032df56 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,37 +2,46 @@
# Setup Project
#===============================================================================
-cmake_minimum_required(VERSION 2.8.8)
+cmake_minimum_required(VERSION 3.4.3)
if (POLICY CMP0042)
cmake_policy(SET CMP0042 NEW) # Set MACOSX_RPATH=YES by default
endif()
+# Add path for custom modules
+set(CMAKE_MODULE_PATH
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+ ${CMAKE_MODULE_PATH}
+ )
+
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
project(libunwind)
# Rely on llvm-config.
set(CONFIG_OUTPUT)
- find_program(LLVM_CONFIG "llvm-config")
+ if(NOT LLVM_CONFIG_PATH)
+ find_program(LLVM_CONFIG_PATH "llvm-config")
+ endif()
if (DEFINED LLVM_PATH)
set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include")
set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
- elseif (LLVM_CONFIG)
- message(STATUS "Found LLVM_CONFIG as ${LLVM_CONFIG}")
- set(CONFIG_COMMAND ${LLVM_CONFIG} "--includedir" "--prefix" "--src-root")
+ elseif(LLVM_CONFIG_PATH)
+ message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}")
+ set(CONFIG_COMMAND ${LLVM_CONFIG_PATH} "--includedir" "--prefix" "--src-root")
execute_process(COMMAND ${CONFIG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if (NOT HAD_ERROR)
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";"
CONFIG_OUTPUT ${CONFIG_OUTPUT})
- else ()
+ else()
string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}")
message(STATUS "${CONFIG_COMMAND_STR}")
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
- endif ()
+ endif()
list(GET CONFIG_OUTPUT 0 INCLUDE_DIR)
list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT)
@@ -41,34 +50,46 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
- set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/share/llvm/cmake")
set(LLVM_LIT_PATH "${LLVM_PATH}/utils/lit/lit.py")
- else ()
+
+ # --cmakedir is supported since llvm r291218 (4.0 release)
+ execute_process(
+ COMMAND ${LLVM_CONFIG_PATH} --cmakedir
+ RESULT_VARIABLE HAD_ERROR
+ OUTPUT_VARIABLE CONFIG_OUTPUT
+ ERROR_QUIET)
+ if(NOT HAD_ERROR)
+ string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH)
+ else()
+ set(LLVM_CMAKE_PATH
+ "${LLVM_BINARY_DIR}/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.")
- endif ()
+ endif()
if (EXISTS ${LLVM_CMAKE_PATH})
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
include("${LLVM_CMAKE_PATH}/HandleLLVMOptions.cmake")
- else ()
+ else()
message(FATAL_ERROR "Not found: ${LLVM_CMAKE_PATH}")
- endif ()
+ endif()
set(PACKAGE_NAME libunwind)
- set(PACKAGE_VERSION 3.8.0svn)
+ set(PACKAGE_VERSION 5.0.0svn)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
- else ()
+ else()
# Seek installed Lit.
find_program(LLVM_LIT "lit.py" ${LLVM_MAIN_SRC_DIR}/utils/lit
DOC "Path to lit.py")
- endif ()
+ endif()
if (LLVM_LIT)
# Define the default arguments to use with 'lit', and an option for the user
@@ -76,16 +97,16 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(LIT_ARGS_DEFAULT "-sv")
if (MSVC OR XCODE)
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
- endif ()
+ endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
if (WIN32 AND NOT CYGWIN)
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
- endif ()
- else ()
+ endif()
+ else()
set(LLVM_INCLUDE_TESTS OFF)
- endif ()
+ endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
@@ -97,15 +118,37 @@ endif()
#===============================================================================
# Setup CMake Options
#===============================================================================
+include(HandleCompilerRT)
# Define options.
+option(LIBUNWIND_BUILD_32_BITS "Build 32 bit libunwind" ${LLVM_BUILD_32_BITS})
option(LIBUNWIND_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
option(LIBUNWIND_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
option(LIBUNWIND_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
option(LIBUNWIND_ENABLE_SHARED "Build libunwind as a shared library." ON)
+option(LIBUNWIND_ENABLE_STATIC "Build libunwind as a static library." ON)
+option(LIBUNWIND_ENABLE_CROSS_UNWINDING "Enable cross-platform unwinding support." OFF)
+option(LIBUNWIND_ENABLE_ARM_WMMX "Enable unwinding support for ARM WMMX registers." OFF)
+option(LIBUNWIND_ENABLE_THREADS "Build libunwind with threading support." ON)
+option(LIBUNWIND_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
+option(LIBUNWIND_INCLUDE_DOCS "Build the libunwind documentation." ${LLVM_INCLUDE_DOCS})
+
+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.")
+
+if (NOT LIBUNWIND_ENABLE_SHARED AND NOT LIBUNWIND_ENABLE_STATIC)
+ message(FATAL_ERROR "libunwind must be built as either a shared or static library.")
+endif()
-set(LIBUNWIND_GCC_TOOLCHAIN "" CACHE STRING "GCC toolchain for cross compiling.")
-set(LIBUNWIND_SYSROOT "" CACHE STRING "Sysroot for cross compiling.")
+# Check that we can build with 32 bits if requested.
+if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
+ if (LIBUNWIND_BUILD_32_BITS AND NOT LLVM_BUILD_32_BITS) # Don't duplicate the output from LLVM
+ message(STATUS "Building 32 bits executables and libraries.")
+ endif()
+elseif(LIBUNWIND_BUILD_32_BITS)
+ message(FATAL_ERROR "LIBUNWIND_BUILD_32_BITS=ON is not supported on this platform.")
+endif()
#===============================================================================
# Configure System
@@ -116,17 +159,15 @@ set(CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
${CMAKE_MODULE_PATH})
-# Configure compiler.
-include(config-ix)
-
set(LIBUNWIND_COMPILER ${CMAKE_CXX_COMPILER})
set(LIBUNWIND_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBUNWIND_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
-#===============================================================================
-# Setup Compiler Flags
-#===============================================================================
+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)
@@ -135,10 +176,33 @@ macro(append_if list condition var)
endif()
endmacro()
-set(LIBUNWIND_C_FLAGS "")
-set(LIBUNWIND_CXX_FLAGS "")
-set(LIBUNWIND_COMPILE_FLAGS "")
-set(LIBUNWIND_LINK_FLAGS "")
+macro(add_target_flags_if condition var)
+ 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})
+ 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}")
+
+# Configure compiler.
+include(config-ix)
+
+if (LIBUNWIND_USE_COMPILER_RT)
+ list(APPEND LIBUNWIND_LINK_FLAGS "-rtlib=compiler-rt")
+endif()
+
+#===============================================================================
+# Setup Compiler Flags
+#===============================================================================
append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_WERROR_FLAG -Werror=return-type)
@@ -189,30 +253,42 @@ if (LIBUNWIND_ENABLE_ASSERTIONS)
# MSVC doesn't like _DEBUG on release builds. See PR 4379.
if (NOT MSVC)
list(APPEND LIBUNWIND_COMPILE_FLAGS -D_DEBUG)
- endif ()
+ endif()
# On Release builds cmake automatically defines NDEBUG, so we
# explicitly undefine it:
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
list(APPEND LIBUNWIND_COMPILE_FLAGS -UNDEBUG)
- endif ()
+ endif()
else()
if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
list(APPEND LIBUNWIND_COMPILE_FLAGS -DNDEBUG)
- endif ()
-endif ()
+ endif()
+endif()
+
+# Cross-unwinding
+if (NOT LIBUNWIND_ENABLE_CROSS_UNWINDING)
+ list(APPEND LIBUNWIND_COMPILE_FLAGS -D_LIBUNWIND_IS_NATIVE_ONLY)
+endif()
+
+# Threading-support
+if (NOT LIBUNWIND_ENABLE_THREADS)
+ list(APPEND LIBUNWIND_COMPILE_FLAGS -D_LIBUNWIND_HAS_NO_THREADS)
+endif()
+
+# ARM WMMX register support
+if (LIBUNWIND_ENABLE_ARM_WMMX)
+ # __ARM_WMMX is a compiler pre-define (as per the ACLE 2.0). Clang does not
+ # define this macro for any supported target at present. Therefore, here we
+ # provide the option to explicitly enable support for WMMX registers in the
+ # unwinder.
+ list(APPEND LIBUNWIND_COMPILE_FLAGS -D__ARM_WMMX)
+endif()
# This is the _ONLY_ place where add_definitions is called.
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
-endif ()
-
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_TARGET_TRIPLE
- "-target ${LIBUNWIND_TARGET_TRIPLE}")
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_GCC_TOOLCHAIN
- "-gcc-toolchain ${LIBUNWIND_GCC_TOOLCHAIN}")
-append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_SYSROOT
- "--sysroot=${LIBUNWIND_SYSROOT}")
+endif()
#===============================================================================
# Setup Source Code
@@ -220,5 +296,28 @@ append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_SYSROOT
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()
diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 0000000..fb77e1b
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,76 @@
+==============================================================================
+libunwind License
+==============================================================================
+
+The libunwind library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+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
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/cmake/Modules/HandleCompilerRT.cmake b/cmake/Modules/HandleCompilerRT.cmake
new file mode 100644
index 0000000..9bf88bb
--- /dev/null
+++ b/cmake/Modules/HandleCompilerRT.cmake
@@ -0,0 +1,58 @@
+function(find_compiler_rt_library name dest)
+ if (NOT DEFINED LIBUNWIND_COMPILE_FLAGS)
+ message(FATAL_ERROR "LIBUNWIND_COMPILE_FLAGS must be defined when using this function")
+ endif()
+ set(dest "" PARENT_SCOPE)
+ set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
+ "--rtlib=compiler-rt" "--print-libgcc-file-name")
+ if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET)
+ list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}")
+ endif()
+ execute_process(
+ COMMAND ${CLANG_COMMAND}
+ RESULT_VARIABLE HAD_ERROR
+ OUTPUT_VARIABLE LIBRARY_FILE
+ )
+ string(STRIP "${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}")
+ set(${dest} "${LIBRARY_FILE}" PARENT_SCOPE)
+ else()
+ message(STATUS "Failed to find compiler-rt library")
+ endif()
+endfunction()
+
+function(find_compiler_rt_dir dest)
+ if (NOT DEFINED LIBUNWIND_COMPILE_FLAGS)
+ message(FATAL_ERROR "LIBUNWIND_COMPILE_FLAGS must be defined when using this function")
+ endif()
+ set(dest "" PARENT_SCOPE)
+ if (APPLE)
+ set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
+ "-print-file-name=lib")
+ execute_process(
+ COMMAND ${CLANG_COMMAND}
+ RESULT_VARIABLE HAD_ERROR
+ OUTPUT_VARIABLE LIBRARY_DIR
+ )
+ string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR)
+ set(LIBRARY_DIR "${LIBRARY_DIR}/darwin")
+ else()
+ set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBUNWIND_COMPILE_FLAGS}
+ "--rtlib=compiler-rt" "--print-libgcc-file-name")
+ execute_process(
+ COMMAND ${CLANG_COMMAND}
+ RESULT_VARIABLE HAD_ERROR
+ OUTPUT_VARIABLE LIBRARY_FILE
+ )
+ string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
+ get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY)
+ endif()
+ if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}")
+ message(STATUS "Found compiler-rt directory: ${LIBRARY_DIR}")
+ set(${dest} "${LIBRARY_DIR}" PARENT_SCOPE)
+ else()
+ message(STATUS "Failed to find compiler-rt directory")
+ endif()
+endfunction()
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index a36f978..40a5dd1 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -3,13 +3,46 @@ include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
+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)
+endif()
+
+# libunwind is built with -nodefaultlibs, so we want all our checks to also
+# use this option, otherwise we may end up with an inconsistency between
+# the flags we think we require during configuration (if the checks are
+# performed without -nodefaultlibs) and the flags that are actually
+# required during compilation (which has the -nodefaultlibs). libc is
+# required for the link to go through. We remove sanitizers from the
+# configuration checks to avoid spurious link errors.
+check_c_compiler_flag(-nodefaultlibs LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
+if (LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
+ if (LIBUNWIND_HAS_C_LIB)
+ 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)
+ endif ()
+ if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all")
+ endif ()
+ if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters")
+ endif ()
+endif ()
+
# Check compiler flags
check_c_compiler_flag(-funwind-tables LIBUNWIND_HAS_FUNWIND_TABLES)
check_cxx_compiler_flag(-fPIC LIBUNWIND_HAS_FPIC_FLAG)
check_cxx_compiler_flag(-fno-exceptions LIBUNWIND_HAS_NO_EXCEPTIONS_FLAG)
check_cxx_compiler_flag(-fno-rtti LIBUNWIND_HAS_NO_RTTI_FLAG)
check_cxx_compiler_flag(-fstrict-aliasing LIBUNWIND_HAS_FSTRICT_ALIASING_FLAG)
-check_cxx_compiler_flag(-nodefaultlibs LIBUNWIND_HAS_NODEFAULTLIBS_FLAG)
check_cxx_compiler_flag(-nostdinc++ LIBUNWIND_HAS_NOSTDINCXX_FLAG)
check_cxx_compiler_flag(-Wall LIBUNWIND_HAS_WALL_FLAG)
check_cxx_compiler_flag(-W LIBUNWIND_HAS_W_FLAG)
@@ -38,8 +71,12 @@ check_cxx_compiler_flag(/EHsc LIBUNWIND_HAS_EHSC_FLAG)
check_cxx_compiler_flag(/EHs- LIBUNWIND_HAS_NO_EHS_FLAG)
check_cxx_compiler_flag(/EHa- LIBUNWIND_HAS_NO_EHA_FLAG)
check_cxx_compiler_flag(/GR- LIBUNWIND_HAS_NO_GR_FLAG)
+check_cxx_compiler_flag(-std=c++11 LIBUNWIND_HAS_STD_CXX11)
+
+if(LIBUNWIND_HAS_STD_CXX11)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+endif()
-check_library_exists(c printf "" LIBUNWIND_HAS_C_LIB)
check_library_exists(dl dladdr "" LIBUNWIND_HAS_DL_LIB)
check_library_exists(pthread pthread_once "" LIBUNWIND_HAS_PTHREAD_LIB)
diff --git a/docs/BuildingLibunwind.rst b/docs/BuildingLibunwind.rst
new file mode 100644
index 0000000..6aa4556
--- /dev/null
+++ b/docs/BuildingLibunwind.rst
@@ -0,0 +1,167 @@
+.. _BuildingLibunwind:
+
+==================
+Building libunwind
+==================
+
+.. contents::
+ :local:
+
+.. _build instructions:
+
+Getting Started
+===============
+
+On Mac OS, the easiest way to get this library is to link with -lSystem.
+However if you want to build tip-of-trunk from here (getting the bleeding
+edge), read on.
+
+The basic steps needed to build libc++ are:
+
+#. Checkout LLVM:
+
+ * ``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``
+
+#. Configure and build libunwind:
+
+ CMake is the only supported configuration system.
+
+ Clang is the preferred compiler when building and using libunwind.
+
+ * ``cd where you want to build llvm``
+ * ``mkdir build``
+ * ``cd build``
+ * ``cmake -G <generator> [options] <path to llvm sources>``
+
+ For more information about configuring libunwind see :ref:`CMake Options`.
+
+ * ``make unwind`` --- will build libunwind.
+ * ``make check-unwind`` --- will run the test suite.
+
+ Shared and static libraries for libunwind should now be present in llvm/build/lib.
+
+#. **Optional**: Install libunwind
+
+ If your system already provides an unwinder, it is important to be careful
+ not to replace it. Remember Use the CMake option ``CMAKE_INSTALL_PREFIX`` to
+ select a safe place to install libunwind.
+
+ * ``make install-unwind`` --- Will install the libraries and the headers
+
+
+It is sometimes beneficial to build outside of the LLVM tree. An out-of-tree
+build would look like this:
+
+.. code-block:: bash
+
+ $ cd where-you-want-libunwind-to-live
+ $ # Check out llvm, and libunwind
+ $ ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
+ $ ``svn co http://llvm.org/svn/llvm-project/libunwind/trunk libunwind``
+ $ cd where-you-want-to-build
+ $ mkdir build && cd build
+ $ export CC=clang CXX=clang++
+ $ cmake -DLLVM_PATH=path/to/llvm \
+ path/to/libunwind
+ $ make
+
+
+.. _CMake Options:
+
+CMake Options
+=============
+
+Here are some of the CMake variables that are used often, along with a
+brief explanation and LLVM-specific notes. For full documentation, check the
+CMake docs or execute ``cmake --help-variable VARIABLE_NAME``.
+
+**CMAKE_BUILD_TYPE**:STRING
+ Sets the build type for ``make`` based generators. Possible values are
+ Release, Debug, RelWithDebInfo and MinSizeRel. On systems like Visual Studio
+ the user sets the build type with the IDE settings.
+
+**CMAKE_INSTALL_PREFIX**:PATH
+ Path where LLVM will be installed if "make install" is invoked or the
+ "INSTALL" target is built.
+
+**CMAKE_CXX_COMPILER**:STRING
+ The C++ compiler to use when building and testing libunwind.
+
+
+.. _libunwind-specific options:
+
+libunwind specific options
+--------------------------
+
+.. option:: LIBUNWIND_BUILD_32_BITS:BOOL
+
+ **Default**: Same as LLVM_BUILD_32_BITS
+
+ Toggle whether libunwind should be built with -m32.
+
+.. option:: LIBUNWIND_ENABLE_ASSERTIONS:BOOL
+
+ **Default**: ``ON``
+
+ Toggle assertions independent of the build mode.
+
+.. option:: LIBUNWIND_ENABLE_PEDANTIC:BOOL
+
+ **Default**: ``ON``
+
+ Compile with -Wpedantic.
+
+.. option:: LIBUNWIND_ENABLE_WERROR:BOOL
+
+ **Default**: ``ON``
+
+ Compile with -Werror
+
+.. option:: LIBUNWIND_ENABLE_SHARED:BOOL
+
+ **Default**: ``ON``
+
+ Build libunwind as a shared library.
+
+.. option:: LIBUNWIND_ENABLE_STATIC:BOOL
+
+ **Default**: ``ON``
+
+ Build libunwind as a static archive.
+
+.. option:: LIBUNWIND_ENABLE_CROSS_UNWINDING:BOOL
+
+ **Default**: ``OFF``
+
+ Enable cross-platform unwinding support.
+
+.. option:: LIBUNWIND_ENABLE_ARM_WMMX:BOOL
+
+ **Default**: ``OFF``
+
+ Enable unwinding support for ARM WMMX registers.
+
+.. option:: LIBUNWIND_ENABLE_THREADS:BOOL
+
+ **Default**: ``ON``
+
+ Build libunwind with threading support.
+
+.. option:: LIBUNWIND_TARGET_TRIPLE:STRING
+
+ Target triple for cross compiling
+
+.. option:: LIBUNWIND_GCC_TOOLCHAIN:PATH
+
+ GCC toolchain for cross compiling
+
+.. option:: LIBUNWIND_SYSROOT
+
+ Sysroot for cross compiling
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
new file mode 100644
index 0000000..c226f2f
--- /dev/null
+++ b/docs/CMakeLists.txt
@@ -0,0 +1,7 @@
+include(FindSphinx)
+if (SPHINX_FOUND)
+ include(AddSphinxTarget)
+ if (${SPHINX_OUTPUT_HTML})
+ add_sphinx_target(html libunwind)
+ endif()
+endif()
diff --git a/docs/README.txt b/docs/README.txt
new file mode 100644
index 0000000..968982f
--- /dev/null
+++ b/docs/README.txt
@@ -0,0 +1,13 @@
+libunwind Documentation
+====================
+
+The libunwind documentation is written using the Sphinx documentation generator. It is
+currently tested with Sphinx 1.1.3.
+
+To build the documents into html configure libunwind with the following cmake options:
+
+ * -DLLVM_ENABLE_SPHINX=ON
+ * -DLIBUNWIND_INCLUDE_DOCS=ON
+
+After configuring libunwind with these options the make rule `docs-libunwind-html`
+should be available.
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..5a2f070
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,251 @@
+# -*- coding: utf-8 -*-
+#
+# libunwind documentation build configuration file.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'libunwind'
+copyright = u'2011-2017, LLVM Project'
+
+# 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 = '5.0'
+# The full version, including alpha/beta/rc tags.
+release = '5.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%Y-%m-%d'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+show_authors = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'friendly'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'haiku'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'libunwinddoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('contents', 'libunwind.tex', u'libunwind Documentation',
+ u'LLVM project', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('contents', 'libunwind', u'libunwind Documentation',
+ [u'LLVM project'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('contents', 'libunwind', u'libunwind Documentation',
+ u'LLVM project', 'libunwind', 'LLVM Unwinder',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# FIXME: Define intersphinx configration.
+intersphinx_mapping = {}
+
+
+# -- Options for extensions ----------------------------------------------------
+
+# Enable this if you want TODOs to show up in the generated documentation.
+todo_include_todos = True
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..7e0b600
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,102 @@
+.. _index:
+
+=======================
+libunwind LLVM Unwinder
+=======================
+
+Overview
+========
+
+libunwind is an implementation of the interface defined by the HP libunwind
+project. It was contributed by Apple as a way to enable clang++ to port to
+platforms that do not have a system unwinder. It is intended to be a small and
+fast implementation of the ABI, leaving off some features of HP's libunwind
+that never materialized (e.g. remote unwinding).
+
+The unwinder has two levels of API. The high level APIs are the `_Unwind_*`
+functions which implement functionality required by `__cxa_*` exception
+funcionts. The low level APIs are the `unw_*` functions which are an interface
+defined by the old HP libunwind project.
+
+Getting Started with libunwind
+------------------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ BuildingLibunwind
+
+Current Status
+--------------
+
+libunwind is a production-quality unwinder, with platform support for DWARF
+unwind info, SjLj, and ARM EHABI.
+
+The low level libunwind API was designed to work either in-process (aka local)
+or to operate on another process (aka remote), but only the local path has been
+implemented. Remote unwinding remains as future work.
+
+Platform and Compiler Support
+-----------------------------
+
+libunwind is known to work on the following platforms:
+
+============ ==================== ============ ========================
+OS Arch Compilers Unwind Info
+============ ==================== ============ ========================
+Mac OS X i386, x86_64 Clang, GCC DWARF CFI
+iOS ARM Clang SjLj
+Linux i386, x86_64 Clang, GCC DWARF CFI
+Linux ARM Clang, GCC EHABI
+Bare Metal ARM Clang, GCC EHABI
+NetBSD x86_64 Clang, GCC DWARF CFI
+============ ==================== ============ ========================
+
+The following minimum compiler versions are strongly recommended.
+
+* Clang 3.5 and above
+* GCC 4.7 and above.
+
+Anything older *may* work.
+
+Notes and Known Issues
+----------------------
+
+* TODO
+
+
+Getting Involved
+================
+
+First please review our `Developer's Policy <http://llvm.org/docs/DeveloperPolicy.html>`__
+and `Getting started with LLVM <http://llvm.org/docs/GettingStarted.html>`__.
+
+**Bug Reports**
+
+If you think you've found a bug in libunwind, please report it using
+the `LLVM Bugzilla`_. If you're not sure, you
+can post a message to the `cfe-dev mailing list`_ or on IRC.
+Please include "libunwind" in your subject.
+
+**Patches**
+
+If you want to contribute a patch to libunwind, the best place for that is
+`Phabricator <http://llvm.org/docs/Phabricator.html>`_. Please include [libunwind] in the subject and
+add `cfe-commits` as a subscriber. Also make sure you are subscribed to the
+`cfe-commits mailing list <http://lists.llvm.org/mailman/listinfo/cfe-commits>`_.
+
+**Discussion and Questions**
+
+Send discussions and questions to the
+`cfe-dev mailing list <http://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
+Please include [libunwind] in the subject.
+
+
+Quick Links
+===========
+* `LLVM Homepage <http://llvm.org/>`_
+* `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/>`_
diff --git a/include/__libunwind_config.h b/include/__libunwind_config.h
index 63393d3..83f4f47 100644
--- a/include/__libunwind_config.h
+++ b/include/__libunwind_config.h
@@ -12,9 +12,58 @@
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
!defined(__ARM_DWARF_EH__)
-#define _LIBUNWIND_ARM_EHABI 1
-#else
-#define _LIBUNWIND_ARM_EHABI 0
+#define _LIBUNWIND_ARM_EHABI
#endif
+#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
+# if defined(__i386__)
+# define _LIBUNWIND_TARGET_I386
+# define _LIBUNWIND_CONTEXT_SIZE 8
+# define _LIBUNWIND_CURSOR_SIZE 19
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 9
+# elif defined(__x86_64__)
+# define _LIBUNWIND_TARGET_X86_64 1
+# define _LIBUNWIND_CONTEXT_SIZE 21
+# define _LIBUNWIND_CURSOR_SIZE 33
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 17
+# elif defined(__ppc__)
+# define _LIBUNWIND_TARGET_PPC 1
+# define _LIBUNWIND_CONTEXT_SIZE 117
+# define _LIBUNWIND_CURSOR_SIZE 128
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 113
+# elif defined(__aarch64__)
+# define _LIBUNWIND_TARGET_AARCH64 1
+# define _LIBUNWIND_CONTEXT_SIZE 66
+# define _LIBUNWIND_CURSOR_SIZE 78
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 96
+# elif defined(__arm__)
+# define _LIBUNWIND_TARGET_ARM 1
+# if defined(__ARM_WMMX)
+# define _LIBUNWIND_CONTEXT_SIZE 60
+# define _LIBUNWIND_CURSOR_SIZE 67
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 42
+# define _LIBUNWIND_CURSOR_SIZE 49
+# endif
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 96
+# elif defined(__or1k__)
+# define _LIBUNWIND_TARGET_OR1K 1
+# define _LIBUNWIND_CONTEXT_SIZE 16
+# define _LIBUNWIND_CURSOR_SIZE 28
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 32
+# else
+# error "Unsupported architecture."
+# endif
+#else // !_LIBUNWIND_IS_NATIVE_ONLY
+# define _LIBUNWIND_TARGET_I386
+# define _LIBUNWIND_TARGET_X86_64 1
+# define _LIBUNWIND_TARGET_PPC 1
+# define _LIBUNWIND_TARGET_AARCH64 1
+# define _LIBUNWIND_TARGET_ARM 1
+# define _LIBUNWIND_TARGET_OR1K 1
+# define _LIBUNWIND_CONTEXT_SIZE 128
+# define _LIBUNWIND_CURSOR_SIZE 140
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 120
+#endif // _LIBUNWIND_IS_NATIVE_ONLY
+
#endif // ____LIBUNWIND_CONFIG_H__
diff --git a/include/libunwind.h b/include/libunwind.h
index 4a75a7b..cd09037 100644
--- a/include/libunwind.h
+++ b/include/libunwind.h
@@ -6,7 +6,7 @@
// Source Licenses. See LICENSE.TXT for details.
//
//
-// Compatible with libuwind API documented at:
+// Compatible with libunwind API documented at:
// http://www.nongnu.org/libunwind/man/libunwind(3).html
//
//===----------------------------------------------------------------------===//
@@ -20,12 +20,26 @@
#include <stddef.h>
#ifdef __APPLE__
- #include <Availability.h>
- #ifdef __arm__
- #define LIBUNWIND_AVAIL __attribute__((unavailable))
+ #if __clang__
+ #if __has_include(<Availability.h>)
+ #include <Availability.h>
+ #endif
+ #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
+ #include <Availability.h>
+ #endif
+
+ #ifdef __arm__
+ #define LIBUNWIND_AVAIL __attribute__((unavailable))
+ #elif defined(__OSX_AVAILABLE_STARTING)
+ #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0)
+ #else
+ #include <AvailabilityMacros.h>
+ #ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+ #define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
#else
- #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0)
+ #define LIBUNWIND_AVAIL __attribute__((unavailable))
#endif
+ #endif
#else
#define LIBUNWIND_AVAIL
#endif
@@ -46,19 +60,19 @@ enum {
};
struct unw_context_t {
- uint64_t data[128];
+ uint64_t data[_LIBUNWIND_CONTEXT_SIZE];
};
typedef struct unw_context_t unw_context_t;
struct unw_cursor_t {
- uint64_t data[140];
+ uint64_t data[_LIBUNWIND_CURSOR_SIZE];
};
typedef struct unw_cursor_t unw_cursor_t;
typedef struct unw_addr_space *unw_addr_space_t;
typedef int unw_regnum_t;
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
typedef uint32_t unw_word_t;
typedef uint64_t unw_fpreg_t;
#else
@@ -75,8 +89,8 @@ struct unw_proc_info_t {
unw_word_t gp; /* not used */
unw_word_t flags; /* not used */
uint32_t format; /* compact unwind encoding, or zero if none */
- uint32_t unwind_info_size; /* size of dwarf unwind info, or zero if none */
- unw_word_t unwind_info; /* address of dwarf unwind info, or zero */
+ uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
+ unw_word_t unwind_info; /* address of DWARF unwind info, or zero */
unw_word_t extra; /* mach_header of mach-o image containing func */
};
typedef struct unw_proc_info_t unw_proc_info_t;
@@ -120,7 +134,7 @@ extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *);
#endif /* UNW_REMOTE */
/*
- * traditional libuwind "remote" API
+ * traditional libunwind "remote" API
* NOT IMPLEMENTED on Mac OS X
*
* extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t,
@@ -497,4 +511,40 @@ enum {
// 8192-16383 -- Unspecified vendor co-processor register.
};
+// OpenRISC1000 register numbers
+enum {
+ UNW_OR1K_R0 = 0,
+ UNW_OR1K_R1 = 1,
+ UNW_OR1K_R2 = 2,
+ UNW_OR1K_R3 = 3,
+ UNW_OR1K_R4 = 4,
+ UNW_OR1K_R5 = 5,
+ UNW_OR1K_R6 = 6,
+ UNW_OR1K_R7 = 7,
+ UNW_OR1K_R8 = 8,
+ UNW_OR1K_R9 = 9,
+ UNW_OR1K_R10 = 10,
+ UNW_OR1K_R11 = 11,
+ UNW_OR1K_R12 = 12,
+ UNW_OR1K_R13 = 13,
+ UNW_OR1K_R14 = 14,
+ UNW_OR1K_R15 = 15,
+ UNW_OR1K_R16 = 16,
+ UNW_OR1K_R17 = 17,
+ UNW_OR1K_R18 = 18,
+ UNW_OR1K_R19 = 19,
+ UNW_OR1K_R20 = 20,
+ UNW_OR1K_R21 = 21,
+ UNW_OR1K_R22 = 22,
+ UNW_OR1K_R23 = 23,
+ UNW_OR1K_R24 = 24,
+ UNW_OR1K_R25 = 25,
+ UNW_OR1K_R26 = 26,
+ UNW_OR1K_R27 = 27,
+ UNW_OR1K_R28 = 28,
+ UNW_OR1K_R29 = 29,
+ UNW_OR1K_R30 = 30,
+ UNW_OR1K_R31 = 31,
+};
+
#endif
diff --git a/include/mach-o/compact_unwind_encoding.h b/include/mach-o/compact_unwind_encoding.h
index b71c2c8..de14fd5 100644
--- a/include/mach-o/compact_unwind_encoding.h
+++ b/include/mach-o/compact_unwind_encoding.h
@@ -6,7 +6,7 @@
// Source Licenses. See LICENSE.TXT for details.
//
//
-// Darwin's alternative to dwarf based unwind encodings.
+// Darwin's alternative to DWARF based unwind encodings.
//
//===----------------------------------------------------------------------===//
@@ -17,7 +17,7 @@
#include <stdint.h>
//
-// Compilers can emit standard Dwarf FDEs in the __TEXT,__eh_frame section
+// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
// of object files. Or compilers can emit compact unwind information in
// the __LD,__compact_unwind section.
//
@@ -26,10 +26,10 @@
// runtime to access unwind info for any given function. If the compiler
// emitted compact unwind info for the function, that compact unwind info will
// be encoded in the __TEXT,__unwind_info section. If the compiler emitted
-// dwarf unwind info, the __TEXT,__unwind_info section will contain the offset
+// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
// of the FDE in the __TEXT,__eh_frame section in the final linked image.
//
-// Note: Previously, the linker would transform some dwarf unwind infos into
+// Note: Previously, the linker would transform some DWARF unwind infos into
// compact unwind info. But that is fragile and no longer done.
@@ -58,7 +58,7 @@ enum {
// 1-bit: has lsda
// 2-bit: personality index
//
-// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf
+// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
// ebp based:
// 15-bits (5*3-bits per reg) register permutation
// 8-bits for stack offset
@@ -128,9 +128,9 @@ enum {
// UNWIND_X86_FRAMELESS_STACK_SIZE.
// UNWIND_X86_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
-// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
+// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
-// linker in final linked images which have only dwarf unwind info for a
+// linker in final linked images which have only DWARF unwind info for a
// function.
//
// The permutation encoding is a Lehmer code sequence encoded into a
@@ -193,7 +193,7 @@ enum {
// 1-bit: has lsda
// 2-bit: personality index
//
-// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf
+// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
// rbp based:
// 15-bits (5*3-bits per reg) register permutation
// 8-bits for stack offset
@@ -262,9 +262,9 @@ enum {
// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
// UNWIND_X86_64_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
-// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
+// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
-// linker in final linked images which have only dwarf unwind info for a
+// linker in final linked images which have only DWARF unwind info for a
// function.
//
@@ -275,14 +275,14 @@ enum {
// 1-bit: has lsda
// 2-bit: personality index
//
-// 4-bits: 4=frame-based, 3=dwarf, 2=frameless
+// 4-bits: 4=frame-based, 3=DWARF, 2=frameless
// frameless:
// 12-bits of stack size
// frame-based:
// 4-bits D reg pairs saved
// 5-bits X reg pairs saved
-// dwarf:
-// 24-bits offset of dwarf FDE in __eh_frame section
+// DWARF:
+// 24-bits offset of DWARF FDE in __eh_frame section
//
enum {
UNWIND_ARM64_MODE_MASK = 0x0F000000,
@@ -320,9 +320,9 @@ enum {
// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
// UNWIND_ARM64_MODE_DWARF:
// No compact unwind encoding is available. Instead the low 24-bits of the
-// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
+// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
// This mode is never used in object files. It is only generated by the
-// linker in final linked images which have only dwarf unwind info for a
+// linker in final linked images which have only DWARF unwind info for a
// function.
//
@@ -385,7 +385,7 @@ enum {
// saved at that range of the function.
//
// If a particular function is so wacky that there is no compact unwind way
-// to encode it, then the compiler can emit traditional dwarf unwind info.
+// to encode it, then the compiler can emit traditional DWARF unwind info.
// The runtime will use which ever is available.
//
// Runtime support for compact unwind encodings are only available on 10.6
diff --git a/include/unwind.h b/include/unwind.h
index 94880bf..fc7d122 100644
--- a/include/unwind.h
+++ b/include/unwind.h
@@ -36,7 +36,7 @@ typedef enum {
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8,
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
_URC_FAILURE = 9
#endif
} _Unwind_Reason_Code;
@@ -51,12 +51,13 @@ typedef enum {
typedef struct _Unwind_Context _Unwind_Context; // opaque
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
typedef uint32_t _Unwind_State;
static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
+static const _Unwind_State _US_ACTION_MASK = 3;
/* Undocumented flag for force unwinding. */
static const _Unwind_State _US_FORCE_UNWIND = 8;
@@ -122,13 +123,16 @@ struct _Unwind_Exception {
uintptr_t private_1; // non-zero means forced unwind
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
#ifndef __LP64__
- // The gcc implementation of _Unwind_Exception used attribute mode on the
- // above fields which had the side effect of causing this whole struct to
+ // 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.
uint32_t reserved[3];
#endif
-};
+ // The Itanium ABI requires that _Unwind_Exception objects are "double-word
+ // aligned". GCC has interpreted this to mean "use the maximum useful
+ // alignment for the target"; so do we.
+} __attribute__((__aligned__));
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
(int version,
@@ -164,7 +168,7 @@ extern void _Unwind_Resume(_Unwind_Exception *exception_object);
#endif
extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
typedef enum {
_UVRSC_CORE = 0, /* integer register */
_UVRSC_VFP = 1, /* vfp */
@@ -204,7 +208,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
_Unwind_VRS_DataRepresentation representation);
#endif
-#if !_LIBUNWIND_ARM_EHABI
+#if !defined(_LIBUNWIND_ARM_EHABI)
extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
@@ -212,7 +216,7 @@ extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
-#else // _LIBUNWIND_ARM_EHABI
+#else // defined(_LIBUNWIND_ARM_EHABI)
#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
@@ -251,7 +255,7 @@ void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
_Unwind_SetGR(context, 15, value | thumb_bit);
}
-#endif // _LIBUNWIND_ARM_EHABI
+#endif // defined(_LIBUNWIND_ARM_EHABI)
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
extern uintptr_t
@@ -321,7 +325,7 @@ extern void __deregister_frame(const void *fde);
// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has
// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind
-// info" which the runtime uses in preference to dwarf unwind info. This
+// info" which the runtime uses in preference to DWARF unwind info. This
// function will only work if the target function has an FDE but no compact
// unwind info.
struct dwarf_eh_bases {
@@ -334,7 +338,7 @@ extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
// This function attempts to find the start (address of first instruction) of
// a function given an address inside the function. It only works if the
-// function has an FDE (dwarf unwind info).
+// function has an FDE (DWARF unwind info).
// This function is unimplemented on Mac OS X 10.6 and later. Instead, use
// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result.
extern void *_Unwind_FindEnclosingFunction(void *pc);
diff --git a/src/AddressSpace.hpp b/src/AddressSpace.hpp
index 567cbda..402cfe0 100644
--- a/src/AddressSpace.hpp
+++ b/src/AddressSpace.hpp
@@ -32,67 +32,31 @@ namespace libunwind {
#include "libunwind.h"
#include "config.h"
#include "dwarf2.h"
-#include "Registers.hpp"
-
-#if _LIBUNWIND_ARM_EHABI
-#ifdef __linux__
-
-typedef long unsigned int *_Unwind_Ptr;
-extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len);
-
-// Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system.
-#define dl_unwind_find_exidx __gnu_Unwind_Find_exidx
-
-#elif !defined(_LIBUNWIND_IS_BAREMETAL)
-#include <link.h>
-#else // !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.
-struct EHTEntry {
- uint32_t functionOffset;
- uint32_t unwindOpcodes;
-};
-extern EHTEntry __exidx_start;
-extern EHTEntry __exidx_end;
-#endif // !defined(_LIBUNWIND_IS_BAREMETAL)
-#endif // _LIBUNWIND_ARM_EHABI
-
-#if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__)
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX
-#include <link.h>
-// Macro for machine-independent access to the ELF program headers. This
-// macro is not available on some systems (e.g., FreeBSD). On these
-// systems the data structures are just called Elf_XXX. Define ElfW()
-// locally.
-#if !defined(ElfW)
-#define ElfW(type) Elf_##type
-#endif
#include "EHHeaderParser.hpp"
-#endif
-#endif
+#include "Registers.hpp"
namespace libunwind {
/// Used by findUnwindSections() to return info about needed sections.
struct UnwindInfoSections {
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND || _LIBUNWIND_SUPPORT_DWARF_INDEX || \
- _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
+ defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
// No dso_base for ARM EHABI.
uintptr_t dso_base;
#endif
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
uintptr_t dwarf_section;
uintptr_t dwarf_section_length;
#endif
-#if _LIBUNWIND_SUPPORT_DWARF_INDEX
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
uintptr_t dwarf_index_section;
uintptr_t dwarf_index_section_length;
#endif
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
uintptr_t compact_unwind_section;
uintptr_t compact_unwind_section_length;
#endif
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
uintptr_t arm_section;
uintptr_t arm_section_length;
#endif
@@ -302,6 +266,7 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
}
#ifdef __APPLE__
+
struct dyld_unwind_sections
{
const struct mach_header* mh;
@@ -316,31 +281,57 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
// In 10.7.0 or later, libSystem.dylib implements this function.
extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
#else
- // In 10.6.x and earlier, we need to implement this functionality.
+ // In 10.6.x and earlier, we need to implement this functionality. Note
+ // that this requires a newer version of libmacho (from cctools) than is
+ // present in libSystem on 10.6.x (for getsectiondata).
static inline bool _dyld_find_unwind_sections(void* addr,
dyld_unwind_sections* info) {
// Find mach-o image containing address.
Dl_info dlinfo;
if (!dladdr(addr, &dlinfo))
return false;
- const mach_header *mh = (const mach_header *)dlinfo.dli_saddr;
-
- // Find dwarf unwind section in that image.
- unsigned long size;
- const uint8_t *p = getsectiondata(mh, "__TEXT", "__eh_frame", &size);
- if (!p)
- return false;
-
- // Fill in return struct.
- info->mh = mh;
- info->dwarf_section = p;
- info->dwarf_section_length = size;
- info->compact_unwind_section = 0;
- info->compact_unwind_section_length = 0;
-
+#if __LP64__
+ const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
+#else
+ const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
+#endif
+
+ // Initialize the return struct
+ info->mh = (const struct mach_header *)mh;
+ info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
+ info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
+
+ if (!info->dwarf_section) {
+ info->dwarf_section_length = 0;
+ }
+
+ if (!info->compact_unwind_section) {
+ info->compact_unwind_section_length = 0;
+ }
+
return true;
}
#endif
+
+#elif defined(_LIBUNWIND_ARM_EHABI) && 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.
+extern char __exidx_start;
+extern char __exidx_end;
+
+#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+
+// ELF-based systems may use dl_iterate_phdr() to access sections
+// containing unwinding information. The ElfW() macro for pointer-size
+// independent ELF header traversal is not provided by <link.h> on some
+// systems (e.g., FreeBSD). On these systems the data structures are
+// just called Elf_XXX. Define ElfW() locally.
+#include <link.h>
+#if !defined(ElfW)
+#define ElfW(type) Elf_##type
+#endif
+
#endif
inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
@@ -349,7 +340,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
dyld_unwind_sections dyldInfo;
if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
info.dso_base = (uintptr_t)dyldInfo.mh;
- #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
info.dwarf_section_length = dyldInfo.dwarf_section_length;
#endif
@@ -357,23 +348,15 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
return true;
}
-#elif _LIBUNWIND_ARM_EHABI
- #ifdef _LIBUNWIND_IS_BAREMETAL
+#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);
- #else
- int length = 0;
- info.arm_section = (uintptr_t) dl_unwind_find_exidx(
- (_Unwind_Ptr) targetAddr, &length);
- info.arm_section_length = (uintptr_t)length;
- #endif
- _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x\n",
+ _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
info.arm_section, info.arm_section_length);
if (info.arm_section && info.arm_section_length)
return true;
-#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND
-#if _LIBUNWIND_SUPPORT_DWARF_INDEX
+#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
struct dl_iterate_cb_data {
LocalAddressSpace *addressSpace;
UnwindInfoSections *sects;
@@ -384,7 +367,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
int found = dl_iterate_phdr(
[](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
auto cbdata = static_cast<dl_iterate_cb_data *>(data);
- size_t object_length;
bool found_obj = false;
bool found_hdr = false;
@@ -401,11 +383,32 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
#if !defined(Elf_Phdr)
typedef ElfW(Phdr) Elf_Phdr;
#endif
+#if !defined(Elf_Addr) && defined(__ANDROID__)
+ typedef ElfW(Addr) Elf_Addr;
+#endif
+
+ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+ #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+ #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
+ #endif
+ size_t object_length;
+#if defined(__ANDROID__)
+ Elf_Addr image_base =
+ pinfo->dlpi_phnum
+ ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
+ reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
+ ->p_offset
+ : 0;
+#endif
for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
if (phdr->p_type == PT_LOAD) {
uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
+#if defined(__ANDROID__)
+ if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
+ begin = begin + image_base;
+#endif
uintptr_t end = begin + phdr->p_memsz;
if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
cbdata->sects->dso_base = begin;
@@ -415,6 +418,10 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
} else if (phdr->p_type == PT_GNU_EH_FRAME) {
EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
+#if defined(__ANDROID__)
+ if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
+ eh_frame_hdr_start = eh_frame_hdr_start + image_base;
+#endif
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
@@ -431,12 +438,26 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
} else {
return false;
}
+ #else // defined(_LIBUNWIND_ARM_EHABI)
+ for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
+ const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
+ if (phdr->p_type == PT_LOAD) {
+ uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
+ uintptr_t end = begin + phdr->p_memsz;
+ if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
+ found_obj = true;
+ } else if (phdr->p_type == PT_ARM_EXIDX) {
+ uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
+ cbdata->sects->arm_section = exidx_start;
+ cbdata->sects->arm_section_length = phdr->p_memsz;
+ found_hdr = true;
+ }
+ }
+ return found_obj && found_hdr;
+ #endif
},
&cb_data);
return static_cast<bool>(found);
-#else
-#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
-#endif
#endif
return false;
@@ -474,14 +495,14 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
#ifdef UNW_REMOTE
-/// OtherAddressSpace is used as a template parameter to UnwindCursor when
+/// 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 OtherAddressSpace {
+class RemoteAddressSpace {
public:
- OtherAddressSpace(task_t task) : fTask(task) {}
+ RemoteAddressSpace(task_t task) : fTask(task) {}
typedef typename P::uint_t pint_t;
@@ -504,29 +525,29 @@ private:
task_t fTask;
};
-template <typename P> uint8_t OtherAddressSpace<P>::get8(pint_t addr) {
+template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
return *((uint8_t *)localCopy(addr));
}
-template <typename P> uint16_t OtherAddressSpace<P>::get16(pint_t 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 OtherAddressSpace<P>::get32(pint_t 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 OtherAddressSpace<P>::get64(pint_t 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 OtherAddressSpace<P>::getP(pint_t addr) {
+typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
return P::getP(*(uint64_t *)localCopy(addr));
}
template <typename P>
-uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
+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;
@@ -536,7 +557,7 @@ uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
}
template <typename P>
-int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
+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;
@@ -545,13 +566,14 @@ int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
return result;
}
-template <typename P> void *OtherAddressSpace<P>::localCopy(pint_t addr) {
+template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
// FIX ME
}
template <typename P>
-bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
- size_t bufLen, unw_word_t *offset) {
+bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
+ size_t bufLen,
+ unw_word_t *offset) {
// FIX ME
}
@@ -567,7 +589,7 @@ struct unw_addr_space {
/// a 32-bit intel process.
struct unw_addr_space_i386 : public unw_addr_space {
unw_addr_space_i386(task_t task) : oas(task) {}
- OtherAddressSpace<Pointer32<LittleEndian> > oas;
+ RemoteAddressSpace<Pointer32<LittleEndian>> oas;
};
/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
@@ -575,7 +597,7 @@ struct unw_addr_space_i386 : public unw_addr_space {
/// 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) {}
- OtherAddressSpace<Pointer64<LittleEndian> > oas;
+ RemoteAddressSpace<Pointer64<LittleEndian>> oas;
};
/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
@@ -583,7 +605,7 @@ struct unw_addr_space_x86_64 : public unw_addr_space {
/// a 32-bit PowerPC process.
struct unw_addr_space_ppc : public unw_addr_space {
unw_addr_space_ppc(task_t task) : oas(task) {}
- OtherAddressSpace<Pointer32<BigEndian> > oas;
+ RemoteAddressSpace<Pointer32<BigEndian>> oas;
};
#endif // UNW_REMOTE
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ee01e9a..0c78523 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -49,19 +49,13 @@ set(LIBUNWIND_SOURCES
${LIBUNWIND_C_SOURCES}
${LIBUNWIND_ASM_SOURCES})
-if (LIBUNWIND_ENABLE_SHARED)
- add_library(unwind SHARED ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
-else()
- add_library(unwind STATIC ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
-endif ()
-
# Generate library list.
set(libraries ${LIBUNWINDCXX_ABI_LIBRARIES})
append_if(libraries LIBUNWIND_HAS_C_LIB c)
append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
-append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
-
-target_link_libraries(unwind ${libraries})
+if (LIBUNWIND_ENABLE_THREADS)
+ append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
+endif()
# Setup flags.
append_if(LIBUNWIND_COMPILE_FLAGS LIBUNWIND_HAS_FPIC_FLAG -fPIC)
@@ -94,19 +88,51 @@ endif ()
string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}")
string(REPLACE ";" " " LIBUNWIND_CXX_FLAGS "${LIBUNWIND_CXX_FLAGS}")
+string(REPLACE ";" " " LIBUNWIND_C_FLAGS "${LIBUNWIND_C_FLAGS}")
string(REPLACE ";" " " LIBUNWIND_LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}")
-set_target_properties(unwind
- PROPERTIES
- COMPILE_FLAGS "${CMAKE_COMPILE_FLAGS} ${LIBUNWIND_COMPILE_FLAGS}"
- LINK_FLAGS "${CMAKE_LINK_FLAGS} ${LIBUNWIND_LINK_FLAGS}"
- OUTPUT_NAME "unwind"
- VERSION "1.0"
- SOVERSION "1")
set_property(SOURCE ${LIBUNWIND_CXX_SOURCES}
- APPEND_STRING PROPERTY COMPILE_FLAGS "${LIBUNWIND_CXX_FLAGS}")
+ APPEND_STRING PROPERTY COMPILE_FLAGS " ${CMAKE_CXX_FLAGS} ${LIBUNWIND_CXX_FLAGS}")
+set_property(SOURCE ${LIBUNWIND_C_SOURCES}
+ APPEND_STRING PROPERTY COMPILE_FLAGS " ${CMAKE_C_FLAGS} ${LIBUNWIND_C_FLAGS}")
+
+# Add a object library that contains the compiled source files.
+add_library(unwind_objects OBJECT ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS})
+
+set_target_properties(unwind_objects
+ PROPERTIES
+ COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}")
+
+set(LIBUNWIND_TARGETS)
+
+# Build the shared library.
+if (LIBUNWIND_ENABLE_SHARED)
+ add_library(unwind_shared SHARED $<TARGET_OBJECTS:unwind_objects>)
+ target_link_libraries(unwind_shared ${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")
+endif()
+
+# Build the static library.
+if (LIBUNWIND_ENABLE_STATIC)
+ add_library(unwind_static STATIC $<TARGET_OBJECTS:unwind_objects>)
+ target_link_libraries(unwind_static ${libraries})
+ set_target_properties(unwind_static
+ PROPERTIES
+ LINK_FLAGS "${LIBUNWIND_LINK_FLAGS}"
+ OUTPUT_NAME "unwind")
+ list(APPEND LIBUNWIND_TARGETS "unwind_static")
+endif()
+
+# Add a meta-target for both libraries.
+add_custom_target(unwind DEPENDS ${LIBUNWIND_TARGETS})
-install(TARGETS unwind
+install(TARGETS ${LIBUNWIND_TARGETS}
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
diff --git a/src/CompactUnwinder.hpp b/src/CompactUnwinder.hpp
index cd9ce3e..7b97bf8 100644
--- a/src/CompactUnwinder.hpp
+++ b/src/CompactUnwinder.hpp
@@ -19,7 +19,6 @@
#include <libunwind.h>
#include <mach-o/compact_unwind_encoding.h>
-#include "AddressSpace.hpp"
#include "Registers.hpp"
#define EXTRACT_BITS(value, mask) \
@@ -27,6 +26,7 @@
namespace libunwind {
+#if defined(_LIBUNWIND_TARGET_I386)
/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_x86 register set
template <typename A>
@@ -104,7 +104,7 @@ int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(
default:
(void)functionStart;
_LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for "
- "function starting at 0x%X\n",
+ "function starting at 0x%X",
compactEncoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
@@ -223,7 +223,7 @@ int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
- "function starting at 0x%X\n",
+ "function starting at 0x%X",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
@@ -255,8 +255,10 @@ void CompactUnwinder_x86<A>::framelessUnwind(
// old esp is before return address
registers.setSP((uint32_t)returnAddressLocation + 4);
}
+#endif // _LIBUNWIND_TARGET_I386
+#if defined(_LIBUNWIND_TARGET_X86_64)
/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_x86_64 register set
template <typename A>
@@ -333,7 +335,7 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
default:
(void)functionStart;
_LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for "
- "function starting at 0x%llX\n",
+ "function starting at 0x%llX",
compactEncoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
@@ -452,7 +454,7 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
- "function starting at 0x%llX\n",
+ "function starting at 0x%llX",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
@@ -484,9 +486,11 @@ void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace,
// old esp is before return address
registers.setSP(returnAddressLocation + 8);
}
+#endif // _LIBUNWIND_TARGET_X86_64
+#if defined(_LIBUNWIND_TARGET_AARCH64)
/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka
/// unwind) by modifying a Registers_arm64 register set
template <typename A>
@@ -686,6 +690,7 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
return UNW_STEP_SUCCESS;
}
+#endif // _LIBUNWIND_TARGET_AARCH64
} // namespace libunwind
diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index ce90aa0..a428633 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -6,7 +6,7 @@
// Source Licenses. See LICENSE.TXT for details.
//
//
-// Processor specific interpretation of dwarf unwind info.
+// Processor specific interpretation of DWARF unwind info.
//
//===----------------------------------------------------------------------===//
@@ -18,7 +18,6 @@
#include <stdlib.h>
#include "dwarf2.h"
-#include "AddressSpace.hpp"
#include "Registers.hpp"
#include "DwarfParser.hpp"
#include "config.h"
@@ -27,7 +26,7 @@
namespace libunwind {
-/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
+/// DwarfInstructions maps abtract DWARF unwind instructions to a particular
/// architecture
template <typename A, typename R>
class DwarfInstructions {
@@ -164,7 +163,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
// get pointer to cfa (architecture specific)
pint_t cfa = getCFA(addressSpace, prolog, registers);
- // restore registers that dwarf says were saved
+ // restore registers that DWARF says were saved
R newRegisters = registers;
pint_t returnAddress = 0;
const int lastReg = R::lastDwarfRegNum();
@@ -480,7 +479,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
case DW_OP_plus_uconst:
// pop stack, add uelb128 constant, push result
- *sp += addressSpace.getULEB128(p, expressionEnd);
+ *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
if (log)
fprintf(stderr, "add constant\n");
break;
@@ -744,7 +743,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
case DW_OP_call4:
case DW_OP_call_ref:
default:
- _LIBUNWIND_ABORT("dwarf opcode not implemented");
+ _LIBUNWIND_ABORT("DWARF opcode not implemented");
}
}
diff --git a/src/DwarfParser.hpp b/src/DwarfParser.hpp
index f6ef738..3c98d30 100644
--- a/src/DwarfParser.hpp
+++ b/src/DwarfParser.hpp
@@ -17,18 +17,17 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-
-#include <vector>
+#include <limits>
#include "libunwind.h"
#include "dwarf2.h"
-#include "AddressSpace.hpp"
+#include "config.h"
namespace libunwind {
/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
-/// See Dwarf Spec for details:
+/// See DWARF Spec for details:
/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
///
template <typename A>
@@ -64,7 +63,7 @@ public:
};
enum {
- kMaxRegisterNumber = 120
+ kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
};
enum RegisterSavedWhere {
kRegisterUnused,
@@ -79,7 +78,7 @@ public:
int64_t value;
};
/// Information about a frame layout and registers saved determined
- /// by "running" the dwarf FDE "instructions"
+ /// by "running" the DWARF FDE "instructions"
struct PrologInfo {
uint32_t cfaRegister;
int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
@@ -140,23 +139,23 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
if (err != NULL)
return err;
p += 4;
- // parse pc begin and range
+ // Parse pc begin and range.
pint_t pcStart =
addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
pint_t pcRange =
addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
- // parse rest of info
+ // Parse rest of info.
fdeInfo->lsda = 0;
- // check for augmentation length
+ // Check for augmentation length.
if (cieInfo->fdesHaveAugmentationData) {
pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
pint_t endOfAug = p + augLen;
if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
- // peek at value (without indirection). Zero means no lsda
+ // Peek at value (without indirection). Zero means no LSDA.
pint_t lsdaStart = p;
if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
0) {
- // reset pointer and re-parse lsda address
+ // Reset pointer and re-parse LSDA address.
p = lsdaStart;
fdeInfo->lsda =
addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
@@ -194,23 +193,23 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
return false; // end marker
uint32_t id = addressSpace.get32(p);
if (id == 0) {
- // skip over CIEs
+ // Skip over CIEs.
p += cfiLength;
} else {
- // process FDE to see if it covers pc
+ // Process FDE to see if it covers pc.
pint_t nextCFI = p + cfiLength;
uint32_t ciePointer = addressSpace.get32(p);
pint_t cieStart = p - ciePointer;
- // validate pointer to CIE is within section
+ // Validate pointer to CIE is within section.
if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
p += 4;
- // parse pc begin and range
+ // Parse pc begin and range.
pint_t pcStart =
addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
pint_t pcRange = addressSpace.getEncodedP(
p, nextCFI, cieInfo->pointerEncoding & 0x0F);
- // test if pc is within the function this FDE covers
+ // Test if pc is within the function this FDE covers.
if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
// parse rest of info
fdeInfo->lsda = 0;
@@ -219,11 +218,11 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
pint_t endOfAug = p + augLen;
if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
- // peek at value (without indirection). Zero means no lsda
+ // Peek at value (without indirection). Zero means no LSDA.
pint_t lsdaStart = p;
if (addressSpace.getEncodedP(
p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
- // reset pointer and re-parse lsda address
+ // Reset pointer and re-parse LSDA address.
p = lsdaStart;
fdeInfo->lsda = addressSpace
.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
@@ -241,7 +240,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
// pc is not in begin/range, skip this FDE
}
} else {
- // malformed CIE, now augmentation describing pc range encoding
+ // Malformed CIE, now augmentation describing pc range encoding.
}
} else {
// malformed FDE. CIE is bad
@@ -340,7 +339,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
}
-/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
+/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
template <typename A>
bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
const FDE_Info &fdeInfo,
@@ -359,22 +358,21 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
upToPC - fdeInfo.pcStart, rememberStack, results);
}
-/// "run" the dwarf instructions
+/// "run" the DWARF instructions
template <typename A>
bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
pint_t instructionsEnd,
const CIE_Info &cieInfo, pint_t pcoffset,
PrologInfoStackEntry *&rememberStack,
PrologInfo *results) {
- const bool logDwarf = false;
pint_t p = instructions;
pint_t codeOffset = 0;
PrologInfo initialState = *results;
- if (logDwarf)
- fprintf(stderr, "parseInstructions(instructions=0x%0" PRIx64 ")\n",
- (uint64_t)instructionsEnd);
- // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
+ _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n",
+ static_cast<uint64_t>(instructionsEnd));
+
+ // see DWARF Spec, section 6.4.2 for details on unwind opcodes
while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
uint64_t reg;
uint64_t reg2;
@@ -382,39 +380,36 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
uint64_t length;
uint8_t opcode = addressSpace.get8(p);
uint8_t operand;
+#if !defined(_LIBUNWIND_NO_HEAP)
PrologInfoStackEntry *entry;
+#endif
++p;
switch (opcode) {
case DW_CFA_nop:
- if (logDwarf)
- fprintf(stderr, "DW_CFA_nop\n");
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
break;
case DW_CFA_set_loc:
codeOffset =
addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
- if (logDwarf)
- fprintf(stderr, "DW_CFA_set_loc\n");
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
break;
case DW_CFA_advance_loc1:
codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
p += 1;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
+ static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_advance_loc2:
codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
p += 2;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
+ static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_advance_loc4:
codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
p += 4;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
+ static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_offset_extended:
reg = addressSpace.getULEB128(p, instructionsEnd);
@@ -422,45 +417,41 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
* cieInfo.dataAlignFactor;
if (reg > kMaxRegisterNumber) {
fprintf(stderr,
- "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
+ "malformed DW_CFA_offset_extended DWARF unwind, reg too big\n");
return false;
}
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_offset_extended(reg=%" PRIu64 ", offset=%" PRId64 ")\n",
- reg, offset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
+ "offset=%" PRId64 ")\n",
+ reg, offset);
break;
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");
+ "malformed DW_CFA_restore_extended DWARF unwind, reg too big\n");
return false;
}
results->savedRegisters[reg] = initialState.savedRegisters[reg];
- if (logDwarf)
- fprintf(stderr, "DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
break;
case DW_CFA_undefined:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
fprintf(stderr,
- "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
+ "malformed DW_CFA_undefined DWARF unwind, reg too big\n");
return false;
}
results->savedRegisters[reg].location = kRegisterUnused;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
break;
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");
+ "malformed DW_CFA_same_value DWARF unwind, reg too big\n");
return false;
}
// <rdar://problem/8456377> DW_CFA_same_value unsupported
@@ -470,30 +461,29 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
results->savedRegisters[reg].location = kRegisterUnused;
// set flag to disable conversion to compact unwind
results->sameValueUsed = true;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
break;
case DW_CFA_register:
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");
+ "malformed DW_CFA_register DWARF unwind, reg too big\n");
return false;
}
if (reg2 > kMaxRegisterNumber) {
fprintf(stderr,
- "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
+ "malformed DW_CFA_register DWARF unwind, reg2 too big\n");
return false;
}
results->savedRegisters[reg].location = kRegisterInRegister;
results->savedRegisters[reg].value = (int64_t)reg2;
// set flag to disable conversion to compact unwind
results->registersInOtherRegisters = true;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n",
- reg, reg2);
+ _LIBUNWIND_TRACE_DWARF(
+ "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
break;
+#if !defined(_LIBUNWIND_NO_HEAP)
case DW_CFA_remember_state:
// avoid operator new, because that would be an upward dependency
entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
@@ -504,8 +494,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
} else {
return false;
}
- if (logDwarf)
- fprintf(stderr, "DW_CFA_remember_state\n");
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
break;
case DW_CFA_restore_state:
if (rememberStack != NULL) {
@@ -516,84 +505,81 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
} else {
return false;
}
- if (logDwarf)
- fprintf(stderr, "DW_CFA_restore_state\n");
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
break;
+#endif
case DW_CFA_def_cfa:
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");
+ fprintf(stderr, "malformed DW_CFA_def_cfa DWARF unwind, reg too big\n");
return false;
}
results->cfaRegister = (uint32_t)reg;
results->cfaRegisterOffset = (int32_t)offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n",
- reg, offset);
+ _LIBUNWIND_TRACE_DWARF(
+ "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset);
break;
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");
+ "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big\n");
return false;
}
results->cfaRegister = (uint32_t)reg;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
break;
case DW_CFA_def_cfa_offset:
results->cfaRegisterOffset = (int32_t)
addressSpace.getULEB128(p, instructionsEnd);
results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n",
- results->cfaRegisterOffset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
+ results->cfaRegisterOffset);
break;
case DW_CFA_def_cfa_expression:
results->cfaRegister = 0;
results->cfaExpression = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
- p += length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%" PRIx64
- ", length=%" PRIu64 ")\n",
- results->cfaExpression, length);
+ assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+ p += static_cast<pint_t>(length);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
+ ", length=%" PRIu64 ")\n",
+ results->cfaExpression, length);
break;
case DW_CFA_expression:
reg = addressSpace.getULEB128(p, instructionsEnd);
if (reg > kMaxRegisterNumber) {
fprintf(stderr,
- "malformed DW_CFA_expression dwarf unwind, reg too big\n");
+ "malformed DW_CFA_expression DWARF unwind, reg too big\n");
return false;
}
results->savedRegisters[reg].location = kRegisterAtExpression;
results->savedRegisters[reg].value = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
- p += length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_expression(reg=%" PRIu64
- ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
- reg, results->savedRegisters[reg].value, length);
+ assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+ p += static_cast<pint_t>(length);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
+ "expression=0x%" PRIx64 ", "
+ "length=%" PRIu64 ")\n",
+ reg, results->savedRegisters[reg].value, length);
break;
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");
+ "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big\n");
return false;
}
offset =
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%" PRIu64
- ", offset=%" PRId64 ")\n",
- reg, offset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
+ "offset=%" PRId64 ")\n",
+ reg, offset);
break;
case DW_CFA_def_cfa_sf:
reg = addressSpace.getULEB128(p, instructionsEnd);
@@ -601,23 +587,21 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
if (reg > kMaxRegisterNumber) {
fprintf(stderr,
- "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
+ "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big\n");
return false;
}
results->cfaRegister = (uint32_t)reg;
results->cfaRegisterOffset = (int32_t)offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_def_cfa_sf(reg=%" PRIu64 ", offset=%" PRId64 ")\n", reg,
- offset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
+ "offset=%" PRId64 ")\n",
+ reg, offset);
break;
case DW_CFA_def_cfa_offset_sf:
results->cfaRegisterOffset = (int32_t)
(addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n",
- results->cfaRegisterOffset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
+ results->cfaRegisterOffset);
break;
case DW_CFA_val_offset:
reg = addressSpace.getULEB128(p, instructionsEnd);
@@ -625,53 +609,50 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
* cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_val_offset(reg=%" PRIu64 ", offset=%" PRId64 "\n", reg,
- offset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
+ "offset=%" PRId64 "\n",
+ reg, offset);
break;
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");
+ "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big\n");
return false;
}
offset =
addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_val_offset_sf(reg=%" PRIu64 ", offset=%" PRId64 "\n",
- reg, offset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
+ "offset=%" PRId64 "\n",
+ reg, offset);
break;
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");
+ "malformed DW_CFA_val_expression DWARF unwind, reg too big\n");
return false;
}
results->savedRegisters[reg].location = kRegisterIsExpression;
results->savedRegisters[reg].value = (int64_t)p;
length = addressSpace.getULEB128(p, instructionsEnd);
- p += length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_val_expression(reg=%" PRIu64
- ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
- reg, results->savedRegisters[reg].value, length);
+ assert(length < std::numeric_limits<pint_t>::max() && "pointer overflow");
+ p += static_cast<pint_t>(length);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
+ "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
+ reg, results->savedRegisters[reg].value, length);
break;
case DW_CFA_GNU_args_size:
length = addressSpace.getULEB128(p, instructionsEnd);
results->spExtraArgSize = (uint32_t)length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
break;
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 "
+ fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended DWARF "
"unwind, reg too big\n");
return false;
}
@@ -679,9 +660,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
* cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = -offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n",
- offset);
+ _LIBUNWIND_TRACE_DWARF(
+ "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
break;
default:
operand = opcode & 0x3F;
@@ -692,25 +672,22 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
* cieInfo.dataAlignFactor;
results->savedRegisters[reg].location = kRegisterInCFA;
results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
- operand, offset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
+ operand, offset);
break;
case DW_CFA_advance_loc:
codeOffset += operand * cieInfo.codeAlignFactor;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
+ static_cast<uint64_t>(codeOffset));
break;
case DW_CFA_restore:
reg = operand;
results->savedRegisters[reg] = initialState.savedRegisters[reg];
- if (logDwarf)
- fprintf(stderr, "DW_CFA_restore(reg=%" PRIu64 ")\n", reg);
+ _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
+ static_cast<uint64_t>(operand));
break;
default:
- if (logDwarf)
- fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
+ _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
return false;
}
}
diff --git a/src/EHHeaderParser.hpp b/src/EHHeaderParser.hpp
index 7945c7b..c66af21 100644
--- a/src/EHHeaderParser.hpp
+++ b/src/EHHeaderParser.hpp
@@ -15,7 +15,6 @@
#include "libunwind.h"
-#include "AddressSpace.hpp"
#include "DwarfParser.hpp"
namespace libunwind {
@@ -85,7 +84,7 @@ bool EHHeaderParser<A>::decodeTableEntry(
const char *message =
CFI_Parser<A>::decodeFDE(addressSpace, fde, fdeInfo, cieInfo);
if (message != NULL) {
- _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s\n",
+ _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s",
message);
return false;
}
diff --git a/src/Registers.hpp b/src/Registers.hpp
index d01ebf0..ff57c60 100644
--- a/src/Registers.hpp
+++ b/src/Registers.hpp
@@ -14,7 +14,6 @@
#define __REGISTERS_HPP__
#include <stdint.h>
-#include <strings.h>
#include <string.h>
#include "libunwind.h"
@@ -26,6 +25,7 @@ namespace libunwind {
struct v128 { uint32_t vec[4]; };
+#if defined(_LIBUNWIND_TARGET_I386)
/// Registers_x86 holds the register state of a thread in a 32-bit intel
/// process.
class _LIBUNWIND_HIDDEN Registers_x86 {
@@ -87,8 +87,8 @@ private:
};
inline Registers_x86::Registers_x86(const void *registers) {
- static_assert(sizeof(Registers_x86) < sizeof(unw_context_t),
- "x86 registers do not fit into unw_context_t");
+ static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
+ "x86 registers do not fit into unw_context_t");
memcpy(&_registers, registers, sizeof(_registers));
}
@@ -122,9 +122,17 @@ inline uint32_t Registers_x86::getRegister(int regNum) const {
return _registers.__edx;
case UNW_X86_EBX:
return _registers.__ebx;
+#if !defined(__APPLE__)
+ case UNW_X86_ESP:
+#else
case UNW_X86_EBP:
+#endif
return _registers.__ebp;
+#if !defined(__APPLE__)
+ case UNW_X86_EBP:
+#else
case UNW_X86_ESP:
+#endif
return _registers.__esp;
case UNW_X86_ESI:
return _registers.__esi;
@@ -154,10 +162,18 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value) {
case UNW_X86_EBX:
_registers.__ebx = value;
return;
+#if !defined(__APPLE__)
+ case UNW_X86_ESP:
+#else
case UNW_X86_EBP:
+#endif
_registers.__ebp = value;
return;
+#if !defined(__APPLE__)
+ case UNW_X86_EBP:
+#else
case UNW_X86_ESP:
+#endif
_registers.__esp = value;
return;
case UNW_X86_ESI:
@@ -212,8 +228,10 @@ inline v128 Registers_x86::getVectorRegister(int) const {
inline void Registers_x86::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no x86 vector registers");
}
+#endif // _LIBUNWIND_TARGET_I386
+#if defined(_LIBUNWIND_TARGET_X86_64)
/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
/// process.
class _LIBUNWIND_HIDDEN Registers_x86_64 {
@@ -279,8 +297,8 @@ private:
};
inline Registers_x86_64::Registers_x86_64(const void *registers) {
- static_assert(sizeof(Registers_x86_64) < sizeof(unw_context_t),
- "x86_64 registers do not fit into unw_context_t");
+ static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
+ "x86_64 registers do not fit into unw_context_t");
memcpy(&_registers, registers, sizeof(_registers));
}
@@ -460,8 +478,10 @@ inline v128 Registers_x86_64::getVectorRegister(int) const {
inline void Registers_x86_64::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no x86_64 vector registers");
}
+#endif // _LIBUNWIND_TARGET_X86_64
+#if defined(_LIBUNWIND_TARGET_PPC)
/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
/// process.
class _LIBUNWIND_HIDDEN Registers_ppc {
@@ -544,8 +564,8 @@ private:
};
inline Registers_ppc::Registers_ppc(const void *registers) {
- static_assert(sizeof(Registers_ppc) < sizeof(unw_context_t),
- "ppc registers do not fit into unw_context_t");
+ static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
+ "ppc registers do not fit into unw_context_t");
memcpy(&_registers, static_cast<const uint8_t *>(registers),
sizeof(_registers));
static_assert(sizeof(ppc_thread_state_t) == 160,
@@ -1024,8 +1044,10 @@ inline const char *Registers_ppc::getRegisterName(int regNum) {
}
}
+#endif // _LIBUNWIND_TARGET_PPC
+#if defined(_LIBUNWIND_TARGET_AARCH64)
/// Registers_arm64 holds the register state of a thread in a 64-bit arm
/// process.
class _LIBUNWIND_HIDDEN Registers_arm64 {
@@ -1072,8 +1094,8 @@ private:
};
inline Registers_arm64::Registers_arm64(const void *registers) {
- static_assert(sizeof(Registers_arm64) < sizeof(unw_context_t),
- "arm64 registers do not fit into unw_context_t");
+ static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
+ "arm64 registers do not fit into unw_context_t");
memcpy(&_registers, registers, sizeof(_registers));
static_assert(sizeof(GPRs) == 0x110,
"expected VFP registers to be at offset 272");
@@ -1290,7 +1312,9 @@ inline v128 Registers_arm64::getVectorRegister(int) const {
inline void Registers_arm64::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no arm64 vector register support yet");
}
+#endif // _LIBUNWIND_TARGET_AARCH64
+#if defined(_LIBUNWIND_TARGET_ARM)
/// Registers_arm holds the register state of a thread in a 32-bit arm
/// process.
///
@@ -1335,10 +1359,12 @@ public:
}
if (_saved_vfp_d16_d31)
restoreVFPv3(_vfp_d16_d31);
+#if defined(__ARM_WMMX)
if (_saved_iwmmx)
restoreiWMMX(_iwmmx);
if (_saved_iwmmx_control)
restoreiWMMXControl(_iwmmx_control);
+#endif
}
private:
@@ -1352,13 +1378,15 @@ private:
static void saveVFPWithFSTMD(unw_fpreg_t*);
static void saveVFPWithFSTMX(unw_fpreg_t*);
static void saveVFPv3(unw_fpreg_t*);
- static void saveiWMMX(unw_fpreg_t*);
- static void saveiWMMXControl(uint32_t*);
static void restoreVFPWithFLDMD(unw_fpreg_t*);
static void restoreVFPWithFLDMX(unw_fpreg_t*);
static void restoreVFPv3(unw_fpreg_t*);
+#if defined(__ARM_WMMX)
+ static void saveiWMMX(unw_fpreg_t*);
+ static void saveiWMMXControl(uint32_t*);
static void restoreiWMMX(unw_fpreg_t*);
static void restoreiWMMXControl(uint32_t*);
+#endif
void restoreCoreAndJumpTo();
// ARM registers
@@ -1376,47 +1404,53 @@ private:
bool _saved_vfp_d0_d15;
// Whether VFPv3 D16-D31 are saved.
bool _saved_vfp_d16_d31;
- // Whether iWMMX data registers are saved.
- bool _saved_iwmmx;
- // Whether iWMMX control registers are saved.
- bool _saved_iwmmx_control;
// VFP registers D0-D15, + padding if saved using FSTMX
unw_fpreg_t _vfp_d0_d15_pad[17];
// VFPv3 registers D16-D31, always saved using FSTMD
unw_fpreg_t _vfp_d16_d31[16];
+#if defined(__ARM_WMMX)
+ // Whether iWMMX data registers are saved.
+ bool _saved_iwmmx;
+ // Whether iWMMX control registers are saved.
+ bool _saved_iwmmx_control;
// iWMMX registers
unw_fpreg_t _iwmmx[16];
// iWMMX control registers
uint32_t _iwmmx_control[4];
+#endif
};
inline Registers_arm::Registers_arm(const void *registers)
: _use_X_for_vfp_save(false),
_saved_vfp_d0_d15(false),
- _saved_vfp_d16_d31(false),
- _saved_iwmmx(false),
- _saved_iwmmx_control(false) {
- static_assert(sizeof(Registers_arm) < sizeof(unw_context_t),
- "arm registers do not fit into unw_context_t");
+ _saved_vfp_d16_d31(false) {
+ static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
+ "arm registers do not fit into unw_context_t");
// See unw_getcontext() note about data.
memcpy(&_registers, registers, sizeof(_registers));
memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
+#if defined(__ARM_WMMX)
+ _saved_iwmmx = false;
+ _saved_iwmmx_control = false;
memset(&_iwmmx, 0, sizeof(_iwmmx));
memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
+#endif
}
inline Registers_arm::Registers_arm()
: _use_X_for_vfp_save(false),
_saved_vfp_d0_d15(false),
- _saved_vfp_d16_d31(false),
- _saved_iwmmx(false),
- _saved_iwmmx_control(false) {
+ _saved_vfp_d16_d31(false) {
memset(&_registers, 0, sizeof(_registers));
memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
+#if defined(__ARM_WMMX)
+ _saved_iwmmx = false;
+ _saved_iwmmx_control = false;
memset(&_iwmmx, 0, sizeof(_iwmmx));
memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
+#endif
}
inline bool Registers_arm::validRegister(int regNum) const {
@@ -1424,24 +1458,35 @@ inline bool Registers_arm::validRegister(int regNum) const {
// virtual register set (VRS).
if (regNum == UNW_REG_IP)
return true;
+
if (regNum == UNW_REG_SP)
return true;
+
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
return true;
+
+#if defined(__ARM_WMMX)
if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
return true;
+#endif
+
return false;
}
inline uint32_t Registers_arm::getRegister(int regNum) {
if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
return _registers.__sp;
+
if (regNum == UNW_ARM_LR)
return _registers.__lr;
+
if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
return _registers.__pc;
+
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
return _registers.__r[regNum];
+
+#if defined(__ARM_WMMX)
if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
if (!_saved_iwmmx_control) {
_saved_iwmmx_control = true;
@@ -1449,26 +1494,44 @@ inline uint32_t Registers_arm::getRegister(int regNum) {
}
return _iwmmx_control[regNum - UNW_ARM_WC0];
}
+#endif
+
_LIBUNWIND_ABORT("unsupported arm register");
}
inline void Registers_arm::setRegister(int regNum, uint32_t value) {
- if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
+ if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
_registers.__sp = value;
- else if (regNum == UNW_ARM_LR)
+ return;
+ }
+
+ if (regNum == UNW_ARM_LR) {
_registers.__lr = value;
- else if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
+ return;
+ }
+
+ if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
_registers.__pc = value;
- else if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
+ return;
+ }
+
+ if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
_registers.__r[regNum] = value;
- else if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
+ return;
+ }
+
+#if defined(__ARM_WMMX)
+ if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
if (!_saved_iwmmx_control) {
_saved_iwmmx_control = true;
saveiWMMXControl(_iwmmx_control);
}
_iwmmx_control[regNum - UNW_ARM_WC0] = value;
- } else
- _LIBUNWIND_ABORT("unsupported arm register");
+ return;
+ }
+#endif
+
+ _LIBUNWIND_ABORT("unsupported arm register");
}
inline const char *Registers_arm::getRegisterName(int regNum) {
@@ -1644,7 +1707,10 @@ inline bool Registers_arm::validFloatRegister(int regNum) const {
// NOTE: Consider the intel MMX registers floating points so the
// unw_get_fpreg can be used to transmit the 64-bit data back.
return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
- || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15));
+#if defined(__ARM_WMMX)
+ || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
+#endif
+ ;
}
inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
@@ -1657,21 +1723,27 @@ inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
saveVFPWithFSTMD(_vfp_d0_d15_pad);
}
return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
- } else if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
+ }
+
+ if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
if (!_saved_vfp_d16_d31) {
_saved_vfp_d16_d31 = true;
saveVFPv3(_vfp_d16_d31);
}
return _vfp_d16_d31[regNum - UNW_ARM_D16];
- } else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
+ }
+
+#if defined(__ARM_WMMX)
+ if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
if (!_saved_iwmmx) {
_saved_iwmmx = true;
saveiWMMX(_iwmmx);
}
return _iwmmx[regNum - UNW_ARM_WR0];
- } else {
- _LIBUNWIND_ABORT("Unknown ARM float register");
}
+#endif
+
+ _LIBUNWIND_ABORT("Unknown ARM float register");
}
inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
@@ -1684,21 +1756,30 @@ inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
saveVFPWithFSTMD(_vfp_d0_d15_pad);
}
_vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
- } else if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
+ return;
+ }
+
+ if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
if (!_saved_vfp_d16_d31) {
_saved_vfp_d16_d31 = true;
saveVFPv3(_vfp_d16_d31);
}
_vfp_d16_d31[regNum - UNW_ARM_D16] = value;
- } else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
+ return;
+ }
+
+#if defined(__ARM_WMMX)
+ if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
if (!_saved_iwmmx) {
_saved_iwmmx = true;
saveiWMMX(_iwmmx);
}
_iwmmx[regNum - UNW_ARM_WR0] = value;
- } else {
- _LIBUNWIND_ABORT("Unknown ARM float register");
+ return;
}
+#endif
+
+ _LIBUNWIND_ABORT("Unknown ARM float register");
}
inline bool Registers_arm::validVectorRegister(int) const {
@@ -1712,7 +1793,193 @@ inline v128 Registers_arm::getVectorRegister(int) const {
inline void Registers_arm::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("ARM vector support not implemented");
}
+#endif // _LIBUNWIND_TARGET_ARM
+
+
+#if defined(_LIBUNWIND_TARGET_OR1K)
+/// Registers_or1k holds the register state of a thread in an OpenRISC1000
+/// process.
+class _LIBUNWIND_HIDDEN Registers_or1k {
+public:
+ Registers_or1k();
+ Registers_or1k(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);
+ const char *getRegisterName(int num);
+ void jumpto();
+ static int lastDwarfRegNum() { return 31; }
+
+ 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; }
+
+private:
+ struct or1k_thread_state_t {
+ unsigned int __r[32];
+ };
+
+ or1k_thread_state_t _registers;
+};
+
+inline Registers_or1k::Registers_or1k(const void *registers) {
+ static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
+ "or1k registers do not fit into unw_context_t");
+ memcpy(&_registers, static_cast<const uint8_t *>(registers),
+ sizeof(_registers));
+}
+
+inline Registers_or1k::Registers_or1k() {
+ memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_or1k::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_OR1K_R31)
+ return true;
+ return false;
+}
+
+inline uint32_t Registers_or1k::getRegister(int regNum) const {
+ if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
+ return _registers.__r[regNum - UNW_OR1K_R0];
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ return _registers.__r[9];
+ case UNW_REG_SP:
+ return _registers.__r[1];
+ }
+ _LIBUNWIND_ABORT("unsupported or1k register");
+}
+
+inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
+ if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
+ _registers.__r[regNum - UNW_OR1K_R0] = value;
+ return;
+ }
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ _registers.__r[9] = value;
+ return;
+ case UNW_REG_SP:
+ _registers.__r[1] = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported or1k register");
+}
+
+inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
+ return false;
+}
+
+inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
+ _LIBUNWIND_ABORT("or1k float support not implemented");
+}
+
+inline void Registers_or1k::setFloatRegister(int /* regNum */,
+ double /* value */) {
+ _LIBUNWIND_ABORT("or1k float support not implemented");
+}
+
+inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
+ return false;
+}
+
+inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
+ _LIBUNWIND_ABORT("or1k vector support not implemented");
+}
+
+inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
+ _LIBUNWIND_ABORT("or1k vector support not implemented");
+}
+
+inline const char *Registers_or1k::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_OR1K_R0:
+ return "r0";
+ case UNW_OR1K_R1:
+ return "r1";
+ case UNW_OR1K_R2:
+ return "r2";
+ case UNW_OR1K_R3:
+ return "r3";
+ case UNW_OR1K_R4:
+ return "r4";
+ case UNW_OR1K_R5:
+ return "r5";
+ case UNW_OR1K_R6:
+ return "r6";
+ case UNW_OR1K_R7:
+ return "r7";
+ case UNW_OR1K_R8:
+ return "r8";
+ case UNW_OR1K_R9:
+ return "r9";
+ case UNW_OR1K_R10:
+ return "r10";
+ case UNW_OR1K_R11:
+ return "r11";
+ case UNW_OR1K_R12:
+ return "r12";
+ case UNW_OR1K_R13:
+ return "r13";
+ case UNW_OR1K_R14:
+ return "r14";
+ case UNW_OR1K_R15:
+ return "r15";
+ case UNW_OR1K_R16:
+ return "r16";
+ case UNW_OR1K_R17:
+ return "r17";
+ case UNW_OR1K_R18:
+ return "r18";
+ case UNW_OR1K_R19:
+ return "r19";
+ case UNW_OR1K_R20:
+ return "r20";
+ case UNW_OR1K_R21:
+ return "r21";
+ case UNW_OR1K_R22:
+ return "r22";
+ case UNW_OR1K_R23:
+ return "r23";
+ case UNW_OR1K_R24:
+ return "r24";
+ case UNW_OR1K_R25:
+ return "r25";
+ case UNW_OR1K_R26:
+ return "r26";
+ case UNW_OR1K_R27:
+ return "r27";
+ case UNW_OR1K_R28:
+ return "r28";
+ case UNW_OR1K_R29:
+ return "r29";
+ case UNW_OR1K_R30:
+ return "r30";
+ case UNW_OR1K_R31:
+ return "r31";
+ default:
+ return "unknown register";
+ }
+
+}
+#endif // _LIBUNWIND_TARGET_OR1K
} // namespace libunwind
#endif // __REGISTERS_HPP__
diff --git a/src/Unwind-EHABI.cpp b/src/Unwind-EHABI.cpp
index bc3df41..109b272 100644
--- a/src/Unwind-EHABI.cpp
+++ b/src/Unwind-EHABI.cpp
@@ -12,7 +12,7 @@
#include "Unwind-EHABI.h"
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
#include <stdbool.h>
#include <stdint.h>
@@ -245,11 +245,9 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
return data;
}
-_Unwind_Reason_Code _Unwind_VRS_Interpret(
- _Unwind_Context* context,
- const uint32_t* data,
- size_t offset,
- size_t len) {
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
+ size_t offset, size_t len) {
bool wrotePC = false;
bool finish = false;
while (offset < len && !finish) {
@@ -351,6 +349,7 @@ _Unwind_Reason_Code _Unwind_VRS_Interpret(
}
case 0xc0: {
switch (byte) {
+#if defined(__ARM_WMMX)
case 0xc0:
case 0xc1:
case 0xc2:
@@ -378,6 +377,7 @@ _Unwind_Reason_Code _Unwind_VRS_Interpret(
_Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE);
break;
}
+#endif
case 0xc8:
case 0xc9: {
uint8_t v = getByte(data, offset++);
@@ -416,63 +416,42 @@ _Unwind_Reason_Code _Unwind_VRS_Interpret(
return _URC_CONTINUE_UNWIND;
}
-extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(
- _Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context) {
+extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
+__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context) {
return unwindOneFrame(state, ucbp, context);
}
-extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(
- _Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context) {
+extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
+__aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context) {
return unwindOneFrame(state, ucbp, context);
}
-extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
- _Unwind_State state,
- _Unwind_Control_Block *ucbp,
- _Unwind_Context *context) {
+extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
+__aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context) {
return unwindOneFrame(state, ucbp, context);
}
static _Unwind_Reason_Code
-unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
+unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
// EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
// phase 1 and then restoring it to the "primary VRS" for phase 2. The
// effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
// In this implementation, the phases don't share the VRS backing store.
// Instead, they are passed the original |uc| and they create a new VRS
// from scratch thus achieving the same effect.
- unw_cursor_t cursor1;
- unw_init_local(&cursor1, uc);
+ unw_init_local(cursor, uc);
// Walk each frame looking for a place to stop.
for (bool handlerNotFound = true; handlerNotFound;) {
-#if !_LIBUNWIND_ARM_EHABI
- // Ask libuwind to get next frame (skip over first which is
- // _Unwind_RaiseException).
- int stepResult = unw_step(&cursor1);
- if (stepResult == 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
- static_cast<void *>(exception_object));
- return _URC_END_OF_STACK;
- } else if (stepResult < 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
- "_URC_FATAL_PHASE1_ERROR\n",
- static_cast<void *>(exception_object));
- return _URC_FATAL_PHASE1_ERROR;
- }
-#endif
-
// See if frame has code to run (has personality routine).
unw_proc_info_t frameInfo;
- if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
+ if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
+ "failed => _URC_FATAL_PHASE1_ERROR",
static_cast<void *>(exception_object));
return _URC_FATAL_PHASE1_ERROR;
}
@@ -482,15 +461,15 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
- if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf),
+ if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
unw_word_t pc;
- unw_get_reg(&cursor1, UNW_REG_IP, &pc);
+ unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, "
- "lsda=0x%llX, personality=0x%llX\n",
+ "lsda=0x%llX, personality=0x%llX",
static_cast<void *>(exception_object), (long long)pc,
(long long)frameInfo.start_ip, functionName,
(long long)frameInfo.lsda, (long long)frameInfo.handler);
@@ -502,10 +481,10 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
__personality_routine p =
(__personality_routine)(long)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
+ "unwind_phase1(ex_ojb=%p): calling personality function %p",
static_cast<void *>(exception_object),
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p)));
- struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor1);
+ struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
exception_object->pr_cache.fnstart = frameInfo.start_ip;
exception_object->pr_cache.ehtp =
(_Unwind_EHT_Header *)frameInfo.unwind_info;
@@ -514,7 +493,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
(*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p "
- "additional %x\n",
+ "additional %x",
static_cast<void *>(exception_object), personalityResult,
exception_object->pr_cache.fnstart,
static_cast<void *>(exception_object->pr_cache.ehtp),
@@ -526,13 +505,13 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
handlerNotFound = false;
// p should have initialized barrier_cache. EHABI #7.3.5
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
+ "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
static_cast<void *>(exception_object));
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
+ "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
static_cast<void *>(exception_object));
// continue unwinding
break;
@@ -544,7 +523,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
+ "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
static_cast<void *>(exception_object));
return _URC_FATAL_PHASE1_ERROR;
}
@@ -553,20 +532,19 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
return _URC_NO_REASON;
}
-static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
+static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
_Unwind_Exception *exception_object,
bool resume) {
// See comment at the start of unwind_phase1 regarding VRS integrity.
- unw_cursor_t cursor2;
- unw_init_local(&cursor2, uc);
+ unw_init_local(cursor, uc);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
static_cast<void *>(exception_object));
int frame_count = 0;
// Walk each frame until we reach where search phase said to stop.
while (true) {
- // Ask libuwind to get next frame (skip over first which is
+ // Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException or _Unwind_Resume).
//
// Resume only ever makes sense for 1 frame.
@@ -580,33 +558,18 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
// for. After this, continue unwinding as if normal.
//
// See #7.4.6 for details.
- unw_set_reg(&cursor2, UNW_REG_IP,
+ unw_set_reg(cursor, UNW_REG_IP,
exception_object->unwinder_cache.reserved2);
resume = false;
}
-#if !_LIBUNWIND_ARM_EHABI
- int stepResult = unw_step(&cursor2);
- if (stepResult == 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
- static_cast<void *>(exception_object));
- return _URC_END_OF_STACK;
- } else if (stepResult < 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
- "_URC_FATAL_PHASE1_ERROR\n",
- static_cast<void *>(exception_object));
- return _URC_FATAL_PHASE2_ERROR;
- }
-#endif
-
// Get info about this frame.
unw_word_t sp;
unw_proc_info_t frameInfo;
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
- if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
+ unw_get_reg(cursor, UNW_REG_SP, &sp);
+ if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
+ "failed => _URC_FATAL_PHASE2_ERROR",
static_cast<void *>(exception_object));
return _URC_FATAL_PHASE2_ERROR;
}
@@ -616,13 +579,13 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
- if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
+ if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
- "lsda=0x%llX, personality=0x%llX\n",
+ "lsda=0x%llX, personality=0x%llX",
static_cast<void *>(exception_object), (long long)frameInfo.start_ip,
functionName, (long long)sp, (long long)frameInfo.lsda,
(long long)frameInfo.handler);
@@ -632,7 +595,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
if (frameInfo.handler != 0) {
__personality_routine p =
(__personality_routine)(long)(frameInfo.handler);
- struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor2);
+ struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
// EHABI #7.2
exception_object->pr_cache.fnstart = frameInfo.start_ip;
exception_object->pr_cache.ehtp =
@@ -644,7 +607,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
case _URC_CONTINUE_UNWIND:
// Continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
+ "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
static_cast<void *>(exception_object));
// EHABI #7.2
if (sp == exception_object->barrier_cache.sp) {
@@ -655,16 +618,16 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
+ "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
static_cast<void *>(exception_object));
// Personality routine says to transfer control to landing pad.
// We may get control back if landing pad calls _Unwind_Resume().
if (_LIBUNWIND_TRACING_UNWINDING) {
unw_word_t pc;
- unw_get_reg(&cursor2, UNW_REG_IP, &pc);
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
+ unw_get_reg(cursor, UNW_REG_IP, &pc);
+ unw_get_reg(cursor, UNW_REG_SP, &sp);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
- "user code with ip=0x%llX, sp=0x%llX\n",
+ "user code with ip=0x%llX, sp=0x%llX",
static_cast<void *>(exception_object),
(long long)pc, (long long)sp);
}
@@ -673,10 +636,10 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
// EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume
// is called back, to find this same frame.
unw_word_t pc;
- unw_get_reg(&cursor2, UNW_REG_IP, &pc);
+ unw_get_reg(cursor, UNW_REG_IP, &pc);
exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
}
- unw_resume(&cursor2);
+ unw_resume(cursor);
// unw_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
@@ -702,9 +665,10 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
/// Called by __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)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
static_cast<void *>(exception_object));
unw_context_t uc;
+ unw_cursor_t cursor;
unw_getcontext(&uc);
// This field for is for compatibility with GCC to say this isn't a forced
@@ -712,12 +676,12 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
exception_object->unwinder_cache.reserved1 = 0;
// phase 1: the search phase
- _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
+ _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
if (phase1 != _URC_NO_REASON)
return phase1;
// phase 2: the clean up phase
- return unwind_phase2(&uc, exception_object, false);
+ return unwind_phase2(&uc, &cursor, exception_object, false);
}
_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {
@@ -739,15 +703,16 @@ _LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(_Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)",
static_cast<void *>(exception_object));
unw_context_t uc;
+ unw_cursor_t cursor;
unw_getcontext(&uc);
// _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
// which is in the same position as private_1 below.
// TODO(ajwong): Who wronte the above? Why is it true?
- unwind_phase2(&uc, exception_object, true);
+ unwind_phase2(&uc, &cursor, exception_object, true);
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
@@ -762,7 +727,7 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.lsda;
_LIBUNWIND_TRACE_API(
- "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx\n",
+ "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx",
static_cast<void *>(context), (long long)result);
return result;
}
@@ -785,12 +750,12 @@ static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
return value;
}
-_Unwind_VRS_Result
+_LIBUNWIND_EXPORT _Unwind_VRS_Result
_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
void *valuep) {
_LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "
- "rep=%d, value=0x%llX)\n",
+ "rep=%d, value=0x%llX)",
static_cast<void *>(context), regclass, regno,
representation,
ValueAsBitPattern(representation, valuep));
@@ -803,13 +768,6 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
*(unw_word_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
- case _UVRSC_WMMXC:
- if (representation != _UVRSD_UINT32 || regno > 3)
- return _UVRSR_FAILED;
- return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
- *(unw_word_t *)valuep) == UNW_ESUCCESS
- ? _UVRSR_OK
- : _UVRSR_FAILED;
case _UVRSC_VFP:
if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
return _UVRSR_FAILED;
@@ -826,6 +784,14 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
*(unw_fpreg_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
+#if defined(__ARM_WMMX)
+ case _UVRSC_WMMXC:
+ if (representation != _UVRSD_UINT32 || regno > 3)
+ return _UVRSR_FAILED;
+ return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
+ *(unw_word_t *)valuep) == UNW_ESUCCESS
+ ? _UVRSR_OK
+ : _UVRSR_FAILED;
case _UVRSC_WMMXD:
if (representation != _UVRSD_DOUBLE || regno > 31)
return _UVRSR_FAILED;
@@ -833,6 +799,11 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
*(unw_fpreg_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
+#else
+ case _UVRSC_WMMXC:
+ case _UVRSC_WMMXD:
+ break;
+#endif
}
_LIBUNWIND_ABORT("unsupported register class");
}
@@ -851,13 +822,6 @@ _Unwind_VRS_Get_Internal(_Unwind_Context *context,
(unw_word_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
- case _UVRSC_WMMXC:
- if (representation != _UVRSD_UINT32 || regno > 3)
- return _UVRSR_FAILED;
- return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
- (unw_word_t *)valuep) == UNW_ESUCCESS
- ? _UVRSR_OK
- : _UVRSR_FAILED;
case _UVRSC_VFP:
if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
return _UVRSR_FAILED;
@@ -874,6 +838,14 @@ _Unwind_VRS_Get_Internal(_Unwind_Context *context,
(unw_fpreg_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
+#if defined(__ARM_WMMX)
+ case _UVRSC_WMMXC:
+ if (representation != _UVRSD_UINT32 || regno > 3)
+ return _UVRSR_FAILED;
+ return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
+ (unw_word_t *)valuep) == UNW_ESUCCESS
+ ? _UVRSR_OK
+ : _UVRSR_FAILED;
case _UVRSC_WMMXD:
if (representation != _UVRSD_DOUBLE || regno > 31)
return _UVRSR_FAILED;
@@ -881,21 +853,24 @@ _Unwind_VRS_Get_Internal(_Unwind_Context *context,
(unw_fpreg_t *)valuep) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
+#else
+ case _UVRSC_WMMXC:
+ case _UVRSC_WMMXD:
+ break;
+#endif
}
_LIBUNWIND_ABORT("unsupported register class");
}
-_Unwind_VRS_Result _Unwind_VRS_Get(
- _Unwind_Context *context,
- _Unwind_VRS_RegClass regclass,
- uint32_t regno,
- _Unwind_VRS_DataRepresentation representation,
- void *valuep) {
+_LIBUNWIND_EXPORT _Unwind_VRS_Result
+_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
+ uint32_t regno, _Unwind_VRS_DataRepresentation representation,
+ void *valuep) {
_Unwind_VRS_Result result =
_Unwind_VRS_Get_Internal(context, regclass, regno, representation,
valuep);
_LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, "
- "rep=%d, value=0x%llX, result = %d)\n",
+ "rep=%d, value=0x%llX, result = %d)",
static_cast<void *>(context), regclass, regno,
representation,
ValueAsBitPattern(representation, valuep), result);
@@ -907,12 +882,15 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t discriminator,
_Unwind_VRS_DataRepresentation representation) {
_LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, "
- "discriminator=%d, representation=%d)\n",
+ "discriminator=%d, representation=%d)",
static_cast<void *>(context), regclass, discriminator,
representation);
switch (regclass) {
- case _UVRSC_CORE:
- case _UVRSC_WMMXC: {
+ case _UVRSC_WMMXC:
+#if !defined(__ARM_WMMX)
+ break;
+#endif
+ case _UVRSC_CORE: {
if (representation != _UVRSD_UINT32)
return _UVRSR_FAILED;
// When popping SP from the stack, we don't want to override it from the
@@ -940,8 +918,11 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
}
return _UVRSR_OK;
}
- case _UVRSC_VFP:
- case _UVRSC_WMMXD: {
+ case _UVRSC_WMMXD:
+#if !defined(__ARM_WMMX)
+ break;
+#endif
+ case _UVRSC_VFP: {
if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
return _UVRSR_FAILED;
uint32_t first = discriminator >> 16;
@@ -980,7 +961,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
uintptr_t result = 0;
if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.start_ip;
- _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX",
static_cast<void *>(context), (long long)result);
return result;
}
@@ -990,7 +971,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
// is caught.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
static_cast<void *>(exception_object));
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
@@ -1006,4 +987,4 @@ __gnu_unwind_frame(_Unwind_Exception *exception_object,
return _URC_OK;
}
-#endif // _LIBUNWIND_ARM_EHABI
+#endif // defined(_LIBUNWIND_ARM_EHABI)
diff --git a/src/Unwind-EHABI.h b/src/Unwind-EHABI.h
index a7c62df..fe164ff 100644
--- a/src/Unwind-EHABI.h
+++ b/src/Unwind-EHABI.h
@@ -13,7 +13,7 @@
#include <__libunwind_config.h>
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
#include <stdint.h>
#include <unwind.h>
@@ -46,6 +46,6 @@ extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
} // extern "C"
#endif
-#endif // _LIBUNWIND_ARM_EHABI
+#endif // defined(_LIBUNWIND_ARM_EHABI)
#endif // __UNWIND_EHABI_H__
diff --git a/src/Unwind-sjlj.c b/src/Unwind-sjlj.c
index f9256b5..f01e652 100644
--- a/src/Unwind-sjlj.c
+++ b/src/Unwind-sjlj.c
@@ -32,7 +32,7 @@
// function also sets the personality and lsda fields of the block.
//
-#if _LIBUNWIND_BUILD_SJLJ_APIS
+#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
struct _Unwind_FunctionContext {
// next function in stack of handlers
@@ -72,7 +72,7 @@ _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\n", c);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c);
// walk each frame looking for a place to stop
for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
@@ -80,17 +80,17 @@ unwind_phase1(struct _Unwind_Exception *exception_object) {
// check for no more frames
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
- "bottom => _URC_END_OF_STACK\n",
+ "bottom => _URC_END_OF_STACK",
exception_object);
return _URC_END_OF_STACK;
}
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p\n", c);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", 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\n",
+ "personality function %p",
exception_object, c->personality);
_Unwind_Reason_Code personalityResult = (*c->personality)(
1, _UA_SEARCH_PHASE, exception_object->exception_class,
@@ -102,19 +102,19 @@ 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\n", exception_object);
+ "_URC_HANDLER_FOUND", exception_object);
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
- "_URC_CONTINUE_UNWIND\n", exception_object);
+ "_URC_CONTINUE_UNWIND", exception_object);
// continue unwinding
break;
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
+ "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
@@ -126,18 +126,18 @@ 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)\n", exception_object);
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", 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\n",
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p",
exception_object, 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\n",
+ "bottom => _URC_END_OF_STACK",
exception_object);
return _URC_END_OF_STACK;
}
@@ -157,7 +157,7 @@ unwind_phase2(struct _Unwind_Exception *exception_object) {
case _URC_CONTINUE_UNWIND:
// continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
+ "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
exception_object);
if ((uintptr_t) c == exception_object->private_2) {
// phase 1 said we would stop at this frame, but we did not...
@@ -168,7 +168,7 @@ unwind_phase2(struct _Unwind_Exception *exception_object) {
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
"_URC_INSTALL_CONTEXT, will resume at "
- "landing pad %p\n",
+ "landing pad %p",
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()
@@ -202,7 +202,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
// get next frame (skip over first which is _Unwind_RaiseException)
if (c == NULL) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
+ "bottom => _URC_END_OF_STACK",
exception_object);
return _URC_END_OF_STACK;
}
@@ -214,11 +214,11 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
(*stop)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)c, stop_parameter);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "stop function returned %d\n",
+ "stop function returned %d",
exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "stopped by stop function\n",
+ "stopped by stop function",
exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -227,7 +227,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
if (c->personality != NULL) {
__personality_routine p = (__personality_routine) c->personality;
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "calling personality function %p\n",
+ "calling personality function %p",
exception_object, p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
@@ -235,13 +235,13 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "personality returned _URC_CONTINUE_UNWIND\n",
+ "personality returned _URC_CONTINUE_UNWIND",
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\n",
+ "personality returned _URC_INSTALL_CONTEXT",
exception_object);
// we may get control back if landing pad calls _Unwind_Resume()
__Unwind_SjLj_SetTopOfFunctionStack(c);
@@ -251,7 +251,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object,
// something went wrong
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned %d, "
- "_URC_FATAL_PHASE2_ERROR\n",
+ "_URC_FATAL_PHASE2_ERROR",
exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -262,7 +262,7 @@ 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\n",
+ "function with _UA_END_OF_STACK",
exception_object);
_Unwind_Action lastAction =
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
@@ -278,7 +278,7 @@ 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)\n", exception_object);
+ _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object);
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
// thing
@@ -308,7 +308,7 @@ _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)\n", exception_object);
+ _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object);
if (exception_object->private_1 != 0)
unwind_phase2_forced(exception_object,
@@ -326,7 +326,7 @@ _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\n",
+ "private_1=%ld",
exception_object, exception_object->private_1);
// If this is non-forced and a stopping place was found, then this is a
// re-throw.
@@ -350,7 +350,7 @@ _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\n", context, ufc->lsda);
+ "=> 0x%0lX", context, ufc->lsda);
return ufc->lsda;
}
@@ -358,7 +358,7 @@ _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)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)",
context, index);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
return ufc->resumeParameters[index];
@@ -368,7 +368,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n"
+ _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)"
, context, index, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeParameters[index] = new_value;
@@ -378,7 +378,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
- _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context,
+ _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context,
ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@@ -391,7 +391,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
*ipBefore = 0;
- _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX",
context, ipBefore, ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@@ -400,7 +400,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter instruction pointer.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t new_value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)",
context, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeLocation = new_value - 1;
@@ -413,7 +413,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)\n", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context);
return 0;
}
@@ -422,7 +422,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
/// is caught.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
exception_object);
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
@@ -437,7 +437,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)\n", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context);
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
}
@@ -448,14 +448,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)\n", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", 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)\n", context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context);
if (context != NULL) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
// Setjmp/longjmp based exceptions don't have a true CFA.
@@ -465,4 +465,4 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
return 0;
}
-#endif // _LIBUNWIND_BUILD_SJLJ_APIS
+#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
diff --git a/src/UnwindCursor.hpp b/src/UnwindCursor.hpp
index 59924f0..5f9cba9 100644
--- a/src/UnwindCursor.hpp
+++ b/src/UnwindCursor.hpp
@@ -6,7 +6,7 @@
// Source Licenses. See LICENSE.TXT for details.
//
//
-// C++ interface to lower levels of libuwind
+// C++ interface to lower levels of libunwind
//===----------------------------------------------------------------------===//
#ifndef __UNWINDCURSOR_HPP__
@@ -16,7 +16,9 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <pthread.h>
+#ifndef _LIBUNWIND_HAS_NO_THREADS
+ #include <pthread.h>
+#endif
#include <unwind.h>
#ifdef __APPLE__
@@ -36,7 +38,7 @@
namespace libunwind {
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
/// Cache of recently found FDEs.
template <typename A>
class _LIBUNWIND_HIDDEN DwarfFDECache {
@@ -60,7 +62,9 @@ private:
// These fields are all static to avoid needing an initializer.
// There is only one instance of this class per process.
+#ifndef _LIBUNWIND_HAS_NO_THREADS
static pthread_rwlock_t _lock;
+#endif
#ifdef __APPLE__
static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
static bool _registeredForDyldUnloads;
@@ -87,8 +91,10 @@ DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
template <typename A>
typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
+#ifndef _LIBUNWIND_HAS_NO_THREADS
template <typename A>
pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
+#endif
#ifdef __APPLE__
template <typename A>
@@ -114,6 +120,7 @@ typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
template <typename A>
void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
pint_t fde) {
+#if !defined(_LIBUNWIND_NO_HEAP)
_LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock));
if (_bufferUsed >= _bufferEnd) {
size_t oldSize = (size_t)(_bufferEnd - _buffer);
@@ -139,6 +146,7 @@ void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
}
#endif
_LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
+#endif
}
template <typename A>
@@ -172,12 +180,12 @@ void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
}
_LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
}
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
template <typename A> class UnwindSectionHeader {
public:
UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
@@ -365,7 +373,7 @@ private:
A &_addressSpace;
typename A::pint_t _addr;
};
-#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
public:
@@ -438,7 +446,7 @@ public:
private:
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
int stepWithEHABI() {
@@ -456,7 +464,7 @@ private:
}
#endif
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
uint32_t fdeSectionOffsetHint=0);
int stepWithDwarfFDE() {
@@ -467,11 +475,11 @@ private:
}
#endif
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
bool getInfoFromCompactEncodingSection(pint_t pc,
const UnwindInfoSections &sects);
int stepWithCompactEncoding() {
- #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
if ( compactSaysUseDwarf() )
return stepWithDwarfFDE();
#endif
@@ -479,30 +487,39 @@ private:
return stepWithCompactEncoding(dummy);
}
+#if defined(_LIBUNWIND_TARGET_X86_64)
int stepWithCompactEncoding(Registers_x86_64 &) {
return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
_info.format, _info.start_ip, _addressSpace, _registers);
}
+#endif
+#if defined(_LIBUNWIND_TARGET_I386)
int stepWithCompactEncoding(Registers_x86 &) {
return CompactUnwinder_x86<A>::stepWithCompactEncoding(
_info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
}
+#endif
+#if defined(_LIBUNWIND_TARGET_PPC)
int stepWithCompactEncoding(Registers_ppc &) {
return UNW_EINVAL;
}
+#endif
+#if defined(_LIBUNWIND_TARGET_AARCH64)
int stepWithCompactEncoding(Registers_arm64 &) {
return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
_info.format, _info.start_ip, _addressSpace, _registers);
}
+#endif
bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
R dummy;
return compactSaysUseDwarf(dummy, offset);
}
+#if defined(_LIBUNWIND_TARGET_X86_64)
bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
if (offset)
@@ -511,7 +528,9 @@ private:
}
return false;
}
+#endif
+#if defined(_LIBUNWIND_TARGET_I386)
bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
if (offset)
@@ -520,11 +539,15 @@ private:
}
return false;
}
+#endif
+#if defined(_LIBUNWIND_TARGET_PPC)
bool compactSaysUseDwarf(Registers_ppc &, 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) {
if (offset)
@@ -533,30 +556,45 @@ private:
}
return false;
}
-#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#endif
+#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
compact_unwind_encoding_t dwarfEncoding() const {
R dummy;
return dwarfEncoding(dummy);
}
+#if defined(_LIBUNWIND_TARGET_X86_64)
compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
return UNWIND_X86_64_MODE_DWARF;
}
+#endif
+#if defined(_LIBUNWIND_TARGET_I386)
compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
return UNWIND_X86_MODE_DWARF;
}
+#endif
+#if defined(_LIBUNWIND_TARGET_PPC)
compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
return 0;
}
+#endif
+#if defined(_LIBUNWIND_TARGET_AARCH64)
compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
return UNWIND_ARM64_MODE_DWARF;
}
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#endif
+
+#if defined (_LIBUNWIND_TARGET_OR1K)
+ compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
+ return 0;
+ }
+#endif
+#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
A &_addressSpace;
@@ -571,7 +609,7 @@ template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
_isSignalFrame(false) {
- static_assert(sizeof(UnwindCursor<A, R>) < sizeof(unw_cursor_t),
+ 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));
}
@@ -634,7 +672,7 @@ template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
return _isSignalFrame;
}
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
struct EHABIIndexEntry {
uint32_t functionOffset;
uint32_t data;
@@ -655,7 +693,8 @@ struct EHABISectionIterator {
return _Self(addressSpace, sects, 0);
}
static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
- return _Self(addressSpace, sects, sects.arm_section_length);
+ return _Self(addressSpace, sects,
+ sects.arm_section_length / sizeof(EHABIIndexEntry));
}
EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
@@ -829,7 +868,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
}
#endif
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
template <typename A, typename R>
bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
const UnwindInfoSections &sects,
@@ -845,7 +884,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
sects.dwarf_section + fdeSectionOffsetHint,
&fdeInfo, &cieInfo);
}
-#if _LIBUNWIND_SUPPORT_DWARF_INDEX
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
if (!foundFDE && (sects.dwarf_index_section != 0)) {
foundFDE = EHHeaderParser<A>::findFDE(
_addressSpace, pc, sects.dwarf_index_section,
@@ -888,7 +927,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
// Add to cache (to make next lookup faster) if we had no hint
// and there was no index.
if (!foundInCache && (fdeSectionOffsetHint == 0)) {
- #if _LIBUNWIND_SUPPORT_DWARF_INDEX
+ #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
if (sects.dwarf_index_section == 0)
#endif
DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
@@ -897,13 +936,13 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
return true;
}
}
- //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc);
+ //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
return false;
}
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
template <typename A, typename R>
bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
const UnwindInfoSections &sects) {
@@ -1054,13 +1093,13 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
if (pc < funcStart) {
_LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
- "level compressed unwind table. funcStart=0x%llX\n",
+ "level compressed unwind table. funcStart=0x%llX",
(uint64_t) pc, (uint64_t) funcStart);
return false;
}
if (pc > funcEnd) {
_LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
- "level compressed unwind table. funcEnd=0x%llX\n",
+ "level compressed unwind table. funcEnd=0x%llX",
(uint64_t) pc, (uint64_t) funcEnd);
return false;
}
@@ -1081,7 +1120,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
}
} else {
_LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
- "level page\n",
+ "level page",
(uint64_t) sects.compact_unwind_section);
return false;
}
@@ -1111,7 +1150,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
}
if (lsda == 0) {
_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
- "pc=0x%0llX, but lsda table has no entry\n",
+ "pc=0x%0llX, but lsda table has no entry",
encoding, (uint64_t) pc);
return false;
}
@@ -1124,7 +1163,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
--personalityIndex; // change 1-based to zero-based index
if (personalityIndex > sectionHeader.personalityArrayCount()) {
_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
- "but personality table has only %d entires\n",
+ "but personality table has only %d entires",
encoding, personalityIndex,
sectionHeader.personalityArrayCount());
return false;
@@ -1157,13 +1196,13 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
_info.extra = sects.dso_base;
return true;
}
-#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
template <typename A, typename R>
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
// Remove the thumb bit so the IP represents the actual instruction address.
// This matches the behaviour of _Unwind_GetIP on arm.
pc &= (pint_t)~0x1;
@@ -1180,11 +1219,11 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
// Ask address space object to find unwind sections for this pc.
UnwindInfoSections sects;
if (_addressSpace.findUnwindSections(pc, sects)) {
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
// If there is a compact unwind encoding table, look there first.
if (sects.compact_unwind_section != 0) {
if (this->getInfoFromCompactEncodingSection(pc, sects)) {
- #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// Found info in table, done unless encoding says to use dwarf.
uint32_t dwarfOffset;
if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
@@ -1201,9 +1240,9 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
return;
}
}
-#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// If there is dwarf unwind info, look there next.
if (sects.dwarf_section != 0) {
if (this->getInfoFromDwarfSection(pc, sects)) {
@@ -1213,14 +1252,14 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
}
#endif
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
// If there is ARM EHABI unwind info, look there next.
if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
return;
#endif
}
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// There is no static unwind info for this pc. Look to see if an FDE was
// dynamically registered for it.
pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
@@ -1279,7 +1318,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
}
}
}
-#endif // #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// no unwind info, flag that we can't reliably unwind
_unwindInfoMissing = true;
@@ -1293,11 +1332,11 @@ int UnwindCursor<A, R>::step() {
// Use unwinding info to modify register set as if function returned.
int result;
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
result = this->stepWithCompactEncoding();
-#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
result = this->stepWithDwarfFDE();
-#elif _LIBUNWIND_ARM_EHABI
+#elif defined(_LIBUNWIND_ARM_EHABI)
result = this->stepWithEHABI();
#else
#error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
diff --git a/src/UnwindLevel1-gcc-ext.c b/src/UnwindLevel1-gcc-ext.c
index 28ba092..f8c1fb4 100644
--- a/src/UnwindLevel1-gcc-ext.c
+++ b/src/UnwindLevel1-gcc-ext.c
@@ -23,22 +23,22 @@
#include "Unwind-EHABI.h"
#include "unwind.h"
-#if _LIBUNWIND_BUILD_ZERO_COST_APIS
+#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
/// Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
-#if _LIBUNWIND_ARM_EHABI
- _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n",
+#if defined(_LIBUNWIND_ARM_EHABI)
+ _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
(void *)exception_object,
(long)exception_object->unwinder_cache.reserved1);
#else
- _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n",
+ _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
(void *)exception_object,
(long)exception_object->private_1);
#endif
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
// _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
// which is in the same position as private_1 below.
return _Unwind_RaiseException(exception_object);
@@ -66,7 +66,7 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
(void)context;
- _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)\n", (void *)context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
}
@@ -76,7 +76,7 @@ _Unwind_GetDataRelBase(struct _Unwind_Context *context) {
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
(void)context;
- _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", (void *)context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
_LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
@@ -84,7 +84,7 @@ _Unwind_GetTextRelBase(struct _Unwind_Context *context) {
/// Scans unwind information to find the function that contains the
/// specified code address "pc".
_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
- _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)\n", pc);
+ _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc);
// This is slow, but works.
// We create an unwind cursor then alter the IP to be pc
unw_cursor_t cursor;
@@ -108,10 +108,10 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
- _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)",
(void *)(uintptr_t)callback);
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
// Create a mock exception object for force unwinding.
_Unwind_Exception ex;
memset(&ex, '\0', sizeof(ex));
@@ -122,12 +122,12 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
while (true) {
_Unwind_Reason_Code result;
-#if !_LIBUNWIND_ARM_EHABI
- // ask libuwind to get next frame (skip over first frame which is
+#if !defined(_LIBUNWIND_ARM_EHABI)
+ // ask libunwind to get next frame (skip over first frame which is
// _Unwind_Backtrace())
if (unw_step(&cursor) <= 0) {
_LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached "
- "bottom of stack, returning %d\n",
+ "bottom of stack, returning %d",
_URC_END_OF_STACK);
return _URC_END_OF_STACK;
}
@@ -154,7 +154,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
_URC_CONTINUE_UNWIND) {
return _URC_END_OF_STACK;
}
-#endif // _LIBUNWIND_ARM_EHABI
+#endif // defined(_LIBUNWIND_ARM_EHABI)
// debugging
if (_LIBUNWIND_TRACING_UNWINDING) {
@@ -164,7 +164,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
unw_get_proc_name(&cursor, functionName, 512, &offset);
unw_get_proc_info(&cursor, &frame);
_LIBUNWIND_TRACE_UNWINDING(
- " _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n",
+ " _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p",
(long long)frame.start_ip, functionName, (long long)frame.lsda,
(void *)&cursor);
}
@@ -173,14 +173,14 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
result = (*callback)((struct _Unwind_Context *)(&cursor), ref);
if (result != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING(
- " _backtrace: ended because callback returned %d\n", result);
+ " _backtrace: ended because callback returned %d", result);
return result;
}
}
}
-/// Find dwarf unwind info for an address 'pc' in some function.
+/// Find DWARF unwind info for an address 'pc' in some function.
_LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
struct dwarf_eh_bases *bases) {
// This is slow, but works.
@@ -195,7 +195,7 @@ _LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
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\n", pc,
+ _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc,
(void *)(long) info.unwind_info);
return (void *)(long) info.unwind_info;
}
@@ -206,7 +206,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_word_t result;
unw_get_reg(cursor, UNW_REG_SP, &result);
- _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIx64 "\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIx64,
(void *)context, (uint64_t)result);
return (uintptr_t)result;
}
@@ -217,19 +217,19 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
/// site address. Normally IP is the return address.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) {
- _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)\n", (void *)context);
+ _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context);
*ipBefore = 0;
return _Unwind_GetIP(context);
}
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
/// Called by programs with dynamic code generators that want
/// to register a dynamically generated FDE.
/// This function has existed on Mac OS X since 10.4, but
/// was broken until 10.6.
_LIBUNWIND_EXPORT void __register_frame(const void *fde) {
- _LIBUNWIND_TRACE_API("__register_frame(%p)\n", fde);
+ _LIBUNWIND_TRACE_API("__register_frame(%p)", fde);
_unw_add_dynamic_fde((unw_word_t)(uintptr_t) fde);
}
@@ -239,7 +239,7 @@ _LIBUNWIND_EXPORT void __register_frame(const void *fde) {
/// This function has existed on Mac OS X since 10.4, but
/// was broken until 10.6.
_LIBUNWIND_EXPORT void __deregister_frame(const void *fde) {
- _LIBUNWIND_TRACE_API("__deregister_frame(%p)\n", fde);
+ _LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde);
_unw_remove_dynamic_fde((unw_word_t)(uintptr_t) fde);
}
@@ -252,14 +252,14 @@ _LIBUNWIND_EXPORT void __deregister_frame(const void *fde) {
// applications working. We also add the not in 10.6 symbol so that nwe
// application won't be able to use them.
-#if _LIBUNWIND_SUPPORT_FRAME_APIS
+#if defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
_LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob,
void *tb, void *db) {
(void)fde;
(void)ob;
(void)tb;
(void)db;
- _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)\n",
+ _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)",
fde, ob, tb, db);
// do nothing, this function never worked in Mac OS X
}
@@ -267,7 +267,7 @@ _LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob,
_LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) {
(void)fde;
(void)ob;
- _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)\n", fde, ob);
+ _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob);
// do nothing, this function never worked in Mac OS X
}
@@ -279,38 +279,38 @@ _LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde,
(void)tb;
(void)db;
_LIBUNWIND_TRACE_API("__register_frame_info_table_bases"
- "(%p,%p, %p, %p)\n", fde, ob, tb, db);
+ "(%p,%p, %p, %p)", fde, ob, tb, db);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) {
(void)fde;
(void)ob;
- _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)\n", fde, ob);
+ _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void __register_frame_table(const void *fde) {
(void)fde;
- _LIBUNWIND_TRACE_API("__register_frame_table(%p)\n", fde);
+ _LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde);
// do nothing, this function never worked in Mac OS X
}
_LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) {
(void)fde;
- _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)\n", fde);
+ _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde);
// do nothing, this function never worked in Mac OS X
return NULL;
}
_LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) {
(void)fde;
- _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)\n", fde);
+ _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde);
// do nothing, this function never worked in Mac OS X
return NULL;
}
-#endif // _LIBUNWIND_SUPPORT_FRAME_APIS
+#endif // defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
-#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS
+#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
diff --git a/src/UnwindLevel1.c b/src/UnwindLevel1.c
index ce6eb28..19116fa 100644
--- a/src/UnwindLevel1.c
+++ b/src/UnwindLevel1.c
@@ -30,27 +30,26 @@
#include "unwind.h"
#include "config.h"
-#if !_LIBUNWIND_ARM_EHABI
+#if !defined(_LIBUNWIND_ARM_EHABI)
static _Unwind_Reason_Code
-unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
- unw_cursor_t cursor1;
- unw_init_local(&cursor1, uc);
+unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
+ unw_init_local(cursor, uc);
// Walk each frame looking for a place to stop.
bool handlerNotFound = true;
while (handlerNotFound) {
- // Ask libuwind to get next frame (skip over first which is
+ // Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
- int stepResult = unw_step(&cursor1);
+ int stepResult = unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
+ "bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
- "_URC_FATAL_PHASE1_ERROR\n",
+ "_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
@@ -58,9 +57,9 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
// See if frame has code to run (has personality routine).
unw_proc_info_t frameInfo;
unw_word_t sp;
- if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
+ if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
+ "failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
@@ -70,15 +69,15 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
- if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf),
+ if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
unw_word_t pc;
- unw_get_reg(&cursor1, UNW_REG_IP, &pc);
+ unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64
- ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
+ ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "",
(void *)exception_object, pc, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
@@ -89,26 +88,26 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
__personality_routine p =
(__personality_routine)(long)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
+ "unwind_phase1(ex_ojb=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
- exception_object, (struct _Unwind_Context *)(&cursor1));
+ exception_object, (struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_HANDLER_FOUND:
// found a catch clause or locals that need destructing in this frame
// stop search and remember stack pointer at the frame
handlerNotFound = false;
- unw_get_reg(&cursor1, UNW_REG_SP, &sp);
+ unw_get_reg(cursor, UNW_REG_SP, &sp);
exception_object->private_2 = (uintptr_t)sp;
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
+ "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
(void *)exception_object);
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
+ "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
// continue unwinding
break;
@@ -116,7 +115,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
+ "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
@@ -127,27 +126,26 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
static _Unwind_Reason_Code
-unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
- unw_cursor_t cursor2;
- unw_init_local(&cursor2, uc);
+unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
+ unw_init_local(cursor, uc);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
(void *)exception_object);
// Walk each frame until we reach where search phase said to stop.
while (true) {
- // Ask libuwind to get next frame (skip over first which is
+ // Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
- int stepResult = unw_step(&cursor2);
+ int stepResult = unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
+ "bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
- "_URC_FATAL_PHASE1_ERROR\n",
+ "_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -155,10 +153,10 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
// Get info about this frame.
unw_word_t sp;
unw_proc_info_t frameInfo;
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
- if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
+ unw_get_reg(cursor, UNW_REG_SP, &sp);
+ if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
+ "failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -168,13 +166,13 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
- if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
+ if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64
", func=%s, sp=0x%" PRIx64 ", lsda=0x%" PRIx64
- ", personality=0x%" PRIx64 "\n",
+ ", personality=0x%" PRIx64,
(void *)exception_object, frameInfo.start_ip,
functionName, sp, frameInfo.lsda,
frameInfo.handler);
@@ -191,12 +189,12 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
}
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
- (struct _Unwind_Context *)(&cursor2));
+ (struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
// Continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
+ "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
if (sp == exception_object->private_2) {
// Phase 1 said we would stop at this frame, but we did not...
@@ -206,20 +204,20 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
+ "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
(void *)exception_object);
// Personality routine says to transfer control to landing pad.
// We may get control back if landing pad calls _Unwind_Resume().
if (_LIBUNWIND_TRACING_UNWINDING) {
unw_word_t pc;
- unw_get_reg(&cursor2, UNW_REG_IP, &pc);
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
+ unw_get_reg(cursor, UNW_REG_IP, &pc);
+ unw_get_reg(cursor, UNW_REG_SP, &sp);
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
"user code with ip=0x%" PRIx64
- ", sp=0x%" PRIx64 "\n",
+ ", sp=0x%" PRIx64,
(void *)exception_object, pc, sp);
}
- unw_resume(&cursor2);
+ unw_resume(cursor);
// unw_resume() only returns if there was an error.
return _URC_FATAL_PHASE2_ERROR;
default:
@@ -237,20 +235,19 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
}
static _Unwind_Reason_Code
-unwind_phase2_forced(unw_context_t *uc,
+unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
_Unwind_Exception *exception_object,
_Unwind_Stop_Fn stop, void *stop_parameter) {
- unw_cursor_t cursor2;
- unw_init_local(&cursor2, uc);
+ unw_init_local(cursor, uc);
// Walk each frame until we reach where search phase said to stop
- while (unw_step(&cursor2) > 0) {
+ while (unw_step(cursor) > 0) {
// Update info about this frame.
unw_proc_info_t frameInfo;
- if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
+ if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
- "failed => _URC_END_OF_STACK\n",
+ "failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -260,13 +257,13 @@ unwind_phase2_forced(unw_context_t *uc,
char functionBuf[512];
const char *functionName = functionBuf;
unw_word_t offset;
- if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
+ if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
- ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
+ ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
@@ -276,13 +273,13 @@ unwind_phase2_forced(unw_context_t *uc,
(_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);
+ (struct _Unwind_Context *)(cursor), stop_parameter);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
+ "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\n",
+ "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -292,32 +289,32 @@ unwind_phase2_forced(unw_context_t *uc,
__personality_routine p =
(__personality_routine)(long)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n",
+ "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));
+ (struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned "
- "_URC_CONTINUE_UNWIND\n",
+ "_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\n",
+ "_URC_INSTALL_CONTEXT",
(void *)exception_object);
// We may get control back if landing pad calls _Unwind_Resume().
- unw_resume(&cursor2);
+ unw_resume(cursor);
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\n",
+ "_URC_FATAL_PHASE2_ERROR",
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -327,12 +324,12 @@ unwind_phase2_forced(unw_context_t *uc,
// 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\n",
+ "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);
+ (struct _Unwind_Context *)(cursor), stop_parameter);
// Clean up phase did not resume at the frame that the search phase said it
// would.
@@ -343,9 +340,10 @@ unwind_phase2_forced(unw_context_t *uc,
/// Called by __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)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
(void *)exception_object);
unw_context_t uc;
+ unw_cursor_t cursor;
unw_getcontext(&uc);
// Mark that this is a non-forced unwind, so _Unwind_Resume()
@@ -354,12 +352,12 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
exception_object->private_2 = 0;
// phase 1: the search phase
- _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
+ _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
if (phase1 != _URC_NO_REASON)
return phase1;
// phase 2: the clean up phase
- return unwind_phase2(&uc, exception_object);
+ return unwind_phase2(&uc, &cursor, exception_object);
}
@@ -377,16 +375,17 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(_Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object);
+ _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
unw_context_t uc;
+ unw_cursor_t cursor;
unw_getcontext(&uc);
if (exception_object->private_1 != 0)
- unwind_phase2_forced(&uc, exception_object,
+ unwind_phase2_forced(&uc, &cursor, exception_object,
(_Unwind_Stop_Fn) exception_object->private_1,
(void *)exception_object->private_2);
else
- unwind_phase2(&uc, exception_object);
+ unwind_phase2(&uc, &cursor, exception_object);
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
@@ -400,9 +399,10 @@ _Unwind_Resume(_Unwind_Exception *exception_object) {
_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)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
(void *)exception_object, (void *)(uintptr_t)stop);
unw_context_t uc;
+ unw_cursor_t cursor;
unw_getcontext(&uc);
// Mark that this is a forced unwind, so _Unwind_Resume() can do
@@ -411,7 +411,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
exception_object->private_2 = (uintptr_t) stop_parameter;
// do it
- return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
+ return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
}
@@ -424,11 +424,11 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.lsda;
_LIBUNWIND_TRACE_API(
- "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR "\n",
+ "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
if (result != 0) {
if (*((uint8_t *)result) != 0xFF)
- _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF\n",
+ _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
result);
}
return result;
@@ -444,7 +444,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
uintptr_t result = 0;
if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
result = (uintptr_t)frameInfo.start_ip;
- _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR "\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
return result;
}
@@ -454,7 +454,7 @@ _Unwind_GetRegionStart(struct _Unwind_Context *context) {
// is caught.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
- _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
+ _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
(void *)exception_object);
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
@@ -467,7 +467,7 @@ _Unwind_GetGR(struct _Unwind_Context *context, int index) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_word_t result;
unw_get_reg(cursor, index, &result);
- _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64,
(void *)context, index, (uint64_t)result);
return (uintptr_t)result;
}
@@ -476,7 +476,7 @@ _Unwind_GetGR(struct _Unwind_Context *context, int index) {
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIx64
- ")\n",
+ ")",
(void *)context, index, (uint64_t)value);
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_set_reg(cursor, index, value);
@@ -487,7 +487,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_word_t result;
unw_get_reg(cursor, UNW_REG_IP, &result);
- _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n",
+ _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64,
(void *)context, (uint64_t)result);
return (uintptr_t)result;
}
@@ -497,10 +497,10 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
/// start executing in the landing pad.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n",
+ _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")",
(void *)context, (uint64_t)value);
unw_cursor_t *cursor = (unw_cursor_t *)context;
unw_set_reg(cursor, UNW_REG_IP, value);
}
-#endif // !_LIBUNWIND_ARM_EHABI
+#endif // !defined(_LIBUNWIND_ARM_EHABI)
diff --git a/src/UnwindRegistersRestore.S b/src/UnwindRegistersRestore.S
index 7d21953..408ba03 100644
--- a/src/UnwindRegistersRestore.S
+++ b/src/UnwindRegistersRestore.S
@@ -282,8 +282,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
ldp x22,x23, [x0, #0x0B0]
ldp x24,x25, [x0, #0x0C0]
ldp x26,x27, [x0, #0x0D0]
- ldp x28,fp, [x0, #0x0E0]
- ldr lr, [x0, #0x100] // restore pc into lr
+ ldp x28,x29, [x0, #0x0E0]
+ ldr x30, [x0, #0x100] // restore pc into lr
ldr x1, [x0, #0x0F8]
mov sp,x1 // restore sp
@@ -306,7 +306,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
ldr d31, [x0, #0x208]
ldp x0, x1, [x0, #0x000] // restore x0,x1
- ret lr // jump to pc
+ ret x30 // jump to pc
#elif defined(__arm__) && !defined(__APPLE__)
@@ -322,9 +322,18 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
@
.p2align 2
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv)
-#if !defined(__ARM_ARCH_ISA_ARM)
- ldr r2, [r0, #52]
- ldr r3, [r0, #60]
+#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
+ @ r8-r11: ldm into r1-r4, then mov to r8-r11
+ adds r0, #0x20
+ ldm r0!, {r1-r4}
+ subs r0, #0x30
+ mov r8, r1
+ mov r9, r2
+ mov r10, r3
+ mov r11, r4
+ @ r12 does not need loading, it it the intra-procedure-call scratch register
+ ldr r2, [r0, #0x34]
+ ldr r3, [r0, #0x3c]
mov sp, r2
mov lr, r3 @ restore pc into lr
ldm r0, {r0-r7}
@@ -383,6 +392,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
vldmia r0, {d16-d31}
JMP(lr)
+#if defined(__ARM_WMMX)
+
@
@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values)
@
@@ -390,8 +401,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
@ values pointer is in r0
@
.p2align 2
+ .arch armv5te
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
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
@@ -408,7 +419,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8
ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8
ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8
-#endif
JMP(lr)
@
@@ -418,13 +428,68 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
@ values pointer is in r0
@
.p2align 2
+ .arch armv5te
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4
ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4
ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4
ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4
-#endif
JMP(lr)
#endif
+
+#elif defined(__or1k__)
+
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
+#
+# void libunwind::Registers_or1k::jumpto()
+#
+# On entry:
+# thread_state pointer is in r3
+#
+
+ # restore integral registerrs
+ l.lwz r0, 0(r3)
+ l.lwz r1, 4(r3)
+ l.lwz r2, 8(r3)
+ # skip r3 for now
+ l.lwz r4, 16(r3)
+ l.lwz r5, 20(r3)
+ l.lwz r6, 24(r3)
+ l.lwz r7, 28(r3)
+ l.lwz r8, 32(r3)
+ l.lwz r9, 36(r3)
+ l.lwz r10, 40(r3)
+ l.lwz r11, 44(r3)
+ l.lwz r12, 48(r3)
+ l.lwz r13, 52(r3)
+ l.lwz r14, 56(r3)
+ l.lwz r15, 60(r3)
+ l.lwz r16, 64(r3)
+ l.lwz r17, 68(r3)
+ l.lwz r18, 72(r3)
+ l.lwz r19, 76(r3)
+ l.lwz r20, 80(r3)
+ l.lwz r21, 84(r3)
+ l.lwz r22, 88(r3)
+ l.lwz r23, 92(r3)
+ l.lwz r24, 96(r3)
+ l.lwz r25,100(r3)
+ l.lwz r26,104(r3)
+ l.lwz r27,108(r3)
+ l.lwz r28,112(r3)
+ l.lwz r29,116(r3)
+ l.lwz r30,120(r3)
+ l.lwz r31,124(r3)
+
+ # at last, restore r3
+ l.lwz r3, 12(r3)
+
+ # jump to pc
+ l.jr r9
+ l.nop
+
+#endif
+
+NO_EXEC_STACK_DIRECTIVE
+
diff --git a/src/UnwindRegistersSave.S b/src/UnwindRegistersSave.S
index fed295a..4860e8f 100644
--- a/src/UnwindRegistersSave.S
+++ b/src/UnwindRegistersSave.S
@@ -87,6 +87,15 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
xorl %eax, %eax # return UNW_ESUCCESS
ret
+# elif defined(__mips__)
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# Just trap for the time being.
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+ teq $0, $0
+
#elif defined(__ppc__)
;
@@ -254,11 +263,11 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
stp x22,x23, [x0, #0x0B0]
stp x24,x25, [x0, #0x0C0]
stp x26,x27, [x0, #0x0D0]
- stp x28,fp, [x0, #0x0E0]
- str lr, [x0, #0x0F0]
+ stp x28,x29, [x0, #0x0E0]
+ str x30, [x0, #0x0F0]
mov x1,sp
str x1, [x0, #0x0F8]
- str lr, [x0, #0x100] // store return address as pc
+ str x30, [x0, #0x100] // store return address as pc
// skip cpsr
stp d0, d1, [x0, #0x110]
stp d2, d3, [x0, #0x120]
@@ -300,13 +309,24 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
@
.p2align 2
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
-#if !defined(__ARM_ARCH_ISA_ARM)
- stm r0, {r0-r7}
+#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
+ stm r0!, {r0-r7}
+ mov r1, r8
+ mov r2, r9
+ mov r3, r10
+ stm r0!, {r1-r3}
+ mov r1, r11
mov r2, sp
mov r3, lr
- str r2, [r0, #52]
- str r3, [r0, #56]
- str r3, [r0, #60] @ store return address as pc
+ str r1, [r0, #0] @ r11
+ @ r12 does not need storing, it it the intra-procedure-call scratch register
+ str r2, [r0, #8] @ sp
+ str r3, [r0, #12] @ lr
+ str r3, [r0, #16] @ store return address as pc
+ @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
+ @ It is safe to use here though because we are about to return, and cpsr is
+ @ not expected to be preserved.
+ movs r0, #0 @ return UNW_ESUCCESS
#else
@ 32bit thumb-2 restrictions for stm:
@ . the sp (r13) cannot be in the list
@@ -315,13 +335,6 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
str sp, [r0, #52]
str lr, [r0, #56]
str lr, [r0, #60] @ store return address as pc
-#endif
-#if __ARM_ARCH_ISA_THUMB == 1
- @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
- @ It is safe to use here though because we are about to return, and cpsr is
- @ not expected to be preserved.
- movs r0, #0 @ return UNW_ESUCCESS
-#else
mov r0, #0 @ return UNW_ESUCCESS
#endif
JMP(lr)
@@ -369,6 +382,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
vstmia r0, {d16-d31}
JMP(lr)
+#if defined(_LIBUNWIND_ARM_WMMX)
+
@
@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
@
@@ -376,8 +391,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
@ values pointer is in r0
@
.p2align 2
+ .arch armv5te
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
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
@@ -394,7 +409,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
-#endif
JMP(lr)
@
@@ -404,13 +418,58 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
@ values pointer is in r0
@
.p2align 2
+ .arch armv5te
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4
-#endif
JMP(lr)
#endif
+
+#elif defined(__or1k__)
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+# thread_state pointer is in r3
+#
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+ l.sw 0(r3), r0
+ l.sw 4(r3), r1
+ l.sw 8(r3), r2
+ l.sw 12(r3), r3
+ l.sw 16(r3), r4
+ l.sw 20(r3), r5
+ l.sw 24(r3), r6
+ l.sw 28(r3), r7
+ l.sw 32(r3), r8
+ l.sw 36(r3), r9
+ l.sw 40(r3), r10
+ l.sw 44(r3), r11
+ l.sw 48(r3), r12
+ l.sw 52(r3), r13
+ l.sw 56(r3), r14
+ l.sw 60(r3), r15
+ l.sw 64(r3), r16
+ l.sw 68(r3), r17
+ l.sw 72(r3), r18
+ l.sw 76(r3), r19
+ l.sw 80(r3), r20
+ l.sw 84(r3), r21
+ l.sw 88(r3), r22
+ l.sw 92(r3), r23
+ l.sw 96(r3), r24
+ l.sw 100(r3), r25
+ l.sw 104(r3), r26
+ l.sw 108(r3), r27
+ l.sw 112(r3), r28
+ l.sw 116(r3), r29
+ l.sw 120(r3), r30
+ l.sw 124(r3), r31
+#endif
+
+NO_EXEC_STACK_DIRECTIVE
+
diff --git a/src/Unwind_AppleExtras.cpp b/src/Unwind_AppleExtras.cpp
index b8baef5..471059b 100644
--- a/src/Unwind_AppleExtras.cpp
+++ b/src/Unwind_AppleExtras.cpp
@@ -9,6 +9,7 @@
//===----------------------------------------------------------------------===//
#include "config.h"
+#include "AddressSpace.hpp"
#include "DwarfParser.hpp"
#include "unwind_ext.h"
@@ -76,7 +77,7 @@ struct libgcc_object_info {
#endif
-#if _LIBUNWIND_BUILD_ZERO_COST_APIS
+#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
//
// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
@@ -115,12 +116,12 @@ NEVER_HERE(__register_frame_table)
NEVER_HERE(__deregister_frame_info)
NEVER_HERE(__deregister_frame_info_bases)
-#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS
+#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
-#if _LIBUNWIND_BUILD_SJLJ_APIS
+#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
//
// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
// earlier versions
@@ -140,7 +141,7 @@ NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
-#endif // _LIBUNWIND_BUILD_SJLJ_APIS
+#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
namespace libunwind {
@@ -183,23 +184,31 @@ bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) {
}
-#if !defined(FOR_DYLD) && _LIBUNWIND_BUILD_SJLJ_APIS
+#if !defined(FOR_DYLD) && defined(_LIBUNWIND_BUILD_SJLJ_APIS)
-#include <System/pthread_machdep.h>
+#ifndef _LIBUNWIND_HAS_NO_THREADS
+ #include <System/pthread_machdep.h>
+#else
+ _Unwind_FunctionContext *fc_ = nullptr;
+#endif
// Accessors to get get/set linked list of frames for sjlj based execeptions.
_LIBUNWIND_HIDDEN
struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
+#ifndef _LIBUNWIND_HAS_NO_THREADS
return (struct _Unwind_FunctionContext *)
_pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
+#else
+ return fc_;
+#endif
}
_LIBUNWIND_HIDDEN
void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
+#ifndef _LIBUNWIND_HAS_NO_THREADS
_pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
+#else
+ fc_ = fc;
+#endif
}
#endif
-
-
-
-
diff --git a/src/assembly.h b/src/assembly.h
index f46a24d..9fb9905 100644
--- a/src/assembly.h
+++ b/src/assembly.h
@@ -35,19 +35,35 @@
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
#if defined(__APPLE__)
+
#define SYMBOL_IS_FUNC(name)
+#define NO_EXEC_STACK_DIRECTIVE
+
#elif defined(__ELF__)
+
#if defined(__arm__)
#define SYMBOL_IS_FUNC(name) .type name,%function
#else
#define SYMBOL_IS_FUNC(name) .type name,@function
#endif
+
+#if defined(__GNU__) || defined(__ANDROID__) || defined(__FreeBSD__) || \
+ defined(__Fuchsia__)
+#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
+#else
+#define NO_EXEC_STACK_DIRECTIVE
+#endif
+
#else
+
#define SYMBOL_IS_FUNC(name) \
.def name SEPARATOR \
.scl 2 SEPARATOR \
.type 32 SEPARATOR \
.endef
+
+#define NO_EXEC_STACK_DIRECTIVE
+
#endif
#define DEFINE_LIBUNWIND_FUNCTION(name) \
diff --git a/src/config.h b/src/config.h
index 9b24634..4be98c8 100644
--- a/src/config.h
+++ b/src/config.h
@@ -6,7 +6,7 @@
// Source Licenses. See LICENSE.TXT for details.
//
//
-// Defines macros used within libuwind project.
+// Defines macros used within libunwind project.
//
//===----------------------------------------------------------------------===//
@@ -16,6 +16,8 @@
#include <assert.h>
#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
// Define static_assert() unless already defined by compiler.
#ifndef __has_feature
@@ -29,99 +31,134 @@
// Platform specific configuration defines.
#ifdef __APPLE__
- #include <Availability.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- void __assert_rtn(const char *, const char *, int, const char *)
- __attribute__((noreturn));
- #ifdef __cplusplus
- }
- #endif
-
- #define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \
- defined(__x86_64__) || \
- defined(__arm64__))
- #define _LIBUNWIND_BUILD_SJLJ_APIS defined(__arm__)
- #define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \
- defined(__x86_64__))
- #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
- #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
- #define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
- #define _LIBUNWIND_ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg)
-
#if defined(FOR_DYLD)
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
+ #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
#else
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
+ #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
#endif
-
#else
- #include <stdlib.h>
+ #if defined(__ARM_DWARF_EH__) || !defined(__arm__)
+ #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+ #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
+ #endif
+#endif
+
+// FIXME: these macros are not correct for COFF targets
+#define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
+#define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
+
+#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
+#define _LIBUNWIND_BUILD_SJLJ_APIS
+#endif
- static inline void assert_rtn(const char* func, const char* file, int line, const char* msg) __attribute__ ((noreturn));
- static inline void assert_rtn(const char* func, const char* file, int line, const char* msg) {
- fprintf(stderr, "libunwind: %s %s:%d - %s\n", func, file, line, msg);
- assert(false);
- abort();
- }
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__)
+#define _LIBUNWIND_SUPPORT_FRAME_APIS
+#endif
- #define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \
- defined(__x86_64__) || \
- defined(__arm__) || \
- defined(__aarch64__))
- #define _LIBUNWIND_BUILD_SJLJ_APIS 0
- #define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \
- defined(__x86_64__))
- #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
- #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
- #define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
- #define _LIBUNWIND_ABORT(msg) assert_rtn(__func__, __FILE__, __LINE__, msg)
+#if defined(__i386__) || defined(__x86_64__) || \
+ defined(__ppc__) || defined(__ppc64__) || \
+ (!defined(__APPLE__) && defined(__arm__)) || \
+ (defined(__arm64__) || defined(__aarch64__)) || \
+ (defined(__APPLE__) && defined(__mips__))
+#define _LIBUNWIND_BUILD_ZERO_COST_APIS
+#endif
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND !defined(__arm__) || \
- defined(__ARM_DWARF_EH__)
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
+#define _LIBUNWIND_ABORT(msg) \
+ do { \
+ abort(); \
+ } while (0)
+#else
+#define _LIBUNWIND_ABORT(msg) \
+ do { \
+ fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \
+ __LINE__, msg); \
+ fflush(stderr); \
+ abort(); \
+ } while (0)
#endif
+#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
+#define _LIBUNWIND_LOG(msg, ...)
+#else
+#define _LIBUNWIND_LOG(msg, ...) \
+ fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
+#endif
+
+#if defined(_LIBUNWIND_HAS_NO_THREADS)
+ // only used with pthread calls, not needed for the single-threaded builds
+ #define _LIBUNWIND_LOG_NON_ZERO(x)
+#else
+ #if defined(NDEBUG)
+ #define _LIBUNWIND_LOG_NON_ZERO(x) x
+ #else
+ #define _LIBUNWIND_LOG_NON_ZERO(x) \
+ do { \
+ int _err = x; \
+ if (_err != 0) \
+ _LIBUNWIND_LOG("" #x "=%d in %s", _err, __FUNCTION__); \
+ } while (0)
+ #endif
+#endif
// Macros that define away in non-Debug builds
#ifdef NDEBUG
#define _LIBUNWIND_DEBUG_LOG(msg, ...)
#define _LIBUNWIND_TRACE_API(msg, ...)
- #define _LIBUNWIND_TRACING_UNWINDING 0
+ #define _LIBUNWIND_TRACING_UNWINDING (0)
+ #define _LIBUNWIND_TRACING_DWARF (0)
#define _LIBUNWIND_TRACE_UNWINDING(msg, ...)
- #define _LIBUNWIND_LOG_NON_ZERO(x) x
+ #define _LIBUNWIND_TRACE_DWARF(...)
#else
#ifdef __cplusplus
extern "C" {
#endif
extern bool logAPIs();
extern bool logUnwinding();
+ extern bool logDWARF();
#ifdef __cplusplus
}
#endif
#define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__)
- #define _LIBUNWIND_LOG_NON_ZERO(x) \
- do { \
- int _err = x; \
- if ( _err != 0 ) \
- _LIBUNWIND_LOG("" #x "=%d in %s", _err, __FUNCTION__); \
- } while (0)
- #define _LIBUNWIND_TRACE_API(msg, ...) \
- do { \
- if ( logAPIs() ) _LIBUNWIND_LOG(msg, __VA_ARGS__); \
- } while(0)
- #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \
- do { \
- if ( logUnwinding() ) _LIBUNWIND_LOG(msg, __VA_ARGS__); \
- } while(0)
+ #define _LIBUNWIND_TRACE_API(msg, ...) \
+ do { \
+ if (logAPIs()) \
+ _LIBUNWIND_LOG(msg, __VA_ARGS__); \
+ } while (0)
#define _LIBUNWIND_TRACING_UNWINDING logUnwinding()
+ #define _LIBUNWIND_TRACING_DWARF logDWARF()
+ #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \
+ do { \
+ if (logUnwinding()) \
+ _LIBUNWIND_LOG(msg, __VA_ARGS__); \
+ } while (0)
+ #define _LIBUNWIND_TRACE_DWARF(...) \
+ do { \
+ if (logDWARF()) \
+ fprintf(stderr, __VA_ARGS__); \
+ } while (0)
#endif
+#ifdef __cplusplus
+// Used to fit UnwindCursor and Registers_xxx types against unw_context_t /
+// unw_cursor_t sized memory blocks.
+#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
+# define COMP_OP ==
+#else
+# define COMP_OP <
+#endif
+template <typename _Type, typename _Mem>
+struct check_fit {
+ template <typename T>
+ struct blk_count {
+ static const size_t count =
+ (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
+ };
+ static const bool does_fit =
+ (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count);
+};
+#undef COMP_OP
+#endif // __cplusplus
#endif // LIBUNWIND_CONFIG_H
diff --git a/src/libunwind.cpp b/src/libunwind.cpp
index c408e06..f072d55 100644
--- a/src/libunwind.cpp
+++ b/src/libunwind.cpp
@@ -1,4 +1,4 @@
-//===--------------------------- libuwind.cpp -----------------------------===//
+//===--------------------------- libunwind.cpp ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,9 +16,6 @@
#include <cstdlib> // getenv
#endif
#include <new>
-#include <tuple>
-#include <memory>
-#include <vector>
#include <algorithm>
#include "libunwind_ext.h"
@@ -27,6 +24,7 @@
#include <stdlib.h>
+#include "AddressSpace.hpp"
#include "UnwindCursor.hpp"
using namespace libunwind;
@@ -45,28 +43,30 @@ extern int unw_getcontext(unw_context_t *);
/// unw_getcontext().
_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
unw_context_t *context) {
- _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)",
static_cast<void *>(cursor),
static_cast<void *>(context));
- // Use "placement new" to allocate UnwindCursor in the cursor buffer.
#if defined(__i386__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>(
- context, LocalAddressSpace::sThisAddressSpace);
+# define REGISTER_KIND Registers_x86
#elif defined(__x86_64__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
- context, LocalAddressSpace::sThisAddressSpace);
+# define REGISTER_KIND Registers_x86_64
#elif defined(__ppc__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif defined(__arm64__) || defined(__aarch64__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif _LIBUNWIND_ARM_EHABI
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
- context, LocalAddressSpace::sThisAddressSpace);
+# define REGISTER_KIND Registers_ppc
+#elif defined(__aarch64__)
+# define REGISTER_KIND Registers_arm64
+#elif defined(_LIBUNWIND_ARM_EHABI)
+# define REGISTER_KIND Registers_arm
+#elif defined(__or1k__)
+# define REGISTER_KIND Registers_or1k
+#elif defined(__mips__)
+# warning The MIPS architecture is not supported.
#else
-#error Architecture not supported
+# 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);
+#undef REGISTER_KIND
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->setInfoBasedOnIPRegister();
@@ -86,18 +86,18 @@ _LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
switch (as->cpuType) {
case CPU_TYPE_I386:
new ((void *)cursor)
- UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >,
+ UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
break;
case CPU_TYPE_X86_64:
- new ((void *)cursor) UnwindCursor<
- OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(
- ((unw_addr_space_x86_64 *)as)->oas, arg);
+ 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<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>(
- ((unw_addr_space_ppc *)as)->oas, arg);
+ UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
+ Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
break;
default:
return UNW_EUNSPEC;
@@ -158,7 +158,7 @@ _LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
/// 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) {
- _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
static_cast<void *>(cursor), regNum,
static_cast<void *>(value));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@@ -173,7 +173,7 @@ _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
/// Set value of specified register at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_word_t value) {
- _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n",
+ _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)",
static_cast<void *>(cursor), regNum, (long long)value);
typedef LocalAddressSpace::pint_t pint_t;
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@@ -192,7 +192,7 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
/// Get value of specified float register at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_fpreg_t *value) {
- _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
static_cast<void *>(cursor), regNum,
static_cast<void *>(value));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@@ -207,11 +207,11 @@ _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
/// Set value of specified float register at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
unw_fpreg_t value) {
-#if _LIBUNWIND_ARM_EHABI
- _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n",
+#if defined(_LIBUNWIND_ARM_EHABI)
+ _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
static_cast<void *>(cursor), regNum, value);
#else
- _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n",
+ _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
static_cast<void *>(cursor), regNum, value);
#endif
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@@ -225,7 +225,7 @@ _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
/// Move cursor to next frame.
_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
- _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast<void *>(cursor));
+ _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->step();
}
@@ -234,7 +234,7 @@ _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
/// Get unwind info at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
unw_proc_info_t *info) {
- _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)",
static_cast<void *>(cursor), static_cast<void *>(info));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->getInfo(info);
@@ -247,7 +247,7 @@ _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
/// Resume execution at cursor position (aka longjump).
_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
- _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast<void *>(cursor));
+ _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
co->jumpto();
return UNW_EUNSPEC;
@@ -257,7 +257,7 @@ _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
/// Get name of function at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
size_t bufLen, unw_word_t *offset) {
- _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n",
+ _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
static_cast<void *>(cursor), static_cast<void *>(buf),
static_cast<unsigned long>(bufLen));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
@@ -270,7 +270,7 @@ _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
/// Checks if a register is a floating-point register.
_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
- _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n",
+ _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)",
static_cast<void *>(cursor), regNum);
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->validFloatReg(regNum);
@@ -280,7 +280,7 @@ _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
/// Checks if a register is a floating-point register.
_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
unw_regnum_t regNum) {
- _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n",
+ _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)",
static_cast<void *>(cursor), regNum);
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->getRegisterName(regNum);
@@ -289,7 +289,7 @@ _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
/// Checks if current frame is signal trampoline.
_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
- _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)",
static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->isSignalFrame();
@@ -298,7 +298,7 @@ _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
#ifdef __arm__
// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
- _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)",
static_cast<void *>(cursor));
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
return co->saveVFPAsX();
@@ -306,11 +306,11 @@ _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
#endif
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
-/// SPI: walks cached dwarf entries
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+/// SPI: walks cached DWARF entries
_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
- _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n",
+ _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)",
reinterpret_cast<void *>(func));
DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
}
@@ -340,7 +340,7 @@ void _unw_remove_dynamic_fde(unw_word_t fde) {
// fde is own mh_group
DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
}
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
+#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -372,5 +372,17 @@ bool logUnwinding() {
return log;
}
+_LIBUNWIND_HIDDEN
+bool logDWARF() {
+ // do manual lock to avoid use of _cxa_guard_acquire or initializers
+ static bool checked = false;
+ static bool log = false;
+ if (!checked) {
+ log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL);
+ checked = true;
+ }
+ return log;
+}
+
#endif // NDEBUG
diff --git a/src/libunwind_ext.h b/src/libunwind_ext.h
index 72dbf58..ec645a8 100644
--- a/src/libunwind_ext.h
+++ b/src/libunwind_ext.h
@@ -33,7 +33,7 @@ extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start,
extern void _unw_add_dynamic_fde(unw_word_t fde);
extern void _unw_remove_dynamic_fde(unw_word_t fde);
-#if _LIBUNWIND_ARM_EHABI
+#if defined(_LIBUNWIND_ARM_EHABI)
extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
const uint32_t *data,
diff --git a/test/alignment.pass.cpp b/test/alignment.pass.cpp
new file mode 100644
index 0000000..5ab5584
--- /dev/null
+++ b/test/alignment.pass.cpp
@@ -0,0 +1,21 @@
+// -*- 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.
+//
+//===----------------------------------------------------------------------===//
+
+// The Itanium ABI requires that _Unwind_Exception objects are "double-word
+// aligned".
+
+#include <unwind.h>
+
+struct MaxAligned {} __attribute__((aligned));
+static_assert(alignof(_Unwind_Exception) == alignof(MaxAligned), "");
+
+int main()
+{
+}